/*
 * Copyright (C) 2016 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.retaildemo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.VideoView;

import java.io.File;

/**
 * This is the activity for playing the retail demo video. This will also try to keep
 * the screen on.
 *
 * This will check for the demo video in {@link Environment#getDataPreloadsDemoDirectory()} or
 * {@link Context#getObbDir()}. If the demo video is not present, it will run a task to download it
 * from the specified url.
 */
public class DemoPlayer extends Activity implements DownloadVideoTask.ResultListener {

    private static final String TAG = "DemoPlayer";
    private static final boolean DEBUG = false;

    private static final String VIDEO_FILE_NAME = "retail_demo.mp4";
    static final String PRELOADED_VIDEO_FILE = Environment.getDataPreloadsDemoDirectory()
            + File.separator + VIDEO_FILE_NAME;

    /**
     * We save the real elapsed time to serve as an indication for downloading the demo video
     * for the next device boot. The device could boot fast at times and could result in
     * skipping the download during the next boot sessions. To be safe from cases like this, we
     * add this offset to the real elapsed time.
     */
    private static final long REAL_ELAPSED_TIME_OFFSET_MS = 60 * 1000; // 1 min

    /**
     * Maximum amount of time to wait for demo user to set up.
     * After it the user can tap the screen to exit
     */
    private static final long READY_TO_TAP_MAX_DELAY_MS = 60 * 1000; // 1 min

    private PowerManager mPowerManager;

    private VideoView mVideoView;
    private String mDownloadPath;
    private boolean mUsingDownloadedVideo;
    private Handler mHandler;
    private boolean mReadyToTap;
    private SettingsObserver mSettingsObserver;

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

        // Keep screen on
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        setContentView(R.layout.retail_video);

        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mHandler = new Handler();
        mDownloadPath = getObbDir().getPath() + File.separator + VIDEO_FILE_NAME;
        mVideoView = (VideoView) findViewById(R.id.video_content);

        // Start playing the video when it is ready
        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                mediaPlayer.setLooping(true);
                mVideoView.start();
            }
        });

        mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                if (mUsingDownloadedVideo && new File(PRELOADED_VIDEO_FILE).exists()) {
                    if (DEBUG) Log.d(TAG, "Error using the downloaded video, "
                            + "falling back to the preloaded video at " + PRELOADED_VIDEO_FILE);
                    mUsingDownloadedVideo = false;
                    setVideoPath(PRELOADED_VIDEO_FILE);
                    // And delete the downloaded video so that we don't try to use it
                    // again next time.
                    new File(mDownloadPath).delete();
                } else {
                    displayFallbackView();
                }
                return true;
            }
        });

        mReadyToTap = isUserSetupComplete();
        if (!mReadyToTap) {
            // Wait for setup to finish
            mSettingsObserver = new SettingsObserver();
            mSettingsObserver.register();
            // Allow user to exit the demo player if setup takes too long
            mHandler.postDelayed(() -> {
                mReadyToTap = true;
            }, READY_TO_TAP_MAX_DELAY_MS);
        }

        loadVideo();
    }

    private void displayFallbackView() {
        if (DEBUG) Log.d(TAG, "Showing the fallback view");
        findViewById(R.id.fallback_layout).setVisibility(View.VISIBLE);
        findViewById(R.id.video_layout).setVisibility(View.GONE);
    }

    private void displayVideoView() {
        if (DEBUG) Log.d(TAG, "Showing the video view");
        findViewById(R.id.video_layout).setVisibility(View.VISIBLE);
        findViewById(R.id.fallback_layout).setVisibility(View.GONE);
    }

    private void loadVideo() {
        // If the video is already downloaded, then use that and check for an update.
        // Otherwise check if the video is preloaded, if not download the video from the
        // specified url.
        boolean isVideoSet = false;
        if (new File(mDownloadPath).exists()) {
            if (DEBUG) Log.d(TAG, "Using the already existing video at " + mDownloadPath);
            setVideoPath(mDownloadPath);
            isVideoSet = true;
        } else if (new File(PRELOADED_VIDEO_FILE).exists()) {
            if (DEBUG) Log.d(TAG, "Using the preloaded video at " + PRELOADED_VIDEO_FILE);
            setVideoPath(PRELOADED_VIDEO_FILE);
            isVideoSet = true;
        }

        final String downloadUrl = getString(R.string.retail_demo_video_download_url);
        // If the download url is empty, then no need to start the download task.
        if (TextUtils.isEmpty(downloadUrl)) {
            if (!isVideoSet) {
                displayFallbackView();
            }
            return;
        }
        if (!checkIfDownloadingAllowed()) {
            if (DEBUG) Log.d(TAG, "Downloading not allowed, neither starting download nor checking"
                    + " for an update.");
            if (!isVideoSet) {
                displayFallbackView();
            }
            return;
        }
        new DownloadVideoTask(this, mDownloadPath, this).run();
    }

    private boolean checkIfDownloadingAllowed() {
        final long lastRealElapsedTime = DataReaderWriter.getElapsedRealTime(this);
        final long realElapsedTime = SystemClock.elapsedRealtime();
        // We need to download the video atmost once after every boot.
        if (lastRealElapsedTime == 0 || realElapsedTime < lastRealElapsedTime) {
            DataReaderWriter.setElapsedRealTime(this,
                    realElapsedTime + REAL_ELAPSED_TIME_OFFSET_MS);
            return true;
        }
        return false;
    }

    @Override
    public void onFileDownloaded(final String filePath) {
        mUsingDownloadedVideo = true;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                setVideoPath(filePath);
            }
        });
    }

    @Override
    public void onError() {
        displayFallbackView();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mReadyToTap && getSystemService(UserManager.class).isDemoUser()) {
            disableSelf();
        }
        return true;
    }

    private void disableSelf() {
        final String componentName = getString(R.string.demo_overlay_app_component);
        if (!TextUtils.isEmpty(componentName)) {
            ComponentName component = ComponentName.unflattenFromString(componentName);
            if (component != null) {
                Intent intent = new Intent();
                intent.setComponent(component);
                ResolveInfo resolveInfo = getPackageManager().resolveService(intent, 0);
                if (resolveInfo != null) {
                    startService(intent);
                } else {
                    resolveInfo = getPackageManager().resolveActivity(intent,
                            PackageManager.MATCH_DEFAULT_ONLY);
                    if (resolveInfo != null) {
                        startActivity(intent);
                    } else {
                        Log.w(TAG, "Component " + componentName + " cannot be resolved");
                    }
                }
            }
        }
        getPackageManager().setComponentEnabledSetting(getComponentName(),
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
    }

    @Override
    public void onPause() {
        if (mVideoView != null) {
            mVideoView.pause();
        }
        // If power key is pressed to turn screen off, turn screen back on
        if (!mPowerManager.isInteractive()) {
            forceTurnOnScreen();
        }
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        // Resume video playing
        if (mVideoView != null) {
            mVideoView.start();
        }
    }

    @Override
    protected void onDestroy() {
        if (mSettingsObserver != null) {
            mSettingsObserver.unregister();
            mSettingsObserver = null;
        }
        super.onDestroy();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        if (hasFocus) {
            // Make view fullscreen.
            // And since flags SYSTEM_UI_FLAG_HIDE_NAVIGATION and SYSTEM_UI_FLAG_HIDE_NAVIGATION
            // might get cleared on user interaction, we do this here.
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                            | View.STATUS_BAR_DISABLE_BACK);
        }
    }

    private void setVideoPath(String videoPath) {
        // Load the video from resource
        try {
            mVideoView.setVideoPath(videoPath);
            displayVideoView();
        } catch (Exception e) {
            Log.e(TAG, "Exception setting video uri! " + e.getMessage());
            displayFallbackView();
        }
    }

    private void forceTurnOnScreen() {
        final PowerManager.WakeLock wakeLock = mPowerManager.newWakeLock(
                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
        wakeLock.acquire();
        // Device woken up, release the wake-lock
        wakeLock.release();
    }

    private class SettingsObserver extends ContentObserver {
        private final Uri mDemoModeSetupComplete = Settings.Secure.getUriFor(
                Settings.Secure.DEMO_USER_SETUP_COMPLETE);

        SettingsObserver() {
            super(mHandler);
        }

        void register() {
            ContentResolver cr = getContentResolver();
            cr.registerContentObserver(mDemoModeSetupComplete, false, this);
        }

        void unregister() {
            getContentResolver().unregisterContentObserver(this);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (mDemoModeSetupComplete.equals(uri)) {
                mReadyToTap = true;
            }
        }
    }

    private boolean isUserSetupComplete() {
        return "1".equals(Settings.Secure.getString(getContentResolver(),
                Settings.Secure.DEMO_USER_SETUP_COMPLETE));
    }
}
