package ActivityOptionsICS;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.View;
import android.view.WindowManager;

import ActivityOptionsICS.util.Position;

public class ActivityOptionsCompatICS {
	
	/**
	 * 传递的结果码,用来判断
	 */
	public final static int RESULT_CODE = 1314;
	
	/**
	 * 结果码的KEY
	 */
	public static String KEY_RESULT_CODE = "kale:resultCode";
	
    /**
     * Type of animation that arguments specify.
     * 设置动画的类型,在启动activity时用到
     * @hide
     */
    public static final String KEY_ANIM_TYPE = "kale:animType";
    
    /**
     * Custom enter animation resource ID.
     * 进入动画的id
     */
    public static final String KEY_ANIM_ENTER_RES_ID = "kale:animEnterRes";

    /**
     * Custom exit animation resource ID.
     * 退出动画的id
     */
    public static final String KEY_ANIM_EXIT_RES_ID = "kale:animExitRes";

    /**
     * Bitmap for thumbnail animation.
     * 进行拉伸效果的bitmap
     */
    public static final String KEY_ANIM_THUMBNAIL = "kale:animThumbnail";
    
    /**
     * Start X position of thumbnail animation.
     * 设置view开始的X坐标,用于绘制控件的原始位置
     */
    public static final String KEY_ANIM_START_X = "kale:animStartX";
    
    /**
     * Start Y position of thumbnail animation.
     * 设置view开始的Y坐标,用于绘制控件的原始位置
     */
    public static final String KEY_ANIM_START_Y = "kale:animStartY";
    
    /**
     * Initial width of the animation.
     * 设置view开始的的宽度,用户绘制控件的原始宽度
     */
    public static final String KEY_ANIM_WIDTH = "kale:animWidth";
    
    /**
     * Initial height of the animation.
     * 设置view开始的高度,用于绘制控件开始的高度
     */
    public static final String KEY_ANIM_HEIGHT = "kale:animHeight";

    /**
     * 判断现在view是否在屏幕上显示
     */
    public static final String KEY_IS_IN_THE_SCREEN = "kale:isInTheScreen";
    
    /**
     * 判断当前屏幕是否是全屏
     */
    public static final String KEY_IS_START_FULL_SCREEN = "kale:isFullScreen";
    
    /**
     * 判断当前屏幕是否是竖屏
     */
    public static final String KEY_IS_VERTICAL_SCREEN = "kale:isVerticalScreen";
    
	/**
	 * 分享元素的id list
	 */
	public static String kEY_SHARED_ELEMENT_ID_LIST = "kale:sharedElementIdList";
	
	/**
	 * 分享元素显示区域的Rect list
	 */
	public static String kEY_SHARED_ELEMENT_BOUNDS_LIST = "kale:sharedElementBoundsList";
	
	/**
	 * 分享元素显示区域的Rect list
	 */
	public static String kEY_IS_IN_THE_SCREEN_ARR= "kale:isInTheScreenArr";
    
    /** 
     * 没有动画 
     */
    public static final int ANIM_NONE = 0;
    
    /** 
     * 自定义动画:makeCustomAnimation	
     */
    public static final int ANIM_CUSTOM = 1;
    
    /** 
     * 拉伸动画:makeScaleUpAnimation	
     */
    public static final int ANIM_SCALE_UP = 2;
    
    /** 
     * Bitmap的动画效果,从bitmap渐变到activity
     */
    public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
    
    /** 
     * 屏幕动画效果:makeSceneTransitionAnimation	
     */
    public static final int ANIM_SCENE_TRANSITION = 5;

    /**
     * 默认的动画效果,等于没进行设置
     */
    public static final int ANIM_DEFAULT = 6;
    
    private int mAnimationType = ANIM_NONE;
    private int mCustomEnterResId;
    private int mCustomExitResId;
    private Bitmap mThumbnail;
    
    private int mStartX;
    private int mStartY;
    private int mWidth;
    private int mHeight;
    // 分享元素的id list
    private ArrayList<Integer> mSharedElementIds;
    // 分享元素的绘制区域
    private ArrayList<Rect> mSharedElementBounds;
    // 分享元素是否在屏幕上的boolean数组
    private boolean[] mIsInTheScreenArr;
    // 当前是否是竖屏
    private boolean mIsVerticalScreen;
    // 当前是否是全屏
    private boolean mIsStartFullScreen;
    // 当前view是否在屏幕上
    private boolean mIsInTheScreen;

    
    /**
     * Create an ActivityOptions specifying a custom animation to run when
     * the activity is displayed.
     *
     * @param context Who is defining this.  This is the application that the
     * animation resources will be loaded from.
     * @param enterResId A resource ID of the animation resource to use for
     * the incoming activity.  Use 0 for no animation.
     * @param exitResId A resource ID of the animation resource to use for
     * the outgoing activity.  Use 0 for no animation.
     * @return Returns a new ActivityOptions object that you can use to
     * supply these options as the options Bundle when starting an activity.
     */
    public static ActivityOptionsCompatICS makeCustomAnimation(Context context,
    		int enterResId, int exitResId) {
    	
    	ActivityOptionsCompatICS opts = new ActivityOptionsCompatICS();
    	// 设置动画类型和动画资源的id
    	opts.mAnimationType = ANIM_CUSTOM;
        opts.mCustomEnterResId = enterResId;
        opts.mCustomExitResId = exitResId;
        return opts;
    }
    
    /**
     * @param source:新activity开始动画的view,通过startX,startY来定义区域
	 * @param startX:动画开始的X坐标,相对于source左上角的X坐标
	 * @param startY:动画开始的Y坐标,相对于source左上角的Y坐标
	 * @param width:新activity的起始宽度
	 * @param height:新activity的起始高度
	 * 
     * Create an ActivityOptions specifying an animation where the new activity is
     * scaled from a small originating area of the screen to its final full
     * representation.
     * <p/>
     * If the Intent this is being used with has not set its
     * {@link android.content.Intent#setSourceBounds(android.graphics.Rect)},
     * those bounds will be filled in for you based on the initial bounds passed
     * in here.
     *
     * @param source The View that the new activity is animating from. This
     * defines the coordinate space for startX and startY.
     * @param startX The x starting location of the new activity, relative to
     * source.
     * @param startY The y starting location of the activity, relative to source.
     * @param startWidth The initial width of the new activity.
     * @param startHeight The initial height of the new activity.
     * @return Returns a new ActivityOptions object that you can use to supply
     * these options as the options Bundle when starting an activity.
     * 
     */
	public static ActivityOptionsCompatICS makeScaleUpAnimation(View source,
			int startX, int startY, int width, int height) {
		Activity activity = (Activity) source.getContext();
		ActivityOptionsCompatICS opts = new ActivityOptionsCompatICS();
		// 设置动画类型
		opts.mAnimationType = ANIM_SCALE_UP;
		// 判断当前是否是竖屏
		opts.mIsVerticalScreen = isVerticalScreen(activity);
		// 判断view是否在屏幕上,如果在就执行动画,否则不执行动画
		opts.mIsInTheScreen = isInScreen(activity, source);
		
		int[] pts = new int[2];//ps = position,目的得到当前view相对于屏幕的坐标
	    source.getLocationOnScreen(pts);
		// 设置起始坐标和起始宽高
		opts.mStartX = pts[0] + startX;
		opts.mStartY = pts[1] + startY;
		opts.mWidth = width;
		opts.mHeight = height;
		
		return opts;
	}

	
	/**
     * @param source:view
     * @param thumbnail:开始渐变效果的bitmap
     * @param startX:动画开始的X坐标,相对于source
     * @param startY:动画开始的Y坐标,相对于source
     * 
     * Create an ActivityOptions specifying an animation where a thumbnail
     * is scaled from a given position to the new activity window that is
     * being started.
     *
     * <p>If the Intent this is being used with has not set its
     * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
     * those bounds will be filled in for you based on the initial
     * thumbnail location and size provided here.
     *
     * @param source The View that this thumbnail is animating from.  This
     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
     * @param thumbnail The bitmap that will be shown as the initial thumbnail
     * of the animation.
     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
     * @return Returns a new ActivityOptions object that you can use to
     * supply these options as the options Bundle when starting an activity.
     * 
     */
    public static ActivityOptionsCompatICS makeThumbnailScaleUpAnimation(View source,
            Bitmap thumbnail, int startX, int startY) {
    	Activity activity = (Activity) source.getContext();
    	ActivityOptionsCompatICS opts = new ActivityOptionsCompatICS();
        opts.mAnimationType = ANIM_THUMBNAIL_SCALE_UP;
        opts.mThumbnail = thumbnail;
        // 判断当前是否是竖屏
     	opts.mIsVerticalScreen = isVerticalScreen(activity);
     	// 判断当前activity是否是全屏模式
     	opts.mIsStartFullScreen = isFullScreen(activity);
     	// 判断view是否在屏幕上,如果在就执行动画,否则不执行动画
     	opts.mIsInTheScreen = isInScreen(activity, source);
     		
        int[] pts = new int[2];
        source.getLocationOnScreen(pts);
        opts.mStartX = pts[0] + startX;
        opts.mStartY = pts[1] + startY;
        opts.mWidth = thumbnail.getWidth();
        opts.mHeight = thumbnail.getHeight();
        return opts;
    }
	
	/**
	 * 这个方法必须放在view加载完后再执行,否则获取不到view的宽度和坐标
	 * @param activity:执行动画的activity
	 * @param sharedElement:执行动画的元素
	 * @param sharedElementId:新的activity中要接收动画效果的元素的id,这样就得到了两个view之间的联系
	 * 通过两点一线的方式来进行补间动画。
	 * 
     * Create an ActivityOptions to transition between Activities using cross-Activity scene
     * animations. This method carries the position of one shared element to the started Activity.
     * The position of <code>sharedElement</code> will be used as the epicenter for the
     * exit Transition. The position of the shared element in the launched Activity will be the
     * epicenter of its entering Transition.
     *
     * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
     * enabled on the calling Activity to cause an exit transition. The same must be in
     * the called Activity to get an entering transition.</p>
     * @param activity The Activity whose window contains the shared elements.
     * @param sharedElement The View to transition to the started Activity.
     * @param sharedElementId The shared element id as used in the target Activity. This
     *                          must not be null.
     * @return Returns a new ActivityOptions object that you can use to
     *         supply these options as the options Bundle when starting an activity.
     * @see android.transition.Transition#setEpicenterCallback(
     *          android.transition.Transition.EpicenterCallback)
     *          
     */
	@SuppressWarnings("unchecked")
	public static ActivityOptionsCompatICS makeSceneTransitionAnimation(Activity activity, 
			final View sharedElement,int sharedElementId) {
		return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementId));
	}
	
	
	/**
	 * 这个方法必须放在view加载完后再执行,否则获取不到view的宽度和坐标
	 * @param activity:执行动画的activity
	 * @param sharedElement:执行动画的元素
	 * @param sharedElementId:新的activity中要接收动画效果的元素的id,这样就得到了两个view之间的联系
	 * 通过两点一线的方式来进行补间动画。
	 * 
     * 传入多个view——id对,将这些信息传递到新的activity中。
	 * 这里的Rect实现了Parcelable接口,所以可以直接传递
	 * 
     * Create an ActivityOptions to transition between Activities using cross-Activity scene
     * animations. This method carries the position of multiple shared elements to the started
     * Activity. The position of the first element in sharedElements
     * will be used as the epicenter for the exit Transition. The position of the associated
     * shared element in the launched Activity will be the epicenter of its entering Transition.
     *
     * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
     * enabled on the calling Activity to cause an exit transition. The same must be in
     * the called Activity to get an entering transition.</p>
     * @param activity The Activity whose window contains the shared elements.
     * @param sharedElements The names of the shared elements to transfer to the called
     *                       Activity and their associated Views. The Views must each have
     *                       a unique shared element name.
     * @return Returns a new ActivityOptions object that you can use to
     *         supply these options as the options Bundle when starting an activity.
     * @see android.transition.Transition#setEpicenterCallback(
     *          android.transition.Transition.EpicenterCallback)
     *          
     */
	public static ActivityOptionsCompatICS makeSceneTransitionAnimation(Activity activity,
            Pair<View, Integer>... sharedElements) {
		
		ActivityOptionsCompatICS opts = new ActivityOptionsCompatICS();
		// 设置动画的类型
		opts.mAnimationType = ANIM_SCENE_TRANSITION;
		// 判断当前是否是竖屏
		opts.mIsVerticalScreen = isVerticalScreen(activity);
		// 判断当前activity是否是全屏模式
		opts.mIsStartFullScreen = isFullScreen(activity);
		// init
		opts.mSharedElementIds = new ArrayList<Integer>();
		opts.mSharedElementBounds = new ArrayList<Rect>();
		
		if (sharedElements != null) {
			opts.mIsInTheScreenArr = new boolean[sharedElements.length];
		}else {
			throw new RuntimeException("Shared Elements... must not be null");
		}
		
		//得到view+id的list,一个个取出来
        for (int i = 0; i < sharedElements.length; i++) {
        	//sharedElement是单个的一个元素对
            Pair<View, Integer> sharedElement = sharedElements[i];
            Integer sharedElementId = sharedElement.second;
            
            View view = sharedElement.first;
            if (view == null) {
                throw new IllegalArgumentException("Shared element must not be null");
            }
            opts.mSharedElementIds.add(sharedElementId);
            Rect bounds = getBounds(view);
            opts.mSharedElementBounds.add(bounds);
            opts.mIsInTheScreenArr[i] =	isInScreen(activity, view);
        }
		return opts;
	}

	/**
	 * 将各种坐标和参数放入bundle中传递
	 * 
     * Returns the created options as a Bundle, which can be passed to
     * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
     * Context.startActivity(Intent, Bundle)} and related methods.
     * Note that the returned Bundle is still owned by the ActivityOptions
     * object; you must not modify it, but can supply it to the startActivity
     * methods that take an options Bundle.
     */
	public Bundle toBundle() {
		if (mAnimationType == ANIM_DEFAULT) {
            return null;
        }
		Bundle bundle = new Bundle();
        bundle.putInt(KEY_ANIM_TYPE, mAnimationType);
        switch (mAnimationType) {
        
            case ANIM_CUSTOM:
            	bundle.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
                bundle.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
                break;
                
            case ANIM_SCALE_UP:
        		bundle.putBoolean(KEY_IS_VERTICAL_SCREEN, mIsVerticalScreen);
        		bundle.putBoolean(KEY_IS_IN_THE_SCREEN, mIsInTheScreen);
        		
        		bundle.putInt(KEY_ANIM_WIDTH, mWidth);
        		bundle.putInt(KEY_ANIM_HEIGHT, mHeight);
        		bundle.putInt(KEY_ANIM_START_X, mStartX);
        		bundle.putInt(KEY_ANIM_START_Y, mStartY);
                break;
                
            case ANIM_THUMBNAIL_SCALE_UP:
            	bundle.putBoolean(KEY_IS_START_FULL_SCREEN, mIsStartFullScreen);
            	bundle.putBoolean(KEY_IS_VERTICAL_SCREEN, mIsVerticalScreen);
        		bundle.putBoolean(KEY_IS_IN_THE_SCREEN, mIsInTheScreen);
                bundle.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
                bundle.putInt(KEY_ANIM_START_X, mStartX);
                bundle.putInt(KEY_ANIM_START_Y, mStartY);
                bundle.putInt(KEY_ANIM_WIDTH, mWidth);
                bundle.putInt(KEY_ANIM_HEIGHT, mHeight);
                break;
                
            case ANIM_SCENE_TRANSITION:
        		bundle.putBoolean(KEY_IS_VERTICAL_SCREEN, mIsVerticalScreen);
        		bundle.putBoolean(KEY_IS_START_FULL_SCREEN, mIsStartFullScreen);
        		
        		bundle.putBooleanArray(kEY_IS_IN_THE_SCREEN_ARR, mIsInTheScreenArr);
        		bundle.putIntegerArrayList(kEY_SHARED_ELEMENT_ID_LIST, mSharedElementIds);
        		bundle.putParcelableArrayList(kEY_SHARED_ELEMENT_BOUNDS_LIST, mSharedElementBounds);
                break;
        }

		return bundle;
	}

	
	/**
	 * view当前是否显示在屏幕上,包括被遮挡,显示不全的状态
	 * @param activity
	 * @param rect
	 * @return
	 */
	public static boolean isInScreen(Activity activity, View view) {
		Rect bounds = new Rect();
		//只要有一部分显示在屏幕内,就是true,不考虑遮挡情况
		boolean isInScreen = view.getGlobalVisibleRect(bounds);
		if (isInScreen) {
			if (bounds.width() < view.getWidth() * 0.3f || bounds.height() < view.getHeight() * 0.3f) {
				return false;
			}else {
				return true;
			}
		}else {
			return false;
		}
	}

	/**
	 * @param view
	 * @return 目标view的实际大小和实际的显示坐标
	 */
	public static Rect getBounds(View view) {
		Rect bounds = new Rect();
		//view.getGlobalVisibleRect(bounds);
		bounds.set(Position.getGlobalVisibleRect(view));
		return bounds;
	}

	/**
	 * @param activity
	 * @return 屏幕的宽度
	 */
	public static int getScreenWidth(Activity activity) {
		DisplayMetrics dm = new DisplayMetrics();
		activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
		return dm.widthPixels;//宽度
	}
	
	/**
	 * @param activity
	 * @return 屏幕的高度
	 */
	public static int getScreenHeight(Activity activity) {
		DisplayMetrics dm = new DisplayMetrics();
		activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
		return dm.heightPixels ;//高度
	}

	/**
	 * @param activity
	 * @return 判断当前手机是否是全屏
	 */
	public static boolean isFullScreen(Activity activity) {
		int flag = activity.getWindow().getAttributes().flags;  
        if((flag & WindowManager.LayoutParams.FLAG_FULLSCREEN) 
        		== WindowManager.LayoutParams.FLAG_FULLSCREEN) {
        	return true;
        }else {
			return false;
		}
	}
	
	/**
	 * 判断当前屏幕是否是横屏
	 * @param activity
	 * @return
	 */
	public static boolean isVerticalScreen(Activity activity) {
		int flag = activity.getResources().getConfiguration().orientation;
		if (flag == 0) {
			return false;
		}else {
			return true;
		}
	}
	
	/**
	 * @param activity
	 * @param isActivity
	 * @return 得到actionbar的高度,这个必须在view绘制完成后才能的到值,否则返回0
	 */
/*	public static int getActionBarHeight(Activity activity,boolean isActivity) {
		if (isActivity) {
			if (activity.getActionBar() != null) {
				return activity.getActionBar().getHeight();
			}
		}else {
			if (((ActionBarActivity)activity).getSupportActionBar() != null) {
				return ((ActionBarActivity)activity).getSupportActionBar().getHeight();
			}
		}
		return 0;
	}
	*/
	/** 
     * 获取状态栏高度 
     *  
     * @return 
     */ 
    public static int getStatusBarHeight(Context context) {  
        Class<?> c = null;  
        Object obj = null;  
        java.lang.reflect.Field field = null;  
        int x = 0;  
        int statusBarHeight = 0;  
        try {  
            c = Class.forName("com.android.internal.R$dimen");  
            obj = c.newInstance();  
            field = c.getField("status_bar_height");  
            x = Integer.parseInt(field.get(obj).toString());  
            statusBarHeight = context.getResources().getDimensionPixelSize(x);  
            return statusBarHeight;  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return statusBarHeight;  
    }



}