package jp.sourceforge.nicoro;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;

public class PlayerInfoControllerManager {

    private static final int ANIM_TIME_PLAYER_INFO_IN = 500;
    private static final int ANIM_TIME_PLAYER_INFO_OUT = 500;
    private static final int ANIM_TIME_PLAYER_CONTROLLER_IN = 400;
    private static final int ANIM_TIME_PLAYER_CONTROLLER_OUT = 400;

    final ViewGroup mPlayerInfo;
    final ViewGroup mPlayerController;
    private final View mInfoTime;

    private TranslateAnimation mAnimInfoIn;
    private TranslateAnimation mAnimInfoOut;
    private TranslateAnimation mAnimControllerIn;
    private TranslateAnimation mAnimControllerOut;

    private final GestureDetector mGestureDetector;
    private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener {
        private int mDisplayWidth;
        private int mDisplayHeight;

        public CustomGestureListener(Context context) {
            WindowManager windowManager =
                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics metrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(metrics);
            mDisplayWidth = metrics.widthPixels;
            mDisplayHeight = metrics.heightPixels;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2,
                float velocityX, float velocityY) {
            final float absVelocityX = Math.abs(velocityX);
            final float absVelocityY = Math.abs(velocityY);
            if (absVelocityY >= absVelocityX) {
                // Controller操作
                if (mPlayerController != null) {
                    if (velocityY >= 0.0f) {
                        if (isPlayerControllerShown()) {
                            hidePlayerController();
                        }
                    } else {
                        if (!isPlayerControllerShown()) {
                            showPlayerController();
                        }
                    }
                }
            } else {
                // Info操作
                if (mPlayerInfo != null) {
                    if (velocityX >= 0.0f) {
                        if (isPlayerInfoShown()) {
                            hidePlayerInfo();
                        }
                    } else {
                        if (!isPlayerInfoShown()) {
                            showPlayerInfo();
                        }
                    }
                }
            }
            return true;
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            float x = e.getX();
            float y = e.getY();
            if (mPlayerInfo != null && x >= ((float) (mDisplayWidth * 2)) / 3.0f
                    && (y < ((float) (mDisplayHeight * 2)) / 3.0f)) {
                switchPlayerInfoDisplay();
                return true;
            } else if (mPlayerController != null) {
                if (isPlayerControllerShown()) {
                    if (y < ((float) (mDisplayHeight * 2)) / 3.0f) {
                        hidePlayerController();
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    showPlayerController();
                    return true;
                }
            } else {
                return false;
            }
        }
    }

    public PlayerInfoControllerManager(Context context,
            ViewGroup info, ViewGroup controller,
            View infoTime) {
        mPlayerInfo = info;
        mPlayerController = controller;
        mInfoTime = infoTime;
        mGestureDetector = new GestureDetector(context,
                new CustomGestureListener(context));
    }

    public boolean onTouchEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // 1.6向けなのでonKeyDownでback key監視
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (isPlayerControllerShown()) {
                hidePlayerController();
                return true;
            }
        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
            switchPlayerControllerDisplay();
            return true;
        }
        return false;
    }

    public void switchPlayerInfoDisplay() {
        if (mPlayerInfo == null) {
            return;
        }
        if (isPlayerInfoShown()) {
            hidePlayerInfo();
        } else {
            showPlayerInfo();
        }
    }

    public boolean isPlayerInfoShown() {
        if (mPlayerInfo == null) {
            return false;
        }
        final int visibility = mPlayerInfo.getVisibility();
        if (visibility == View.VISIBLE
                && (mAnimInfoOut == null
                        || mPlayerInfo.getAnimation() != mAnimInfoOut)) {
            return true;
        } else {
            return false;
        }
    }
    public void showPlayerInfo() {
        if (mPlayerInfo == null) {
            return;
        }
        if (mAnimInfoIn == null) {
            int infoWidth = mPlayerInfo.getWidth();
            mAnimInfoIn = new TranslateAnimation(
                    infoWidth, 0.0f, 0.0f, 0.0f);
            mAnimInfoIn.setDuration(ANIM_TIME_PLAYER_INFO_IN);
            mAnimInfoIn.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationEnd(Animation animation) {
                    mPlayerInfo.clearAnimation();
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
                @Override
                public void onAnimationStart(Animation animation) {
                }
            });
        }
        mPlayerInfo.setVisibility(View.VISIBLE);
        mPlayerInfo.startAnimation(mAnimInfoIn);
    }
    public void hidePlayerInfo() {
        if (mPlayerInfo == null) {
            return;
        }
        if (mAnimInfoOut == null) {
            int infoWidth = mPlayerInfo.getWidth();
            mAnimInfoOut = new TranslateAnimation(
                    0.0f, infoWidth, 0.0f, 0.0f);
            mAnimInfoOut.setDuration(ANIM_TIME_PLAYER_INFO_OUT);
            mAnimInfoOut.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationEnd(Animation animation) {
                    mPlayerInfo.setVisibility(View.INVISIBLE);
                    mPlayerInfo.clearAnimation();
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
                @Override
                public void onAnimationStart(Animation animation) {
                }
            });
        }
        mPlayerInfo.startAnimation(mAnimInfoOut);
    }

    public void switchPlayerControllerDisplay() {
        if (mPlayerController == null) {
            return;
        }
        if (isPlayerControllerShown()) {
            hidePlayerController();
        } else {
            showPlayerController();
        }
    }

    public boolean isPlayerControllerShown() {
        if (mPlayerController == null) {
            return false;
        }
        final int visibility = mPlayerController.getVisibility();
        if (visibility == View.VISIBLE
                && (mAnimControllerOut == null
                        || mPlayerController.getAnimation() != mAnimControllerOut)) {
            return true;
        } else {
            return false;
        }
    }
    public void showPlayerController() {
        if (mPlayerController == null) {
            return;
        }
        if (mAnimControllerIn == null) {
            int controllerHeight = mPlayerController.getHeight();
            mAnimControllerIn = new TranslateAnimation(
                    0.0f, 0.0f, controllerHeight, 0.0f);
            mAnimControllerIn.setDuration(ANIM_TIME_PLAYER_CONTROLLER_IN);
            mAnimControllerIn.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationEnd(Animation animation) {
                    mPlayerController.clearAnimation();
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
                @Override
                public void onAnimationStart(Animation animation) {
                }
            });
        }
        mPlayerController.setVisibility(View.VISIBLE);
        mPlayerController.startAnimation(mAnimControllerIn);

        // Infoの時間表示を隠す
        if (mInfoTime != null) {
            mInfoTime.setVisibility(View.INVISIBLE);
        }
    }
    public void hidePlayerController() {
        if (mPlayerController == null) {
            return;
        }
        if (mAnimControllerOut == null) {
            int controllerHeight = mPlayerController.getHeight();
            mAnimControllerOut = new TranslateAnimation(
                    0.0f, 0.0f, 0.0f, controllerHeight);
            mAnimControllerOut.setDuration(ANIM_TIME_PLAYER_CONTROLLER_OUT);
            mAnimControllerOut.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationEnd(Animation animation) {
                    mPlayerController.setVisibility(View.INVISIBLE);
                    mPlayerController.clearAnimation();
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
                @Override
                public void onAnimationStart(Animation animation) {
                }
            });
        }
        mPlayerController.startAnimation(mAnimControllerOut);

        // Infoの時間表示を再表示
        if (mInfoTime != null) {
            mInfoTime.setVisibility(View.VISIBLE);
        }
    }
}
