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

import android.annotation.NonNull;
import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.telecom.Log;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Provides various system states to the rest of the telecom codebase.
 */
public class SystemStateHelper implements UiModeManager.OnProjectionStateChangedListener {
    public interface SystemStateListener {
        /**
         * Listener method to inform interested parties when a package name requests to enter or
         * exit car mode.
         * @param priority the priority of the enter/exit request.
         * @param packageName the package name of the requester.
         * @param isCarMode {@code true} if the package is entering car mode, {@code false}
         *                              otherwise.
         */
        void onCarModeChanged(int priority, String packageName, boolean isCarMode);

        /**
         * Listener method to inform interested parties when a package has set automotive projection
         * state.
         * @param automotiveProjectionPackage the package that set automotive projection.
         */
        void onAutomotiveProjectionStateSet(String automotiveProjectionPackage);

        /**
         * Listener method to inform interested parties when automotive projection state has been
         * cleared.
         */
        void onAutomotiveProjectionStateReleased();

        /**
         * Notifies when a package has been uninstalled.
         * @param packageName the package name of the uninstalled package
         */
        void onPackageUninstalled(String packageName);
    }

    private final Context mContext;
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.startSession("SSH.oR");
            try {
                synchronized (mLock) {
                    String action = intent.getAction();
                    if (UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED.equals(action)) {
                        int priority = intent.getIntExtra(UiModeManager.EXTRA_PRIORITY,
                                UiModeManager.DEFAULT_PRIORITY);
                        String callingPackage = intent.getStringExtra(
                                UiModeManager.EXTRA_CALLING_PACKAGE);
                        Log.i(SystemStateHelper.this,
                                "ENTER_CAR_MODE_PRIORITIZED; priority=%d, pkg=%s",
                                priority, callingPackage);
                        onEnterCarMode(priority, callingPackage);
                    } else if (UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED.equals(action)) {
                        int priority = intent.getIntExtra(UiModeManager.EXTRA_PRIORITY,
                                UiModeManager.DEFAULT_PRIORITY);
                        String callingPackage = intent.getStringExtra(
                                UiModeManager.EXTRA_CALLING_PACKAGE);
                        Log.i(SystemStateHelper.this,
                                "EXIT_CAR_MODE_PRIORITIZED; priority=%d, pkg=%s",
                                priority, callingPackage);
                        onExitCarMode(priority, callingPackage);
                    } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
                        Uri data = intent.getData();
                        if (data == null) {
                            Log.w(SystemStateHelper.this,
                                    "Got null data for package removed, ignoring");
                            return;
                        }
                        mListeners.forEach(
                                l -> l.onPackageUninstalled(data.getEncodedSchemeSpecificPart()));
                    } else {
                        Log.w(SystemStateHelper.this,
                                "Unexpected intent received: %s", intent.getAction());
                    }
                }
            } finally {
                Log.endSession();
            }
        }
    };

    @Override
    public void onProjectionStateChanged(int activeProjectionTypes,
            @NonNull Set<String> projectingPackages) {
        Log.startSession("SSH.oPSC");
        try {
            synchronized (mLock) {
                if (projectingPackages.isEmpty()) {
                    onReleaseAutomotiveProjection();
                } else {
                    onSetAutomotiveProjection(projectingPackages.iterator().next());
                }
            }
        } finally {
            Log.endSession();
        }

    }

    private Set<SystemStateListener> mListeners = new CopyOnWriteArraySet<>();
    private boolean mIsCarModeOrProjectionActive;
    private final TelecomSystem.SyncRoot mLock;

    public SystemStateHelper(Context context, TelecomSystem.SyncRoot lock) {
        mContext = context;
        mLock = lock;

        IntentFilter intentFilter1 = new IntentFilter(
                UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED);
        intentFilter1.addAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);

        IntentFilter intentFilter2 = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter2.addDataScheme("package");
        mContext.registerReceiver(mBroadcastReceiver, intentFilter1);
        mContext.registerReceiver(mBroadcastReceiver, intentFilter2);
        Log.i(this, "Registering broadcast receiver: %s", intentFilter1);
        Log.i(this, "Registering broadcast receiver: %s", intentFilter2);

        mContext.getSystemService(UiModeManager.class).addOnProjectionStateChangedListener(
                UiModeManager.PROJECTION_TYPE_AUTOMOTIVE, mContext.getMainExecutor(), this);
        mIsCarModeOrProjectionActive = getSystemCarModeOrProjectionState();
    }

    public void addListener(SystemStateListener listener) {
        if (listener != null) {
            mListeners.add(listener);
        }
    }

    public boolean removeListener(SystemStateListener listener) {
        return mListeners.remove(listener);
    }

    public boolean isCarModeOrProjectionActive() {
        return mIsCarModeOrProjectionActive;
    }

    public boolean isDeviceAtEar() {
        return isDeviceAtEar(mContext);
    }

    /**
     * Returns a guess whether the phone is up to the user's ear. Use the proximity sensor and
     * the gravity sensor to make a guess
     * @return true if the proximity sensor is activated, the magnitude of gravity in directions
     *         parallel to the screen is greater than some configurable threshold, and the
     *         y-component of gravity isn't less than some other configurable threshold.
     */
    public static boolean isDeviceAtEar(Context context) {
        SensorManager sm = context.getSystemService(SensorManager.class);
        if (sm == null) {
            return false;
        }
        Sensor grav = sm.getDefaultSensor(Sensor.TYPE_GRAVITY);
        Sensor proximity = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        if (grav == null || proximity == null) {
            return false;
        }

        AtomicBoolean result = new AtomicBoolean(true);
        CountDownLatch gravLatch = new CountDownLatch(1);
        CountDownLatch proxLatch = new CountDownLatch(1);

        final double xyGravityThreshold = context.getResources().getFloat(
                R.dimen.device_on_ear_xy_gravity_threshold);
        final double yGravityNegativeThreshold = context.getResources().getFloat(
                R.dimen.device_on_ear_y_gravity_negative_threshold);

        SensorEventListener listener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
                    if (gravLatch.getCount() == 0) {
                        return;
                    }
                    double xyMag = Math.sqrt(event.values[0] * event.values[0]
                            + event.values[1] * event.values[1]);
                    if (xyMag < xyGravityThreshold
                            || event.values[1] < yGravityNegativeThreshold) {
                        result.set(false);
                    }
                    gravLatch.countDown();
                } else if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
                    if (proxLatch.getCount() == 0) {
                        return;
                    }
                    if (event.values[0] >= proximity.getMaximumRange()) {
                        result.set(false);
                    }
                    proxLatch.countDown();
                }
            }

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

        try {
            sm.registerListener(listener, grav, SensorManager.SENSOR_DELAY_FASTEST);
            sm.registerListener(listener, proximity, SensorManager.SENSOR_DELAY_FASTEST);
            boolean accelValid = gravLatch.await(100, TimeUnit.MILLISECONDS);
            boolean proxValid = proxLatch.await(100, TimeUnit.MILLISECONDS);
            if (accelValid && proxValid) {
                return result.get();
            } else {
                Log.w(SystemStateHelper.class.getSimpleName(),
                        "Timed out waiting for sensors: %b %b", accelValid, proxValid);
                return false;
            }
        } catch (InterruptedException e) {
            return false;
        } finally {
            sm.unregisterListener(listener);
        }
    }

    private void onEnterCarMode(int priority, String packageName) {
        Log.i(this, "Entering carmode");
        mIsCarModeOrProjectionActive = getSystemCarModeOrProjectionState();
        for (SystemStateListener listener : mListeners) {
            listener.onCarModeChanged(priority, packageName, true /* isCarMode */);
        }
    }

    private void onExitCarMode(int priority, String packageName) {
        Log.i(this, "Exiting carmode");
        mIsCarModeOrProjectionActive = getSystemCarModeOrProjectionState();
        for (SystemStateListener listener : mListeners) {
            listener.onCarModeChanged(priority, packageName, false /* isCarMode */);
        }
    }

    private void onSetAutomotiveProjection(String packageName) {
        Log.i(this, "Automotive projection set.");
        mIsCarModeOrProjectionActive = getSystemCarModeOrProjectionState();
        for (SystemStateListener listener : mListeners) {
            listener.onAutomotiveProjectionStateSet(packageName);
        }

    }

    private void onReleaseAutomotiveProjection() {
        Log.i(this, "Automotive projection released.");
        mIsCarModeOrProjectionActive = getSystemCarModeOrProjectionState();
        for (SystemStateListener listener : mListeners) {
            listener.onAutomotiveProjectionStateReleased();
        }
    }

    /**
     * Checks the system for the current car projection state.
     *
     * @return True if projection is active, false otherwise.
     */
    private boolean getSystemCarModeOrProjectionState() {
        UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);

        if (uiModeManager != null) {
            return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
                    || (uiModeManager.getActiveProjectionTypes()
                            & UiModeManager.PROJECTION_TYPE_AUTOMOTIVE) != 0;
        }

        Log.w(this, "Got null UiModeManager, returning false.");
        return false;
    }
}
