/*
 * 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.camera;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.MediaStore;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;

import com.android.camera.ui.CameraSwitcher;
import com.android.gallery3d.R;
import com.android.gallery3d.app.PhotoPage;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.util.LightCycleHelper;

public class CameraActivity extends ActivityBase
        implements CameraSwitcher.CameraSwitchListener {
    public static final int PHOTO_MODULE_INDEX = 0;
    public static final int VIDEO_MODULE_INDEX = 1;
    public static final int PANORAMA_MODULE_INDEX = 2;
    public static final int LIGHTCYCLE_MODULE_INDEX = 3;

    CameraModule mCurrentModule;
    private FrameLayout mFrame;
    private ShutterButton mShutter;
    private CameraSwitcher mSwitcher;
    private View mCameraControls;
    private View mControlsBackground;
    private View mPieMenuButton;
    private Drawable[] mDrawables;
    private int mCurrentModuleIndex;
    private MotionEvent mDown;
    private boolean mAutoRotateScreen;
    private int mHeightOrWidth = -1;

    private MyOrientationEventListener mOrientationListener;
    // The degrees of the device rotated clockwise from its natural orientation.
    private int mLastRawOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;

    private MediaSaveService mMediaSaveService;
    private ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName className, IBinder b) {
                mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService();
                mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
            }
            @Override
            public void onServiceDisconnected(ComponentName className) {
                mMediaSaveService = null;
            }};

    private static final String TAG = "CAM_activity";

    private static final int[] DRAW_IDS = {
            R.drawable.ic_switch_camera,
            R.drawable.ic_switch_video,
            R.drawable.ic_switch_pan,
            R.drawable.ic_switch_photosphere
    };

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.camera_main);
        mFrame = (FrameLayout) findViewById(R.id.camera_app_root);
        mDrawables = new Drawable[DRAW_IDS.length];
        for (int i = 0; i < DRAW_IDS.length; i++) {
            mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]);
        }
        init();
        if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction())
                || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) {
            mCurrentModule = new VideoModule();
            mCurrentModuleIndex = VIDEO_MODULE_INDEX;
        } else {
            mCurrentModule = new PhotoModule();
            mCurrentModuleIndex = PHOTO_MODULE_INDEX;
        }
        mCurrentModule.init(this, mFrame, true);
        mSwitcher.setCurrentIndex(mCurrentModuleIndex);
        mOrientationListener = new MyOrientationEventListener(this);
        bindMediaSaveService();
    }

    public void init() {
        boolean landscape = Util.getDisplayRotation(this) % 180 == 90;
        mControlsBackground = findViewById(R.id.blocker);
        mCameraControls = findViewById(R.id.camera_controls);
        mShutter = (ShutterButton) findViewById(R.id.shutter_button);
        mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher);
        mPieMenuButton = findViewById(R.id.menu);
        int totaldrawid = (LightCycleHelper.hasLightCycleCapture(this)
                                ? DRAW_IDS.length : DRAW_IDS.length - 1);
        if (!ApiHelper.HAS_OLD_PANORAMA) totaldrawid--;

        int[] drawids = new int[totaldrawid];
        int[] moduleids = new int[totaldrawid];
        int ix = 0;
        for (int i = 0; i < mDrawables.length; i++) {
            if (i == PANORAMA_MODULE_INDEX && !ApiHelper.HAS_OLD_PANORAMA) {
                continue; // not enabled, so don't add to UI
            }
            if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(this)) {
                continue; // not enabled, so don't add to UI
            }
            moduleids[ix] = i;
            drawids[ix++] = DRAW_IDS[i];
        }
        mSwitcher.setIds(moduleids, drawids);
        mSwitcher.setSwitchListener(this);
        mSwitcher.setCurrentIndex(mCurrentModuleIndex);
    }

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

    // Return whether the auto-rotate screen in system settings
    // is turned on.
    public boolean isAutoRotateScreen() {
        return mAutoRotateScreen;
    }

    private class MyOrientationEventListener
            extends OrientationEventListener {
        public MyOrientationEventListener(Context context) {
            super(context);
        }

        @Override
        public void onOrientationChanged(int orientation) {
            // We keep the last known orientation. So if the user first orient
            // the camera then point the camera to floor or sky, we still have
            // the correct orientation.
            if (orientation == ORIENTATION_UNKNOWN) return;
            mLastRawOrientation = orientation;
            mCurrentModule.onOrientationChanged(orientation);
        }
    }

    private ObjectAnimator mCameraSwitchAnimator;

    @Override
    public void onCameraSelected(final int i) {
        if (mPaused) return;
        if (i != mCurrentModuleIndex) {
            mPaused = true;
            CameraScreenNail screenNail = getCameraScreenNail();
            if (screenNail != null) {
                if (mCameraSwitchAnimator != null && mCameraSwitchAnimator.isRunning()) {
                    mCameraSwitchAnimator.cancel();
                }
                mCameraSwitchAnimator = ObjectAnimator.ofFloat(
                        screenNail, "alpha", screenNail.getAlpha(), 0f);
                mCameraSwitchAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        doChangeCamera(i);
                    }
                });
                mCameraSwitchAnimator.start();
            } else {
                doChangeCamera(i);
            }
        }
    }

    private void doChangeCamera(int i) {
        boolean canReuse = canReuseScreenNail();
        CameraHolder.instance().keep();
        closeModule(mCurrentModule);
        mCurrentModuleIndex = i;
        switch (i) {
            case VIDEO_MODULE_INDEX:
                mCurrentModule = new VideoModule();
                break;
            case PHOTO_MODULE_INDEX:
                mCurrentModule = new PhotoModule();
                break;
            case PANORAMA_MODULE_INDEX:
                mCurrentModule = new PanoramaModule();
                break;
            case LIGHTCYCLE_MODULE_INDEX:
                mCurrentModule = LightCycleHelper.createPanoramaModule();
                break;
        }
        showPieMenuButton(mCurrentModule.needsPieMenu());

        openModule(mCurrentModule, canReuse);
        mCurrentModule.onOrientationChanged(mLastRawOrientation);
        if (mMediaSaveService != null) {
            mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
        }
        getCameraScreenNail().setAlpha(0f);
        getCameraScreenNail().setOnFrameDrawnOneShot(mOnFrameDrawn);
    }

    public void showPieMenuButton(boolean show) {
        if (show) {
            findViewById(R.id.blocker).setVisibility(View.VISIBLE);
            findViewById(R.id.menu).setVisibility(View.VISIBLE);
            findViewById(R.id.on_screen_indicators).setVisibility(View.VISIBLE);
        } else {
            findViewById(R.id.blocker).setVisibility(View.INVISIBLE);
            findViewById(R.id.menu).setVisibility(View.INVISIBLE);
            findViewById(R.id.on_screen_indicators).setVisibility(View.INVISIBLE);
        }
    }

    private Runnable mOnFrameDrawn = new Runnable() {

        @Override
        public void run() {
            runOnUiThread(mFadeInCameraScreenNail);
        }
    };

    private Runnable mFadeInCameraScreenNail = new Runnable() {

        @Override
        public void run() {
            mCameraSwitchAnimator = ObjectAnimator.ofFloat(
                    getCameraScreenNail(), "alpha", 0f, 1f);
            mCameraSwitchAnimator.setStartDelay(50);
            mCameraSwitchAnimator.start();
        }
    };

    @Override
    public void onShowSwitcherPopup() {
        mCurrentModule.onShowSwitcherPopup();
    }

    private void openModule(CameraModule module, boolean canReuse) {
        module.init(this, mFrame, canReuse && canReuseScreenNail());
        mPaused = false;
        module.onResumeBeforeSuper();
        module.onResumeAfterSuper();
    }

    private void closeModule(CameraModule module) {
        module.onPauseBeforeSuper();
        module.onPauseAfterSuper();
        mFrame.removeAllViews();
    }

    public ShutterButton getShutterButton() {
        return mShutter;
    }

    public void hideUI() {
        mCameraControls.setVisibility(View.INVISIBLE);
        hideSwitcher();
        mShutter.setVisibility(View.GONE);
    }

    public void showUI() {
        mCameraControls.setVisibility(View.VISIBLE);
        showSwitcher();
        mShutter.setVisibility(View.VISIBLE);
        // Force a layout change to show shutter button
        mShutter.requestLayout();
    }

    public void hideSwitcher() {
        mSwitcher.closePopup();
        mSwitcher.setVisibility(View.INVISIBLE);
    }

    public void showSwitcher() {
        if (mCurrentModule.needsSwitcher()) {
            mSwitcher.setVisibility(View.VISIBLE);
        }
    }

    public boolean isInCameraApp() {
        return mShowCameraAppView;
    }

    @Override
    public void onConfigurationChanged(Configuration config) {
        super.onConfigurationChanged(config);
        mCurrentModule.onConfigurationChanged(config);
    }

    @Override
    public void onPause() {
        mPaused = true;
        mOrientationListener.disable();
        mCurrentModule.onPauseBeforeSuper();
        super.onPause();
        mCurrentModule.onPauseAfterSuper();
    }

    @Override
    public void onResume() {
        mPaused = false;
        if (Settings.System.getInt(getContentResolver(),
                Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {// auto-rotate off
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
            mAutoRotateScreen = false;
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
            mAutoRotateScreen = true;
        }
        mOrientationListener.enable();
        mCurrentModule.onResumeBeforeSuper();
        super.onResume();
        mCurrentModule.onResumeAfterSuper();
    }

    private void bindMediaSaveService() {
        Intent intent = new Intent(this, MediaSaveService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private void unbindMediaSaveService() {
        if (mMediaSaveService != null) {
            mMediaSaveService.setListener(null);
        }
        if (mConnection != null) {
            unbindService(mConnection);
        }
    }

    @Override
    protected void onFullScreenChanged(boolean full) {
        if (full) {
            showUI();
        } else {
            hideUI();
        }
        super.onFullScreenChanged(full);
        if (ApiHelper.HAS_ROTATION_ANIMATION) {
            setRotationAnimation(full);
        }
        mCurrentModule.onFullScreenChanged(full);
    }

    private void setRotationAnimation(boolean fullscreen) {
        int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
        if (fullscreen) {
            rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        }
        Window win = getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        winParams.rotationAnimation = rotationAnimation;
        win.setAttributes(winParams);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mCurrentModule.onStop();
        getStateManager().clearTasks();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        getStateManager().clearActivityResult();
    }

    @Override
    protected void installIntentFilter() {
        super.installIntentFilter();
        mCurrentModule.installIntentFilter();
    }

    @Override
    protected void onActivityResult(
            int requestCode, int resultCode, Intent data) {
        // Only PhotoPage understands ProxyLauncher.RESULT_USER_CANCELED
        if (resultCode == ProxyLauncher.RESULT_USER_CANCELED
                && !(getStateManager().getTopState() instanceof PhotoPage)) {
            resultCode = RESULT_CANCELED;
        }
        super.onActivityResult(requestCode, resultCode, data);
        // Unmap cancel vs. reset
        if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) {
            resultCode = RESULT_CANCELED;
        }
        mCurrentModule.onActivityResult(requestCode, resultCode, data);
    }

    // Preview area is touched. Handle touch focus.
    // Touch to focus is handled by PreviewGestures, this function call
    // is no longer needed. TODO: Clean it up in the next refactor
    @Override
    protected void onSingleTapUp(View view, int x, int y) {
    }

    @Override
    public void onBackPressed() {
        if (!mCurrentModule.onBackPressed()) {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return mCurrentModule.onKeyDown(keyCode,  event)
                || super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        return mCurrentModule.onKeyUp(keyCode,  event)
                || super.onKeyUp(keyCode, event);
    }

    public void cancelActivityTouchHandling() {
        if (mDown != null) {
            MotionEvent cancel = MotionEvent.obtain(mDown);
            cancel.setAction(MotionEvent.ACTION_CANCEL);
            super.dispatchTouchEvent(cancel);
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent m) {
        if (m.getActionMasked() == MotionEvent.ACTION_DOWN) {
            mDown = m;
        }
        if ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) {
            return mSwitcher.onTouch(null, m);
        } else if ((mSwitcher != null) && mSwitcher.isInsidePopup(m)) {
            return superDispatchTouchEvent(m);
        } else {
            return mCurrentModule.dispatchTouchEvent(m);
        }
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
        Intent proxyIntent = new Intent(this, ProxyLauncher.class);
        proxyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        proxyIntent.putExtra(Intent.EXTRA_INTENT, intent);
        super.startActivityForResult(proxyIntent, requestCode);
    }

    public boolean superDispatchTouchEvent(MotionEvent m) {
        return super.dispatchTouchEvent(m);
    }

    // Preview texture has been copied. Now camera can be released and the
    // animation can be started.
    @Override
    public void onPreviewTextureCopied() {
        mCurrentModule.onPreviewTextureCopied();
    }

    @Override
    public void onCaptureTextureCopied() {
        mCurrentModule.onCaptureTextureCopied();
    }

    @Override
    public void onUserInteraction() {
        super.onUserInteraction();
        mCurrentModule.onUserInteraction();
    }

    @Override
    protected boolean updateStorageHintOnResume() {
        return mCurrentModule.updateStorageHintOnResume();
    }

    @Override
    public void updateCameraAppView() {
        super.updateCameraAppView();
        mCurrentModule.updateCameraAppView();
    }

    private boolean canReuseScreenNail() {
        return mCurrentModuleIndex == PHOTO_MODULE_INDEX
                || mCurrentModuleIndex == VIDEO_MODULE_INDEX
                || mCurrentModuleIndex == LIGHTCYCLE_MODULE_INDEX;
    }

    @Override
    public boolean isPanoramaActivity() {
        return (mCurrentModuleIndex == PANORAMA_MODULE_INDEX);
    }

    // Accessor methods for getting latency times used in performance testing
    public long getAutoFocusTime() {
        return (mCurrentModule instanceof PhotoModule) ?
                ((PhotoModule) mCurrentModule).mAutoFocusTime : -1;
    }

    public long getShutterLag() {
        return (mCurrentModule instanceof PhotoModule) ?
                ((PhotoModule) mCurrentModule).mShutterLag : -1;
    }

    public long getShutterToPictureDisplayedTime() {
        return (mCurrentModule instanceof PhotoModule) ?
                ((PhotoModule) mCurrentModule).mShutterToPictureDisplayedTime : -1;
    }

    public long getPictureDisplayedToJpegCallbackTime() {
        return (mCurrentModule instanceof PhotoModule) ?
                ((PhotoModule) mCurrentModule).mPictureDisplayedToJpegCallbackTime : -1;
    }

    public long getJpegCallbackFinishTime() {
        return (mCurrentModule instanceof PhotoModule) ?
                ((PhotoModule) mCurrentModule).mJpegCallbackFinishTime : -1;
    }

    public long getCaptureStartTime() {
        return (mCurrentModule instanceof PhotoModule) ?
                ((PhotoModule) mCurrentModule).mCaptureStartTime : -1;
    }

    public boolean isRecording() {
        return (mCurrentModule instanceof VideoModule) ?
                ((VideoModule) mCurrentModule).isRecording() : false;
    }

    public CameraScreenNail getCameraScreenNail() {
        return (CameraScreenNail) mCameraScreenNail;
    }

    public MediaSaveService getMediaSaveService() {
        return mMediaSaveService;
    }
}
