package com.miz.introactivity;

import android.animation.ArgbEvaluator;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;

/**
 * Base activity that apps should extend
 * to make use of the intro screen.
 */
public abstract class IntroActivity extends AppCompatActivity {

    private final ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();

    private ViewPager mViewPager;
    private Button mSkipButton;
    private NextDoneButton mNextButton;
    private IntroScreenPagerAdapter mPagerAdapter;
    private LinearLayout mProgressLayout;
    private boolean mShowSkipButton, mShowNextButton;
    private int mProgressCircleColor;

    @Override
    protected final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setTheme(R.style.IntroActivity_Theme);

        // Set the content view
        setContentView(R.layout.intro);

        // Set up the progress LinearLayout
        mProgressLayout = (LinearLayout) findViewById(R.id.progress_layout);

        // Set up the back button
        mSkipButton = (Button) findViewById(R.id.skip_button);
        mSkipButton.setOnClickListener(mOnSkipClickListener);

        // Set up the next button
        mNextButton = (NextDoneButton) findViewById(R.id.next_button);
        mNextButton.setOnClickListener(mOnNextClickListener);

        // Set up the ViewPager
        mViewPager = (ViewPager) findViewById(R.id.view_pager);

        // Set up the PagerAdapter
        mPagerAdapter = new IntroScreenPagerAdapter(getSupportFragmentManager());

        // Add the OnPageChangeListener
        mViewPager.addOnPageChangeListener(mOnPageChangeListener);

        // Set a custom animation PageTransformer
        mViewPager.setPageTransformer(false, new CustomAnimationPageTransformer());

        // Call the initialize method to add intro screens
        // and set up the selected styles
        initialize();

        // Set up the progress layout with circles
        setupProgressLayout();

        // Set the ViewPager adapter
        mViewPager.setAdapter(mPagerAdapter);

        // Required in order to get a callback in onPageSelected
        mViewPager.setCurrentItem(0);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        // Remove the OnPageChangeListener when the Activity is destroyed
        mViewPager.removeOnPageChangeListener(mOnPageChangeListener);
    }

    private void setupProgressLayout() {
        int circleSize = Utils.convertDpToPixel(this, 8);
        int circleMargin = Utils.convertDpToPixel(this, 4);

        for (int i = 0; i < mPagerAdapter.getCount(); i++) {
            // Create a new ImageView with a circle background
            ImageView circle = new ImageView(this);
            circle.setBackgroundResource(R.drawable.progress_circle);

            // Set up LayoutParams for the circle
            LinearLayout.LayoutParams pm = new LinearLayout.LayoutParams(circleSize, circleSize);
            pm.setMargins(circleMargin, 0, circleMargin, 0);
            circle.setLayoutParams(pm);

            // Add the circle to the progress layout
            mProgressLayout.addView(circle);
        }

        // Select the first item
        setProgressSelection(0);
    }

    /**
     * OnClickListener for the "Skip" button.
     */
    private final View.OnClickListener mOnSkipClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // "Skip" button pressed callback
            onSkipPressed();
        }
    };

    /**
     * OnClickListener for the "Next" / "Done" button.
     */
    private final View.OnClickListener mOnNextClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int currentItem = mViewPager.getCurrentItem();

            // Navigate to the next page in the ViewPager if we're not at the end already
            if (currentItem < mPagerAdapter.getCount() - 1) {
                // Navigate to the next page
                mViewPager.setCurrentItem(currentItem + 1, true);

                // "Next" button pressed callback
                onNextPressed(mViewPager.getCurrentItem());
            } else {
                // "Done" button pressed callback
                onDonePressed();
            }
        }
    };

    private ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (position < mPagerAdapter.getCount() - 1) {
                // Set the background color of the ViewPager based on the scroll offset
                // in respect to the background color of the pages being scrolled
                mViewPager.setBackgroundColor((Integer) mArgbEvaluator.evaluate(positionOffset,
                        mPagerAdapter.getBackgroundColorForPage(position),
                        mPagerAdapter.getBackgroundColorForPage(position + 1)));
            }
        }

        @Override
        public void onPageSelected(int position) {
            // Check if the current ViewPager position is at the end
            if (position == mPagerAdapter.getCount() - 1) {
                // Show the "Done" button
                mNextButton.showDoneButton(true);

                // Hide the "Skip" button
                mSkipButton.setVisibility(View.INVISIBLE);
            } else {
                // Check if the "Done" button is shown - if so, we should change to
                // "Next" as we're no longer on the last page in the ViewPager
                if (mNextButton.getButtonStyle() == NextDoneButton.STYLE_DONE) {
                    mNextButton.showNextButton(true);
                }

                // Check if the "Skip" button isn't visible when it should be
                if (mShowSkipButton && mSkipButton.getVisibility() != View.VISIBLE) {
                    mSkipButton.setVisibility(View.VISIBLE);
                }
            }

            setProgressSelection(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {}
    };

    private void setProgressSelection(int position) {
        for (int i = 0; i < mProgressLayout.getChildCount(); i++) {
            mProgressLayout.getChildAt(i).setBackgroundResource(i == position ?
                    R.drawable.progress_circle_selected :
                    R.drawable.progress_circle);

            if (mProgressCircleColor == 0) {
                mProgressCircleColor = ContextCompat.getColor(this, R.color.progress_circle_color);
            }

            mProgressLayout.getChildAt(i).getBackground()
                    .setColorFilter(mProgressCircleColor, PorterDuff.Mode.SRC_IN);
        }
    }

    /**
     * Set the color of the progress circles at the bottom
     * of the intro screen.
     * @param color Progress circle color to set.
     */
    protected void setProgressCircleColor(int color) {
        mProgressCircleColor = color;
    }

    /**
     * Use this method to initialize your intro screens
     * and set up various styling options.
     */
    protected abstract void initialize();

    /**
     * Add an intro screen (Fragment) to the ViewPager.
     * @param introScreen Fragment to add.
     */
    protected void addIntroScreen(BaseIntroFragment introScreen, int backgroundColor) {
        mPagerAdapter.addFragment(introScreen, backgroundColor);
    }

    /**
     * Determine if the "Next" button should be shown. Default is true.
     * @param showNextButton True if visible, false otherwise.
     */
    protected void setShowNextButton(boolean showNextButton) {
        mShowNextButton = showNextButton;
        mNextButton.setVisibility(mShowNextButton ? View.VISIBLE : View.GONE);
    }

    /**
     * Determine if the "Skip" button should be shown. Default is true.
     * @param showSkipButton True if visible, false otherwise.
     */
    protected void setShowSkipButton(boolean showSkipButton) {
        mShowSkipButton = showSkipButton;
        mSkipButton.setVisibility(mShowSkipButton ? View.VISIBLE : View.GONE);
    }

    /**
     * Set the text color of the Skip button. Default color is white (#F0F0F0).
     * @param color Text color to set.
     */
    protected void setSkipButtonTextColor(int color) {
        mSkipButton.setTextColor(color);
    }

    /**
     * Set the background color of the Next / Done button. The selected color
     * will be 25 percent opaque. Default color is white (#FFFFFF).
     * @param color Background color for the Next / Done button.
     */
    protected void setNextButtonBackgroundColor(int color) {
        mNextButton.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN);
    }

    /**
     * Set the color of the arrow / done icon for the Next / Done button.
     * Default color is white (#F0F0F0).
     * @param color
     */
    protected void setNextButtonIconColor(int color) {
        mNextButton.setColor(color);
    }

    /**
     * Callback when the "Skip" button is pressed.
     */
    protected abstract void onSkipPressed();

    /**
     * Callback when the "Next" button is pressed.
     * @param pagePosition Zero-based index of the current page position.
     */
    protected abstract void onNextPressed(int pagePosition);

    /**
     * Callback when the "Done" button is pressed.
     */
    protected abstract void onDonePressed();

}