/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.keyguard;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;

import com.android.keyguard.KeyguardActivityLauncher.CameraWidgetInfo;

public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
    private static final String TAG = CameraWidgetFrame.class.getSimpleName();
    private static final boolean DEBUG = KeyguardHostView.DEBUG;
    private static final int WIDGET_ANIMATION_DURATION = 250; // ms
    private static final int WIDGET_WAIT_DURATION = 650; // ms
    private static final int RECOVERY_DELAY = 1000; // ms

    interface Callbacks {
        void onLaunchingCamera();
        void onCameraLaunchedSuccessfully();
        void onCameraLaunchedUnsuccessfully();
    }

    private final Handler mHandler = new Handler();
    private final KeyguardActivityLauncher mActivityLauncher;
    private final Callbacks mCallbacks;
    private final CameraWidgetInfo mWidgetInfo;
    private final WindowManager mWindowManager;
    private final Point mRenderedSize = new Point();
    private final int[] mTmpLoc = new int[2];

    private long mLaunchCameraStart;
    private boolean mActive;
    private boolean mTransitioning;
    private boolean mDown;

    private final Rect mInsets = new Rect();

    private FixedSizeFrameLayout mPreview;
    private View mFullscreenPreview;
    private View mFakeNavBar;

    private final Runnable mTransitionToCameraRunnable = new Runnable() {
        @Override
        public void run() {
            transitionToCamera();
        }};

    private final Runnable mTransitionToCameraEndAction = new Runnable() {
        @Override
        public void run() {
            if (!mTransitioning)
                return;
            Handler worker =  getWorkerHandler() != null ? getWorkerHandler() : mHandler;
            mLaunchCameraStart = SystemClock.uptimeMillis();
            if (DEBUG) Log.d(TAG, "Launching camera at " + mLaunchCameraStart);
            mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
        }};

    private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
        @Override
        public void run() {
            mHandler.post(mTransitionToCameraEndAction);
        }};

    private final Runnable mRecoverRunnable = new Runnable() {
        @Override
        public void run() {
            recover();
        }};

    private final Runnable mRenderRunnable = new Runnable() {
        @Override
        public void run() {
            render();
        }};

    private final Runnable mSecureCameraActivityStartedRunnable = new Runnable() {
        @Override
        public void run() {
            onSecureCameraActivityStarted();
        }
    };

    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
        private boolean mShowing;
        void onKeyguardVisibilityChanged(boolean showing) {
            if (mShowing == showing)
                return;
            mShowing = showing;
            CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
        };
    };

    private static final class FixedSizeFrameLayout extends FrameLayout {
        int width;
        int height;

        FixedSizeFrameLayout(Context context) {
            super(context);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            measureChildren(
                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
            setMeasuredDimension(width, height);
        }
    }

    private CameraWidgetFrame(Context context, Callbacks callbacks,
            KeyguardActivityLauncher activityLauncher,
            CameraWidgetInfo widgetInfo, View previewWidget) {
        super(context);
        mCallbacks = callbacks;
        mActivityLauncher = activityLauncher;
        mWidgetInfo = widgetInfo;
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);

        mPreview = new FixedSizeFrameLayout(context);
        mPreview.addView(previewWidget);
        addView(mPreview);

        View clickBlocker = new View(context);
        clickBlocker.setBackgroundColor(Color.TRANSPARENT);
        clickBlocker.setOnClickListener(this);
        addView(clickBlocker);

        setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
        if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
    }

    public static CameraWidgetFrame create(Context context, Callbacks callbacks,
            KeyguardActivityLauncher launcher) {
        if (context == null || callbacks == null || launcher == null)
            return null;

        CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
        if (widgetInfo == null)
            return null;
        View previewWidget = getPreviewWidget(context, widgetInfo);
        if (previewWidget == null)
            return null;

        return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
    }

    private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
        return widgetInfo.layoutId > 0 ?
                inflateWidgetView(context, widgetInfo) :
                inflateGenericWidgetView(context);
    }

    private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
        if (DEBUG) Log.d(TAG, "inflateWidgetView: " + widgetInfo.contextPackage);
        View widgetView = null;
        Exception exception = null;
        try {
            Context cameraContext = context.createPackageContext(
                    widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED);
            LayoutInflater cameraInflater = (LayoutInflater)
                    cameraContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            cameraInflater = cameraInflater.cloneInContext(cameraContext);
            widgetView = cameraInflater.inflate(widgetInfo.layoutId, null, false);
        } catch (NameNotFoundException e) {
            exception = e;
        } catch (RuntimeException e) {
            exception = e;
        }
        if (exception != null) {
            Log.w(TAG, "Error creating camera widget view", exception);
        }
        return widgetView;
    }

    private static View inflateGenericWidgetView(Context context) {
        if (DEBUG) Log.d(TAG, "inflateGenericWidgetView");
        ImageView iv = new ImageView(context);
        iv.setImageResource(R.drawable.ic_lockscreen_camera);
        iv.setScaleType(ScaleType.CENTER);
        iv.setBackgroundColor(Color.argb(127, 0, 0, 0));
        return iv;
    }

    private void render() {
        final View root = getRootView();
        final int width = root.getWidth() - mInsets.right;    // leave room
        final int height = root.getHeight() - mInsets.bottom; // for bars
        if (mRenderedSize.x == width && mRenderedSize.y == height) {
            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s %d%%",
                    width, height, (int)(100*mPreview.getScaleX())));
            return;
        }
        if (width == 0 || height == 0) {
            return;
        }

        mPreview.width = width;
        mPreview.height = height;
        mPreview.requestLayout();

        final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();

        final float pvScaleX = (float) thisWidth / width;
        final float pvScaleY = (float) thisHeight / height;
        final float pvScale = Math.min(pvScaleX, pvScaleY);

        final int pvWidth = (int) (pvScale * width);
        final int pvHeight = (int) (pvScale * height);

        final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
        final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;

        mPreview.setPivotX(0);
        mPreview.setPivotY(0);
        mPreview.setScaleX(pvScale);
        mPreview.setScaleY(pvScale);
        mPreview.setTranslationX(pvTransX);
        mPreview.setTranslationY(pvTransY);

        mRenderedSize.set(width, height);
        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s %d%% instance=%s",
                width, height, (int)(100*mPreview.getScaleX()), instanceId()));
    }

    private void transitionToCamera() {
        if (mTransitioning || mDown) return;

        mTransitioning = true;

        enableWindowExitAnimation(false);

        final int navHeight = mInsets.bottom;
        final int navWidth = mInsets.right;

        mPreview.getLocationInWindow(mTmpLoc);
        final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
        final float pvCenter = mTmpLoc[1] + pvHeight / 2f;

        final ViewGroup root = (ViewGroup) getRootView();

        if (DEBUG) {
            Log.d(TAG, "root = " + root.getLeft() + "," + root.getTop() + " "
                    + root.getWidth() + "x" + root.getHeight());
        }

        if (mFullscreenPreview == null) {
            mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
            mFullscreenPreview.setClickable(false);
            root.addView(mFullscreenPreview, new FrameLayout.LayoutParams(
                        root.getWidth() - navWidth,
                        root.getHeight() - navHeight));
        }

        final float fsHeight = root.getHeight() - navHeight;
        final float fsCenter = root.getTop() + fsHeight / 2;

        final float fsScaleY = mPreview.getScaleY();
        final float fsTransY = pvCenter - fsCenter;
        final float fsScaleX = fsScaleY;

        mPreview.setVisibility(View.GONE);
        mFullscreenPreview.setVisibility(View.VISIBLE);
        mFullscreenPreview.setTranslationY(fsTransY);
        mFullscreenPreview.setScaleX(fsScaleX);
        mFullscreenPreview.setScaleY(fsScaleY);
        mFullscreenPreview
            .animate()
            .scaleX(1)
            .scaleY(1)
            .translationX(0)
            .translationY(0)
            .setDuration(WIDGET_ANIMATION_DURATION)
            .withEndAction(mPostTransitionToCameraEndAction)
            .start();

        if (navHeight > 0 || navWidth > 0) {
            final boolean atBottom = navHeight > 0;
            if (mFakeNavBar == null) {
                mFakeNavBar = new View(mContext);
                mFakeNavBar.setBackgroundColor(Color.BLACK);
                root.addView(mFakeNavBar, new FrameLayout.LayoutParams(
                            atBottom ? FrameLayout.LayoutParams.MATCH_PARENT
                                     : navWidth,
                            atBottom ? navHeight
                                     : FrameLayout.LayoutParams.MATCH_PARENT,
                            atBottom ? Gravity.BOTTOM|Gravity.FILL_HORIZONTAL
                                     : Gravity.RIGHT|Gravity.FILL_VERTICAL));
                mFakeNavBar.setPivotY(navHeight);
                mFakeNavBar.setPivotX(navWidth);
            }
            mFakeNavBar.setAlpha(0f);
            if (atBottom) {
                mFakeNavBar.setScaleY(0.5f);
            } else {
                mFakeNavBar.setScaleX(0.5f);
            }
            mFakeNavBar.setVisibility(View.VISIBLE);
            mFakeNavBar.animate()
                .alpha(1f)
                .scaleY(1f)
                .scaleY(1f)
                .setDuration(WIDGET_ANIMATION_DURATION)
                .start();
        }
        mCallbacks.onLaunchingCamera();
    }

    private void recover() {
        if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
        mCallbacks.onCameraLaunchedUnsuccessfully();
        reset();
    }

    @Override
    public void setOnLongClickListener(OnLongClickListener l) {
        // ignore
    }

    @Override
    public void onClick(View v) {
        if (DEBUG) Log.d(TAG, "clicked");
        if (mTransitioning) return;
        if (mActive) {
            cancelTransitionToCamera();
            transitionToCamera();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        if (DEBUG) Log.d(TAG, "onDetachedFromWindow: instance " + instanceId()
                + " at " + SystemClock.uptimeMillis());
        super.onDetachedFromWindow();
        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
        cancelTransitionToCamera();
        mHandler.removeCallbacks(mRecoverRunnable);
    }

    @Override
    public void onActive(boolean isActive) {
        mActive = isActive;
        if (mActive) {
            rescheduleTransitionToCamera();
        } else {
            reset();
        }
    }

    @Override
    public boolean onUserInteraction(MotionEvent event) {
        if (mTransitioning) {
            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: mTransitioning");
            return true;
        }

        getLocationOnScreen(mTmpLoc);
        int rawBottom = mTmpLoc[1] + getHeight();
        if (event.getRawY() > rawBottom) {
            if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
            return true;
        }

        int action = event.getAction();
        mDown = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE;
        if (mActive) {
            rescheduleTransitionToCamera();
        }
        if (DEBUG) Log.d(TAG, "onUserInteraction observed, not eaten");
        return false;
    }

    @Override
    protected void onFocusLost() {
        if (DEBUG) Log.d(TAG, "onFocusLost at " + SystemClock.uptimeMillis());
        cancelTransitionToCamera();
        super.onFocusLost();
    }

    public void onScreenTurnedOff() {
        if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
        reset();
    }

    private void rescheduleTransitionToCamera() {
        if (DEBUG) Log.d(TAG, "rescheduleTransitionToCamera at " + SystemClock.uptimeMillis());
        mHandler.removeCallbacks(mTransitionToCameraRunnable);
        mHandler.postDelayed(mTransitionToCameraRunnable, WIDGET_WAIT_DURATION);
    }

    private void cancelTransitionToCamera() {
        if (DEBUG) Log.d(TAG, "cancelTransitionToCamera at " + SystemClock.uptimeMillis());
        mHandler.removeCallbacks(mTransitionToCameraRunnable);
    }

    private void onCameraLaunched() {
        mCallbacks.onCameraLaunchedSuccessfully();
        reset();
    }

    private void reset() {
        if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
        mLaunchCameraStart = 0;
        mTransitioning = false;
        mDown = false;
        cancelTransitionToCamera();
        mHandler.removeCallbacks(mRecoverRunnable);
        mPreview.setVisibility(View.VISIBLE);
        if (mFullscreenPreview != null) {
            mFullscreenPreview.animate().cancel();
            mFullscreenPreview.setVisibility(View.GONE);
        }
        if (mFakeNavBar != null) {
            mFakeNavBar.animate().cancel();
            mFakeNavBar.setVisibility(View.GONE);
        }
        enableWindowExitAnimation(true);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
                w, h, oldw, oldh, SystemClock.uptimeMillis()));
        if ((w != oldw && oldw > 0) || (h != oldh && oldh > 0)) {
            // we can't trust the old geometry anymore; force a re-render
            mRenderedSize.x = mRenderedSize.y = -1;
        }
        mHandler.post(mRenderRunnable);
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    public void onBouncerShowing(boolean showing) {
        if (showing) {
            mTransitioning = false;
            mHandler.post(mRecoverRunnable);
        }
    }

    private void enableWindowExitAnimation(boolean isEnabled) {
        View root = getRootView();
        ViewGroup.LayoutParams lp = root.getLayoutParams();
        if (!(lp instanceof WindowManager.LayoutParams))
            return;
        WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp;
        int newWindowAnimations = isEnabled ? R.style.Animation_LockScreen : 0;
        if (newWindowAnimations != wlp.windowAnimations) {
            if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations
                    + " at " + SystemClock.uptimeMillis());
            wlp.windowAnimations = newWindowAnimations;
            mWindowManager.updateViewLayout(root, wlp);
        }
    }

    private void onKeyguardVisibilityChanged(boolean showing) {
        if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
                + " at " + SystemClock.uptimeMillis());
        if (mTransitioning && !showing) {
            mTransitioning = false;
            mHandler.removeCallbacks(mRecoverRunnable);
            if (mLaunchCameraStart > 0) {
                long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
                if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
                mLaunchCameraStart = 0;
                onCameraLaunched();
            }
        }
    }

    private void onSecureCameraActivityStarted() {
        if (DEBUG) Log.d(TAG, "onSecureCameraActivityStarted at " + SystemClock.uptimeMillis());
        mHandler.postDelayed(mRecoverRunnable, RECOVERY_DELAY);
    }

    private String instanceId() {
        return Integer.toHexString(hashCode());
    }

    public void setInsets(Rect insets) {
        if (DEBUG) Log.d(TAG, "setInsets: " + insets);
        mInsets.set(insets);
    }
}
