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

import android.content.Context;
import android.hardware.location.GeofenceHardware;
import android.hardware.location.GeofenceHardwareImpl;
import android.hardware.location.GeofenceHardwareRequestParcelable;
import android.hardware.location.IFusedLocationHardware;
import android.hardware.location.IFusedLocationHardwareSink;
import android.location.FusedBatchOptions;
import android.location.IFusedGeofenceHardware;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.os.Bundle;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;

/**
 * This class is an interop layer for JVM types and the JNI code that interacts
 * with the FLP HAL implementation.
 *
 * {@hide}
 */
public class FlpHardwareProvider {
    private static final int FIRST_VERSION_WITH_FLUSH_LOCATIONS = 2;
    private GeofenceHardwareImpl mGeofenceHardwareSink = null;
    private IFusedLocationHardwareSink mLocationSink = null;
    // Capabilities provided by FlpCallbacks
    private boolean mHaveBatchingCapabilities;
    private int mBatchingCapabilities;
    private int mVersion = 1;

    private static FlpHardwareProvider sSingletonInstance = null;

    private final static String TAG = "FlpHardwareProvider";
    private final Context mContext;
    private final Object mLocationSinkLock = new Object();

    // FlpHal result codes, they must be equal to the ones in fused_location.h
    private static final int FLP_RESULT_SUCCESS = 0;
    private static final int FLP_RESULT_ERROR = -1;
    private static final int FLP_RESULT_INSUFFICIENT_MEMORY = -2;
    private static final int FLP_RESULT_TOO_MANY_GEOFENCES = -3;
    private static final int FLP_RESULT_ID_EXISTS = -4;
    private static final int FLP_RESULT_ID_UNKNOWN = -5;
    private static final int FLP_RESULT_INVALID_GEOFENCE_TRANSITION = -6;

    // FlpHal monitor status codes, they must be equal to the ones in fused_location.h
    private static final int FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE = 1<<0;
    private static final int FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE = 1<<1;

    public static FlpHardwareProvider getInstance(Context context) {
        if (sSingletonInstance == null) {
            sSingletonInstance = new FlpHardwareProvider(context);
            sSingletonInstance.nativeInit();
        }

        return sSingletonInstance;
    }

    private FlpHardwareProvider(Context context) {
        mContext = context;

        // register for listening for passive provider data
        LocationManager manager = (LocationManager) mContext.getSystemService(
                Context.LOCATION_SERVICE);
        final long minTime = 0;
        final float minDistance = 0;
        final boolean oneShot = false;
        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
                LocationManager.PASSIVE_PROVIDER,
                minTime,
                minDistance,
                oneShot);
        // Don't keep track of this request since it's done on behalf of other clients
        // (which are kept track of separately).
        request.setHideFromAppOps(true);
        manager.requestLocationUpdates(
                request,
                new NetworkLocationListener(),
                Looper.myLooper());
    }

    public static boolean isSupported() {
        return nativeIsSupported();
    }

    /**
     * Private callback functions used by FLP HAL.
     */
    // FlpCallbacks members
    private void onLocationReport(Location[] locations) {
        for (Location location : locations) {
            location.setProvider(LocationManager.FUSED_PROVIDER);
            // set the elapsed time-stamp just as GPS provider does
            location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
        }

        IFusedLocationHardwareSink sink;
        synchronized (mLocationSinkLock) {
            sink = mLocationSink;
        }
        try {
            if (sink != null) {
                sink.onLocationAvailable(locations);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException calling onLocationAvailable");
        }
    }

    private void onBatchingCapabilities(int capabilities) {
        synchronized (mLocationSinkLock) {
            mHaveBatchingCapabilities = true;
            mBatchingCapabilities = capabilities;
        }

        maybeSendCapabilities();

        if (mGeofenceHardwareSink != null) {
            mGeofenceHardwareSink.setVersion(getVersion());
        }
    }

    private void onBatchingStatus(int status) {
        IFusedLocationHardwareSink sink;
        synchronized (mLocationSinkLock) {
            sink = mLocationSink;
        }
        try {
            if (sink != null) {
                sink.onStatusChanged(status);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException calling onBatchingStatus");
        }
    }

    // Returns the current version of the FLP HAL.  This depends both on the version of the
    // structure returned by the hardware layer, and whether or not we've received the
    // capabilities callback on initialization.  Assume original version until we get
    // the new initialization callback.
    private int getVersion() {
        synchronized (mLocationSinkLock) {
            if (mHaveBatchingCapabilities) {
                return mVersion;
            }
        }
        return 1;
    }

    private void setVersion(int version) {
        mVersion = version;
        if (mGeofenceHardwareSink != null) {
            mGeofenceHardwareSink.setVersion(getVersion());
        }
    }

    private void maybeSendCapabilities() {
        IFusedLocationHardwareSink sink;
        boolean haveBatchingCapabilities;
        int batchingCapabilities;
        synchronized (mLocationSinkLock) {
            sink = mLocationSink;
            haveBatchingCapabilities = mHaveBatchingCapabilities;
            batchingCapabilities = mBatchingCapabilities;
        }
        try {
            if (sink != null && haveBatchingCapabilities) {
                sink.onCapabilities(batchingCapabilities);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException calling onLocationAvailable");
        }
    }

    // FlpDiagnosticCallbacks members
    private void onDataReport(String data) {
        IFusedLocationHardwareSink sink;
        synchronized (mLocationSinkLock) {
            sink = mLocationSink;
        }
        try {
            if (mLocationSink != null) {
                sink.onDiagnosticDataAvailable(data);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
        }
    }

    // FlpGeofenceCallbacks members
    private void onGeofenceTransition(
            int geofenceId,
            Location location,
            int transition,
            long timestamp,
            int sourcesUsed) {
        // the transition Id does not require translation because the values in fused_location.h
        // and GeofenceHardware are in sync
        getGeofenceHardwareSink().reportGeofenceTransition(
                geofenceId,
                updateLocationInformation(location),
                transition,
                timestamp,
                GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
                sourcesUsed);
    }

    private void onGeofenceMonitorStatus(int status, int source, Location location) {
        // allow the location to be optional in this event
        Location updatedLocation = null;
        if(location != null) {
            updatedLocation = updateLocationInformation(location);
        }

        int monitorStatus;
        switch (status) {
            case FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE:
                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
                break;
            case FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE:
                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
                break;
            default:
                Log.e(TAG, "Invalid FlpHal Geofence monitor status: " + status);
                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
                break;
        }

        getGeofenceHardwareSink().reportGeofenceMonitorStatus(
                GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
                monitorStatus,
                updatedLocation,
                source);
    }

    private void onGeofenceAdd(int geofenceId, int result) {
        getGeofenceHardwareSink().reportGeofenceAddStatus(
                geofenceId,
                translateToGeofenceHardwareStatus(result));
    }

    private void onGeofenceRemove(int geofenceId, int result) {
        getGeofenceHardwareSink().reportGeofenceRemoveStatus(
                geofenceId,
                translateToGeofenceHardwareStatus(result));
    }

    private void onGeofencePause(int geofenceId, int result) {
        getGeofenceHardwareSink().reportGeofencePauseStatus(
                geofenceId,
                translateToGeofenceHardwareStatus(result));
    }

    private void onGeofenceResume(int geofenceId, int result) {
        getGeofenceHardwareSink().reportGeofenceResumeStatus(
                geofenceId,
                translateToGeofenceHardwareStatus(result));
    }

    private void onGeofencingCapabilities(int capabilities) {
        getGeofenceHardwareSink().onCapabilities(capabilities);
    }

    /**
     * Private native methods accessing FLP HAL.
     */
    static { nativeClassInit(); }

    // Core members
    private static native void nativeClassInit();
    private static native boolean nativeIsSupported();

    // FlpLocationInterface members
    private native void nativeInit();
    private native int nativeGetBatchSize();
    private native void nativeStartBatching(int requestId, FusedBatchOptions options);
    private native void nativeUpdateBatchingOptions(int requestId, FusedBatchOptions optionsObject);
    private native void nativeStopBatching(int id);
    private native void nativeRequestBatchedLocation(int lastNLocations);
    private native void nativeFlushBatchedLocations();
    private native void nativeInjectLocation(Location location);
    private native void nativeCleanup();

    // FlpDiagnosticsInterface members
    private native boolean nativeIsDiagnosticSupported();
    private native void nativeInjectDiagnosticData(String data);

    // FlpDeviceContextInterface members
    private native boolean nativeIsDeviceContextSupported();
    private native void nativeInjectDeviceContext(int deviceEnabledContext);

    // FlpGeofencingInterface members
    private native boolean nativeIsGeofencingSupported();
    private native void nativeAddGeofences(
            GeofenceHardwareRequestParcelable[] geofenceRequestsArray);
    private native void nativePauseGeofence(int geofenceId);
    private native void  nativeResumeGeofence(int geofenceId, int monitorTransitions);
    private native void nativeModifyGeofenceOption(
        int geofenceId,
        int lastTransition,
        int monitorTransitions,
        int notificationResponsiveness,
        int unknownTimer,
        int sourcesToUse);
    private native void nativeRemoveGeofences(int[] geofenceIdsArray);

    /**
     * Interface implementations for services built on top of this functionality.
     */
    public static final String LOCATION = "Location";
    public static final String GEOFENCING = "Geofencing";

    public IFusedLocationHardware getLocationHardware() {
        return mLocationHardware;
    }

    public IFusedGeofenceHardware getGeofenceHardware() {
        return mGeofenceHardwareService;
    }

    public void cleanup() {
        Log.i(TAG, "Calling nativeCleanup()");
        nativeCleanup();
    }

    private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() {
        @Override
        public void registerSink(IFusedLocationHardwareSink eventSink) {
            synchronized (mLocationSinkLock) {
                // only one sink is allowed at the moment
                if (mLocationSink != null) {
                    Log.e(TAG, "Replacing an existing IFusedLocationHardware sink");
                }

                mLocationSink = eventSink;
            }
            maybeSendCapabilities();
        }

        @Override
        public void unregisterSink(IFusedLocationHardwareSink eventSink) {
            synchronized (mLocationSinkLock) {
                // don't throw if the sink is not registered, simply make it a no-op
                if (mLocationSink == eventSink) {
                    mLocationSink = null;
                }
            }
        }

        @Override
        public int getSupportedBatchSize() {
            return nativeGetBatchSize();
        }

        @Override
        public void startBatching(int requestId, FusedBatchOptions options) {
            nativeStartBatching(requestId, options);
        }

        @Override
        public void stopBatching(int requestId) {
            nativeStopBatching(requestId);
        }

        @Override
        public void updateBatchingOptions(int requestId, FusedBatchOptions options) {
            nativeUpdateBatchingOptions(requestId, options);
        }

        @Override
        public void requestBatchOfLocations(int batchSizeRequested) {
            nativeRequestBatchedLocation(batchSizeRequested);
        }

        @Override
        public void flushBatchedLocations() {
            if (getVersion() >= FIRST_VERSION_WITH_FLUSH_LOCATIONS) {
                nativeFlushBatchedLocations();
            } else {
                Log.wtf(TAG,
                        "Tried to call flushBatchedLocations on an unsupported implementation");
            }
        }

        @Override
        public boolean supportsDiagnosticDataInjection() {
            return nativeIsDiagnosticSupported();
        }

        @Override
        public void injectDiagnosticData(String data) {
            nativeInjectDiagnosticData(data);
        }

        @Override
        public boolean supportsDeviceContextInjection() {
            return nativeIsDeviceContextSupported();
        }

        @Override
        public void injectDeviceContext(int deviceEnabledContext) {
            nativeInjectDeviceContext(deviceEnabledContext);
        }

        @Override
        public int getVersion() {
            return FlpHardwareProvider.this.getVersion();
        }
    };

    private final IFusedGeofenceHardware mGeofenceHardwareService =
            new IFusedGeofenceHardware.Stub() {
        @Override
        public boolean isSupported() {
            return nativeIsGeofencingSupported();
        }

        @Override
        public void addGeofences(GeofenceHardwareRequestParcelable[] geofenceRequestsArray) {
            nativeAddGeofences(geofenceRequestsArray);
        }

        @Override
        public void removeGeofences(int[] geofenceIds) {
            nativeRemoveGeofences(geofenceIds);
        }

        @Override
        public void pauseMonitoringGeofence(int geofenceId) {
            nativePauseGeofence(geofenceId);
        }

        @Override
        public void resumeMonitoringGeofence(int geofenceId, int monitorTransitions) {
            nativeResumeGeofence(geofenceId, monitorTransitions);
        }

        @Override
        public void modifyGeofenceOptions(int geofenceId,
                int lastTransition,
                int monitorTransitions,
                int notificationResponsiveness,
                int unknownTimer,
                int sourcesToUse) {
            nativeModifyGeofenceOption(
                    geofenceId,
                    lastTransition,
                    monitorTransitions,
                    notificationResponsiveness,
                    unknownTimer,
                    sourcesToUse);
        }
    };

    /**
     * Internal classes and functions used by the provider.
     */
    private final class NetworkLocationListener implements LocationListener {
        @Override
        public void onLocationChanged(Location location) {
            if (
                !LocationManager.NETWORK_PROVIDER.equals(location.getProvider()) ||
                !location.hasAccuracy()
                ) {
                return;
            }

            nativeInjectLocation(location);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) { }

        @Override
        public void onProviderEnabled(String provider) { }

        @Override
        public void onProviderDisabled(String provider) { }
    }

    private GeofenceHardwareImpl getGeofenceHardwareSink() {
        if (mGeofenceHardwareSink == null) {
            mGeofenceHardwareSink = GeofenceHardwareImpl.getInstance(mContext);
            mGeofenceHardwareSink.setVersion(getVersion());
        }

        return mGeofenceHardwareSink;
    }

    private static int translateToGeofenceHardwareStatus(int flpHalResult) {
        switch(flpHalResult) {
            case FLP_RESULT_SUCCESS:
                return GeofenceHardware.GEOFENCE_SUCCESS;
            case FLP_RESULT_ERROR:
                return GeofenceHardware.GEOFENCE_FAILURE;
            case FLP_RESULT_INSUFFICIENT_MEMORY:
                return GeofenceHardware.GEOFENCE_ERROR_INSUFFICIENT_MEMORY;
            case FLP_RESULT_TOO_MANY_GEOFENCES:
                return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
            case FLP_RESULT_ID_EXISTS:
                return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
            case FLP_RESULT_ID_UNKNOWN:
                return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
            case FLP_RESULT_INVALID_GEOFENCE_TRANSITION:
                return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
            default:
                Log.e(TAG, String.format("Invalid FlpHal result code: %d", flpHalResult));
                return GeofenceHardware.GEOFENCE_FAILURE;
        }
    }

    private Location updateLocationInformation(Location location) {
        location.setProvider(LocationManager.FUSED_PROVIDER);
        // set the elapsed time-stamp just as GPS provider does
        location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
        return location;
    }
}
