package com.sebastianrask.bettersubscription.activities.setup;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import androidx.core.app.ActivityCompat;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.sebastianrask.bettersubscription.R;
import com.sebastianrask.bettersubscription.activities.UsageTrackingAppCompatActivity;
import com.sebastianrask.bettersubscription.service.Service;

import io.codetail.animation.SupportAnimator;
import io.codetail.animation.ViewAnimationUtils;


public class WelcomeActivity extends UsageTrackingAppCompatActivity {
	private String LOG_TAG = getClass().getSimpleName();
	private boolean hasTransitioned = false;
	private SupportAnimator transitionAnimationWhite = null;
	private SupportAnimator transitionAnimationBlue = null;


	final int REVEAL_ANIMATION_DURATION 		= 650;
	final int REVEAL_ANIMATION_DELAY_DURATION 	= 200;
	final int ANIMATIONS_START_DELAY 			= 500;
	final int LOGO_ANIMATION_DURATION 			= 1000;
	final int LOGO_Container_ANIMATION_DURATION = 1750;
	final int WELCOME_TEXT_ANIMATION_DURATION 	= 900;
	final int WELCOME_TEXT_ANIMATION_BASE_DELAY = 175;
	final int CONTINUE_FAB_ANIMATION_DURATION 	= 750;

	private RelativeLayout 	mWelcomeText;
	private TextView 		mWelcomeTextLineOne,
							mWelcomeTextLineTwo,
							mWelcomeTextLineThree;
	private ImageView 		mLogo,
							mContinueIcon;
	private View 			mLogoCenter,
							mContinueFAB,
							mContinueFABShadow,
							mTransitionViewWhite,
							mTransitionViewBlue;
	private FrameLayout		mLogoContainer;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_welcome);
		trackEvent(R.string.category_read, R.string.action_welcome);

		mWelcomeText 			= (RelativeLayout) findViewById(R.id.welcome_text);
		mWelcomeTextLineOne 	= (TextView) findViewById(R.id.welcome_text_line_one);
		mWelcomeTextLineTwo 	= (TextView) findViewById(R.id.welcome_text_line_two);
		mWelcomeTextLineThree 	= (TextView) findViewById(R.id.welcome_text_line_three);

		mLogo 					= (ImageView) findViewById(R.id.welcome_icon);
		mContinueIcon 			= (ImageView) findViewById(R.id.forward_arrow);
		mLogoContainer 			= (FrameLayout) findViewById(R.id.welcome_icon_layout);
		mLogoCenter 			= findViewById(R.id.welcome_icon_center);
		mContinueFAB 			= findViewById(R.id.continue_circle);
		mContinueFABShadow 		= findViewById(R.id.welcome_continue_circle_shadow);
		mTransitionViewWhite 	= findViewById(R.id.transition_view);
		mTransitionViewBlue 	= findViewById(R.id.transition_view_blue);

		mTransitionViewBlue		.setVisibility(View.INVISIBLE);
		mTransitionViewWhite	.setVisibility(View.INVISIBLE);
		mWelcomeTextLineOne		.setVisibility(View.INVISIBLE);
		mWelcomeTextLineTwo		.setVisibility(View.INVISIBLE);
		mWelcomeTextLineThree	.setVisibility(View.INVISIBLE);
		mLogo					.setVisibility(View.INVISIBLE);
		mLogoContainer			.setVisibility(View.INVISIBLE);
		mContinueFAB			.setVisibility(View.INVISIBLE);
		mContinueIcon			.setVisibility(View.INVISIBLE);


		Service.bringToBack(mTransitionViewWhite);
		Service.bringToBack(mTransitionViewBlue);

		// Change the position of the WelcomeText. Doing it this way is more dynamic, instead of a fixed
		// DP length from the bottom
		int yPosition = (int) (2.5 * (getScreenHeight() / 5));
		mWelcomeText.setY(yPosition);

		// Start the animations. Make sure the animations that in the correct order,
		// by adding Animation Listeners that start the next animation on animation end.
		new Handler().postDelayed(new Runnable() {
			@Override
			public void run() {
				startLogoContainerAnimations().setAnimationListener(new Animation.AnimationListener() {
					@Override
					public void onAnimationStart(Animation animation) {
						mLogoContainer.setVisibility(View.VISIBLE);
					}

					@Override
					public void onAnimationEnd(Animation animation) {

					}

					@Override
					public void onAnimationRepeat(Animation animation) {

					}
				});
				startLogoOuterAnimations().setAnimationListener(new Animation.AnimationListener() {
					@Override
					public void onAnimationStart(Animation animation) {

					}

					@Override
					public void onAnimationEnd(Animation animation) {
						startWelcomeTextLineAnimations(mWelcomeTextLineOne, 1);
						startWelcomeTextLineAnimations(mWelcomeTextLineTwo, 2);
						startWelcomeTextLineAnimations(mWelcomeTextLineThree, 3).setAnimationListener(new Animation.AnimationListener() {
							@Override
							public void onAnimationStart(Animation animation) {

							}

							@Override
							public void onAnimationEnd(Animation animation) {
								startContinueFABAnimations();
							}

							@Override
							public void onAnimationRepeat(Animation animation) {

							}
						});
					}

					@Override
					public void onAnimationRepeat(Animation animation) {

					}
				});
			}
		}, ANIMATIONS_START_DELAY);



		mContinueFAB.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// Get the center for the FAB
				int cx = (int) mContinueFAB.getX() + mContinueFAB.getMeasuredHeight() / 2;
				int cy = (int) mContinueFAB.getY() + mContinueFAB.getMeasuredWidth() / 2;

				// get the final radius for the clipping circle
				int dx = Math.max(cx, mTransitionViewWhite.getWidth() - cx);
				int dy = Math.max(cy, mTransitionViewWhite.getHeight() - cy);
				float finalRadius = (float) Math.hypot(dx, dy);

				final SupportAnimator whiteTransitionAnimation =
						ViewAnimationUtils.createCircularReveal(mTransitionViewWhite, cx, cy, 0, finalRadius);
				whiteTransitionAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
				whiteTransitionAnimation.setDuration(REVEAL_ANIMATION_DURATION);
				whiteTransitionAnimation.addListener(new SupportAnimator.AnimatorListener() {
					@Override
					public void onAnimationStart() {
						mTransitionViewWhite.bringToFront();
						mTransitionViewWhite.setVisibility(View.VISIBLE);
						mContinueFAB.setClickable(false);
						startHideContinueIconAnimations();
					}

					@Override
					public void onAnimationEnd() {
						transitionAnimationWhite = whiteTransitionAnimation;
					}

					@Override
					public void onAnimationCancel() {
						onAnimationEnd();
					}

					@Override
					public void onAnimationRepeat() {

					}
				});


				final SupportAnimator blueTransitionAnimation =
						ViewAnimationUtils.createCircularReveal(mTransitionViewBlue, cx, cy, 0, finalRadius);
				blueTransitionAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
				blueTransitionAnimation.setDuration(REVEAL_ANIMATION_DURATION);
				blueTransitionAnimation.addListener(new SupportAnimator.AnimatorListener() {
					@Override
					public void onAnimationStart() {
						mTransitionViewBlue.setVisibility(View.VISIBLE);
						mTransitionViewBlue.bringToFront();
						mContinueFABShadow.bringToFront();
						mContinueFAB.bringToFront();
					}

					@Override
					public void onAnimationEnd() {
						transitionAnimationBlue = blueTransitionAnimation;
					}

					@Override
					public void onAnimationCancel() {
						onAnimationEnd();
					}

					@Override
					public void onAnimationRepeat() {

					}
				});

				whiteTransitionAnimation.start();
				blueTransitionAnimation.setStartDelay(REVEAL_ANIMATION_DELAY_DURATION);
				blueTransitionAnimation.start();

				new Handler().postDelayed(new Runnable() {
					@Override
					public void run() {
						Log.d(LOG_TAG, "Navigating To Login Activity");
						navigateToLoginActivity();
					}
				}, REVEAL_ANIMATION_DELAY_DURATION + REVEAL_ANIMATION_DURATION);

			}
		});
	}

	@Override
	public void onResume() {
		super.onResume();
		// The user has returned from the login screen. Lol wtf?
		if(transitionAnimationWhite != null && hasTransitioned) {
			SupportAnimator blueReversed = transitionAnimationBlue.reverse();
			blueReversed.setInterpolator(new AccelerateDecelerateInterpolator());
			blueReversed.addListener(new SupportAnimator.AnimatorListener() {
				@Override
				public void onAnimationStart() {
					mTransitionViewBlue.setVisibility(View.VISIBLE);
					mTransitionViewBlue.bringToFront();
				}

				@Override
				public void onAnimationEnd() {
					Service.bringToBack(mTransitionViewBlue);
					mTransitionViewBlue.setVisibility(View.INVISIBLE);
				}

				@Override
				public void onAnimationCancel() {

				}

				@Override
				public void onAnimationRepeat() {

				}
			});
			blueReversed.setDuration(REVEAL_ANIMATION_DURATION);
			blueReversed.start();

			final SupportAnimator whiteReversed = transitionAnimationWhite.reverse();
			whiteReversed.setInterpolator(new AccelerateDecelerateInterpolator());
			whiteReversed.addListener(new SupportAnimator.AnimatorListener() {
				@Override
				public void onAnimationStart() {
					mTransitionViewWhite.setVisibility(View.VISIBLE);
					mTransitionViewWhite.bringToFront();
				}

				@Override
				public void onAnimationEnd() {
					Service.bringToBack(mTransitionViewWhite);
					mTransitionViewWhite.setVisibility(View.INVISIBLE);
					mContinueFAB.setClickable(true);
					startShowContinueIconAnimations();
				}

				@Override
				public void onAnimationCancel() {

				}

				@Override
				public void onAnimationRepeat() {

				}
			});
			whiteReversed.setDuration(REVEAL_ANIMATION_DURATION);
			new Handler().postDelayed(new Runnable() {
				@Override
				public void run() {
					whiteReversed.start();
				}
			}, REVEAL_ANIMATION_DELAY_DURATION);
			hasTransitioned = false;
		}
	}

	private void navigateToLoginActivity() {
		// Go to the login activity, with no transition.
		hasTransitioned = true;
		Intent loginActivityIntent = new Intent(getBaseContext(), LoginActivity.class);
		loginActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
		ActivityCompat.startActivity(this, loginActivityIntent, null);
	}

	private int getScreenHeight() {
		WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
		final DisplayMetrics displayMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(displayMetrics);
		return displayMetrics.heightPixels;
	}

	/**
	 * Animations for the views in this activity
	 */

	private AnimationSet startLogoContainerAnimations() {
		mLogoCenter.setLayerType(View.LAYER_TYPE_HARDWARE, null);
		AnimationSet mInitLogoAnimations = new AnimationSet(true);
		TranslateAnimation trans = new TranslateAnimation(0,0,getScreenHeight(), 0);

		mInitLogoAnimations.setDuration(LOGO_Container_ANIMATION_DURATION);
		mInitLogoAnimations.setFillAfter(true);
		mInitLogoAnimations.setInterpolator(new OvershootInterpolator(0.7f));
		mInitLogoAnimations.addAnimation(trans);
		mInitLogoAnimations.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {

			}

			@Override
			public void onAnimationEnd(Animation animation) {
				mLogoCenter.setLayerType(View.LAYER_TYPE_NONE, null);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {

			}
		});

		mLogoContainer.startAnimation(mInitLogoAnimations);
		return mInitLogoAnimations;
	}

	private AnimationSet startLogoOuterAnimations() {
		mLogo.setLayerType(View.LAYER_TYPE_HARDWARE, null);

		Animation mScaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		mScaleAnimation.setDuration(LOGO_ANIMATION_DURATION);
		mScaleAnimation.setInterpolator(new OvershootInterpolator(0.7f));

		Animation mAlphaAnimation = new AlphaAnimation(0f, 1f);
		mAlphaAnimation.setDuration(LOGO_ANIMATION_DURATION);
		mAlphaAnimation.setInterpolator(new DecelerateInterpolator());
		mAlphaAnimation.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {
				mLogo.setVisibility(View.VISIBLE);
			}

			@Override
			public void onAnimationEnd(Animation animation) {

			}

			@Override
			public void onAnimationRepeat(Animation animation) {

			}
		});

		RotateAnimation mRotateAnimation = new RotateAnimation(
			  0, 360,
			  Animation.RELATIVE_TO_SELF, 0.5f,
			  Animation.RELATIVE_TO_SELF, 0.5f
		);
		mRotateAnimation.setInterpolator(new DecelerateInterpolator());
		mRotateAnimation.setDuration(LOGO_ANIMATION_DURATION);
		mRotateAnimation.setRepeatCount(0);

		final AnimationSet mLogoAnimations = new AnimationSet(false);
		mLogoAnimations.setInterpolator(new AccelerateDecelerateInterpolator());
		mLogoAnimations.setFillBefore(true);
		mLogoAnimations.setFillAfter(true);
		mLogoAnimations.addAnimation(mScaleAnimation);
		mLogoAnimations.addAnimation(mRotateAnimation);
		mLogoAnimations.addAnimation(mAlphaAnimation);

		mLogoAnimations.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {

			}

			@Override
			public void onAnimationEnd(Animation animation) {
				mLogo.setLayerType(View.LAYER_TYPE_NONE, null);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {

			}
		});

		new Handler().postDelayed(new Runnable() {
			@Override
			public void run() {
				mLogo.startAnimation(mLogoAnimations);
			}
		}, LOGO_Container_ANIMATION_DURATION - LOGO_ANIMATION_DURATION);

		return mLogoAnimations;
	}

	private AnimationSet startWelcomeTextLineAnimations(final TextView mWelcomeTextLine, int lineNumber) {
		mWelcomeTextLine.setLayerType(View.LAYER_TYPE_HARDWARE, null);

		int travelDistance = (lineNumber < 3)
			   ? (int) TypedValue.applyDimension(
							TypedValue.COMPLEX_UNIT_SP,
							getResources().getDimension(R.dimen.welcome_text_line_three_size),
							getResources().getDisplayMetrics())
			   : 0;

		float overshoot = (lineNumber == 1) ? 2f : 1f;
		final Animation mTranslationAnimation = new TranslateAnimation(0, 0, travelDistance, 0);
		mTranslationAnimation.setInterpolator(new OvershootInterpolator(overshoot));

		final Animation mAlphaAnimation = new AlphaAnimation(0f, 1f);
		mAlphaAnimation.setInterpolator(new DecelerateInterpolator());
		mAlphaAnimation.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {
				mWelcomeTextLine.setVisibility(View.VISIBLE);
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				mWelcomeTextLine.setLayerType(View.LAYER_TYPE_NONE, null);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {

			}
		});



		final AnimationSet mWelcomeTextAnimations = new AnimationSet(false);
		mWelcomeTextAnimations.setDuration(WELCOME_TEXT_ANIMATION_DURATION);
		mWelcomeTextAnimations.setInterpolator(new AccelerateDecelerateInterpolator());
		mWelcomeTextAnimations.setFillBefore(true);
		mWelcomeTextAnimations.setFillAfter(true);
		mWelcomeTextAnimations.addAnimation(mAlphaAnimation);
		mWelcomeTextAnimations.addAnimation(mTranslationAnimation);

		int delay = (lineNumber < 3)
				? WELCOME_TEXT_ANIMATION_BASE_DELAY * lineNumber
				: WELCOME_TEXT_ANIMATION_BASE_DELAY * (lineNumber * 2);
		new Handler().postDelayed(new Runnable() {
			@Override
			public void run() {
				mWelcomeTextLine.startAnimation(mWelcomeTextAnimations);

			}
		}, delay);

		return mWelcomeTextAnimations;
	}

	private AnimationSet startContinueFABAnimations() {
		mContinueFAB.setLayerType(View.LAYER_TYPE_HARDWARE, null);
		mContinueFABShadow.setLayerType(View.LAYER_TYPE_HARDWARE, null);

		int travelDistance = Service.dpToPixels(getBaseContext(), getResources().getDimension(R.dimen.welcome_continue_circle_diameter));

		final Animation mTranslationAnimation = new TranslateAnimation(0, 0, travelDistance, 0);

		final AnimationSet mContinueFABAnimations = new AnimationSet(true);
		mContinueFABAnimations.setDuration(CONTINUE_FAB_ANIMATION_DURATION);
		mContinueFABAnimations.setInterpolator(new OvershootInterpolator(1f));
		mContinueFABAnimations.addAnimation(mTranslationAnimation);
		mContinueFABAnimations.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {
				// Start running the show animation for the FAB icon a third into this animation
				mContinueFAB.setVisibility(View.VISIBLE);
				new Handler().postDelayed(new Runnable() {
					@Override
					public void run() {
						mContinueIcon.setVisibility(View.VISIBLE);
						startShowContinueIconAnimations();
					}
				}, CONTINUE_FAB_ANIMATION_DURATION/3);
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				mContinueFAB.setLayerType(View.LAYER_TYPE_NONE, null);
				mContinueFABShadow.setLayerType(View.LAYER_TYPE_NONE, null);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {

			}
		});

		mContinueFAB.startAnimation(mContinueFABAnimations);
		mContinueFABShadow.startAnimation(mContinueFABAnimations);
		return mContinueFABAnimations;
	}

	private AnimationSet startShowContinueIconAnimations() {
		Animation mScaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		Animation mRotateAnimation = new RotateAnimation(
					0, 360,
					Animation.RELATIVE_TO_SELF, 0.5f,
					Animation.RELATIVE_TO_SELF, 0.5f
		);
		mRotateAnimation.setRepeatCount(0);

		AnimationSet mAnimations = new AnimationSet(true);
		mAnimations.setDuration(REVEAL_ANIMATION_DURATION);
		mAnimations.setFillAfter(true);
		mAnimations.setInterpolator(new OvershootInterpolator(1.5f));
		mAnimations.addAnimation(mScaleAnimation);
		mAnimations.addAnimation(mRotateAnimation);

		mContinueIcon.startAnimation(mAnimations);
		return mAnimations;
	}

	private AnimationSet startHideContinueIconAnimations() {
		Animation mScaleAnimation = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		Animation mRotateAnimation = new RotateAnimation(
					0, 360,
					Animation.RELATIVE_TO_SELF, 0.5f,
					Animation.RELATIVE_TO_SELF, 0.5f
		);
		mRotateAnimation.setRepeatCount(0);

		AnimationSet mAnimations = new AnimationSet(true);
		mAnimations.setDuration(REVEAL_ANIMATION_DURATION);
		mAnimations.setFillAfter(true);
		mAnimations.setInterpolator(new OvershootInterpolator(1.5f));
		mAnimations.addAnimation(mScaleAnimation);
		mAnimations.addAnimation(mRotateAnimation);

		mContinueIcon.startAnimation(mAnimations);
		return mAnimations;
	}



}