/*
 * Copyright (C) 2015 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.systemui.analytics;

import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;

import android.content.Context;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Toast;

import com.android.systemui.Dependency;
import com.android.systemui.plugins.FalsingPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
 * the data containing these events is saved to a file. This data is collected
 * to analyze how a human interaction looks like.
 *
 * A session starts when the screen is turned on.
 * A session ends when the screen is turned off or user unlocks the phone.
 */
public class DataCollector implements SensorEventListener {
    private static final String TAG = "DataCollector";
    private static final String COLLECTOR_ENABLE = "data_collector_enable";
    private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches";
    private static final String ALLOW_REJECTED_TOUCH_REPORTS =
            "data_collector_allow_rejected_touch_reports";
    private static final String DISABLE_UNLOCKING_FOR_FALSING_COLLECTION =
            "data_collector_disable_unlocking";

    private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
    public static final boolean DEBUG = false;

    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final Context mContext;

    // Err on the side of caution, so logging is not started after a crash even tough the screen
    // is off.
    private SensorLoggerSession mCurrentSession = null;

    private boolean mEnableCollector = false;
    private boolean mCollectBadTouches = false;
    private boolean mCornerSwiping = false;
    private boolean mTrackingStarted = false;
    private boolean mAllowReportRejectedTouch = false;
    private boolean mDisableUnlocking = false;

    private static DataCollector sInstance = null;

    private FalsingPlugin mFalsingPlugin = null;

    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange) {
            updateConfiguration();
        }
    };

    private final PluginListener mPluginListener = new PluginListener<FalsingPlugin>() {
        public void onPluginConnected(FalsingPlugin plugin, Context context) {
            mFalsingPlugin = plugin;
        }

        public void onPluginDisconnected(FalsingPlugin plugin) {
            mFalsingPlugin = null;
        }
    };

    private DataCollector(Context context) {
        mContext = context;

        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(COLLECTOR_ENABLE), false,
                mSettingsObserver,
                UserHandle.USER_ALL);

        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(COLLECT_BAD_TOUCHES), false,
                mSettingsObserver,
                UserHandle.USER_ALL);

        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(ALLOW_REJECTED_TOUCH_REPORTS), false,
                mSettingsObserver,
                UserHandle.USER_ALL);

        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(DISABLE_UNLOCKING_FOR_FALSING_COLLECTION), false,
                mSettingsObserver,
                UserHandle.USER_ALL);

        updateConfiguration();

        Dependency.get(PluginManager.class).addPluginListener(mPluginListener, FalsingPlugin.class);
    }

    public static DataCollector getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new DataCollector(context);
        }
        return sInstance;
    }

    private void updateConfiguration() {
        mEnableCollector = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
                mContext.getContentResolver(),
                COLLECTOR_ENABLE, 0);
        mCollectBadTouches = mEnableCollector && 0 != Settings.Secure.getInt(
                mContext.getContentResolver(),
                COLLECT_BAD_TOUCHES, 0);
        mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
                mContext.getContentResolver(),
                ALLOW_REJECTED_TOUCH_REPORTS, 0);
        mDisableUnlocking = mEnableCollector && Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
                mContext.getContentResolver(),
                DISABLE_UNLOCKING_FOR_FALSING_COLLECTION, 0);
    }

    private boolean sessionEntrypoint() {
        if (isEnabled() && mCurrentSession == null) {
            onSessionStart();
            return true;
        }
        return false;
    }

    private void sessionExitpoint(int result) {
        if (mCurrentSession != null) {
            onSessionEnd(result);
        }
    }

    private void onSessionStart() {
        mCornerSwiping = false;
        mTrackingStarted = false;
        mCurrentSession = new SensorLoggerSession(System.currentTimeMillis(), System.nanoTime());
    }

    private void onSessionEnd(int result) {
        SensorLoggerSession session = mCurrentSession;
        mCurrentSession = null;

        if (mEnableCollector || mDisableUnlocking) {
            session.end(System.currentTimeMillis(), result);
            queueSession(session);
        }
    }

    public Uri reportRejectedTouch() {
        if (mCurrentSession == null) {
            Toast.makeText(mContext, "Generating rejected touch report failed: session timed out.",
                    Toast.LENGTH_LONG).show();
            return null;
        }
        SensorLoggerSession currentSession = mCurrentSession;

        currentSession.setType(Session.REJECTED_TOUCH_REPORT);
        currentSession.end(System.currentTimeMillis(), Session.SUCCESS);
        Session proto = currentSession.toProto();

        byte[] b = Session.toByteArray(proto);
        File dir = new File(mContext.getExternalCacheDir(), "rejected_touch_reports");
        dir.mkdir();
        File touch = new File(dir, "rejected_touch_report_" + System.currentTimeMillis());

        try {
            new FileOutputStream(touch).write(b);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return Uri.fromFile(touch);
    }

    private void queueSession(final SensorLoggerSession currentSession) {
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                byte[] b = Session.toByteArray(currentSession.toProto());

                if (mFalsingPlugin != null) {
                    mFalsingPlugin.dataCollected(currentSession.getResult() == Session.SUCCESS, b);
                } else {
                    String dir = mContext.getFilesDir().getAbsolutePath();
                    if (currentSession.getResult() != Session.SUCCESS) {
                        if (!mDisableUnlocking && !mCollectBadTouches) {
                            return;
                        }
                        dir += "/bad_touches";
                    } else if (!mDisableUnlocking) {
                        dir += "/good_touches";
                    }

                    File file = new File(dir);
                    file.mkdir();
                    File touch = new File(file, "trace_" + System.currentTimeMillis());
                    try {
                        new FileOutputStream(touch).write(b);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
    }

    @Override
    public synchronized void onSensorChanged(SensorEvent event) {
        if (isEnabled() && mCurrentSession != null) {
            mCurrentSession.addSensorEvent(event, System.nanoTime());
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    /**
     * @return true if data is being collected - either for data gathering or creating a
     *         rejected touch report.
     */
    public boolean isEnabled() {
        return mEnableCollector || mAllowReportRejectedTouch || mDisableUnlocking;
    }

    public boolean isUnlockingDisabled() {
        return mDisableUnlocking;
    }
    /**
     * @return true if the full data set for data gathering should be collected - including
     *         extensive sensor data, which is is not normally included with rejected touch reports.
     */
    public boolean isEnabledFull() {
        return mEnableCollector;
    }

    public void onScreenTurningOn() {
        if (sessionEntrypoint()) {
            if (DEBUG) {
                Log.d(TAG, "onScreenTurningOn");
            }
            addEvent(PhoneEvent.ON_SCREEN_ON);
        }
    }

    public void onScreenOnFromTouch() {
        if (sessionEntrypoint()) {
            if (DEBUG) {
                Log.d(TAG, "onScreenOnFromTouch");
            }
            addEvent(PhoneEvent.ON_SCREEN_ON_FROM_TOUCH);
        }
    }

    public void onScreenOff() {
        if (DEBUG) {
            Log.d(TAG, "onScreenOff");
        }
        addEvent(PhoneEvent.ON_SCREEN_OFF);
        sessionExitpoint(Session.FAILURE);
    }

    public void onSucccessfulUnlock() {
        if (DEBUG) {
            Log.d(TAG, "onSuccessfulUnlock");
        }
        addEvent(PhoneEvent.ON_SUCCESSFUL_UNLOCK);
        sessionExitpoint(Session.SUCCESS);
    }

    public void onBouncerShown() {
        if (DEBUG) {
            Log.d(TAG, "onBouncerShown");
        }
        addEvent(PhoneEvent.ON_BOUNCER_SHOWN);
    }

    public void onBouncerHidden() {
        if (DEBUG) {
            Log.d(TAG, "onBouncerHidden");
        }
        addEvent(PhoneEvent.ON_BOUNCER_HIDDEN);
    }

    public void onQsDown() {
        if (DEBUG) {
            Log.d(TAG, "onQsDown");
        }
        addEvent(PhoneEvent.ON_QS_DOWN);
    }

    public void setQsExpanded(boolean expanded) {
        if (DEBUG) {
            Log.d(TAG, "setQsExpanded = " + expanded);
        }
        if (expanded) {
            addEvent(PhoneEvent.SET_QS_EXPANDED_TRUE);
        } else {
            addEvent(PhoneEvent.SET_QS_EXPANDED_FALSE);
        }
    }

    public void onTrackingStarted() {
        if (DEBUG) {
            Log.d(TAG, "onTrackingStarted");
        }
        mTrackingStarted = true;
        addEvent(PhoneEvent.ON_TRACKING_STARTED);
    }

    public void onTrackingStopped() {
        if (mTrackingStarted) {
            if (DEBUG) {
                Log.d(TAG, "onTrackingStopped");
            }
            mTrackingStarted = false;
            addEvent(PhoneEvent.ON_TRACKING_STOPPED);
        }
    }

    public void onNotificationActive() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationActive");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_ACTIVE);
    }


    public void onNotificationDoubleTap() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationDoubleTap");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_DOUBLE_TAP);
    }

    public void setNotificationExpanded() {
        if (DEBUG) {
            Log.d(TAG, "setNotificationExpanded");
        }
        addEvent(PhoneEvent.SET_NOTIFICATION_EXPANDED);
    }

    public void onNotificatonStartDraggingDown() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationStartDraggingDown");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_START_DRAGGING_DOWN);
    }

    public void onNotificatonStopDraggingDown() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationStopDraggingDown");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DRAGGING_DOWN);
    }

    public void onNotificationDismissed() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationDismissed");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_DISMISSED);
    }

    public void onNotificatonStartDismissing() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationStartDismissing");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_START_DISMISSING);
    }

    public void onNotificatonStopDismissing() {
        if (DEBUG) {
            Log.d(TAG, "onNotificationStopDismissing");
        }
        addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DISMISSING);
    }

    public void onCameraOn() {
        if (DEBUG) {
            Log.d(TAG, "onCameraOn");
        }
        addEvent(PhoneEvent.ON_CAMERA_ON);
    }

    public void onLeftAffordanceOn() {
        if (DEBUG) {
            Log.d(TAG, "onLeftAffordanceOn");
        }
        addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_ON);
    }

    public void onAffordanceSwipingStarted(boolean rightCorner) {
        if (DEBUG) {
            Log.d(TAG, "onAffordanceSwipingStarted");
        }
        mCornerSwiping = true;
        if (rightCorner) {
            addEvent(PhoneEvent.ON_RIGHT_AFFORDANCE_SWIPING_STARTED);
        } else {
            addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_SWIPING_STARTED);
        }
    }

    public void onAffordanceSwipingAborted() {
        if (mCornerSwiping) {
            if (DEBUG) {
                Log.d(TAG, "onAffordanceSwipingAborted");
            }
            mCornerSwiping = false;
            addEvent(PhoneEvent.ON_AFFORDANCE_SWIPING_ABORTED);
        }
    }

    public void onUnlockHintStarted() {
        if (DEBUG) {
            Log.d(TAG, "onUnlockHintStarted");
        }
        addEvent(PhoneEvent.ON_UNLOCK_HINT_STARTED);
    }

    public void onCameraHintStarted() {
        if (DEBUG) {
            Log.d(TAG, "onCameraHintStarted");
        }
        addEvent(PhoneEvent.ON_CAMERA_HINT_STARTED);
    }

    public void onLeftAffordanceHintStarted() {
        if (DEBUG) {
            Log.d(TAG, "onLeftAffordanceHintStarted");
        }
        addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_HINT_STARTED);
    }

    public void onTouchEvent(MotionEvent event, int width, int height) {
        if (mCurrentSession != null) {
            if (DEBUG) {
                Log.v(TAG, "onTouchEvent(ev.action="
                        + MotionEvent.actionToString(event.getAction()) + ")");
            }
            mCurrentSession.addMotionEvent(event);
            mCurrentSession.setTouchArea(width, height);
        }
    }

    private void addEvent(int eventType) {
        if (isEnabled() && mCurrentSession != null) {
            mCurrentSession.addPhoneEvent(eventType, System.nanoTime());
        }
    }

    public boolean isReportingEnabled() {
        return mAllowReportRejectedTouch;
    }

    public void onFalsingSessionStarted() {
        sessionEntrypoint();
    }
}
