/*
 * 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 android.hardware.location;

import android.location.Location;
import android.os.RemoteException;

import java.lang.ref.WeakReference;
import java.util.HashMap;

/**
 * This class handles geofences managed by various hardware subsystems. It contains
 * the public APIs that is needed to accomplish the task.
 *
 * <p>The APIs should not be called directly by the app developers. A higher level api
 * which abstracts the hardware should be used instead. All the checks are done by the higher
 * level public API. Any needed locking should be handled by the higher level API.
 *
 * <p> There are 3 states associated with a Geofence: Inside, Outside, Unknown.
 * There are 3 transitions: {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED},
 * {@link #GEOFENCE_UNCERTAIN}. The APIs only expose the transitions.
 *
 * <p> Inside state: The hardware subsystem is reasonably confident that the user is inside
 * the geofence. Outside state: The hardware subsystem is reasonably confident that the user
 * is outside the geofence Unknown state: Unknown state can be interpreted as a state in which the
 * monitoring subsystem isn't confident enough that the user is either inside or
 * outside the Geofence. If the accuracy does not improve for a sufficient period of time,
 * the {@link #GEOFENCE_UNCERTAIN} transition would be triggered. If the accuracy improves later,
 * an appropriate transition would be triggered. The "reasonably confident" parameter
 * depends on the hardware system and the positioning algorithms used.
 * For instance, {@link #MONITORING_TYPE_GPS_HARDWARE} uses 95% as a confidence level.
 */
public final class GeofenceHardware {
    private IGeofenceHardware mService;

    // Hardware systems that do geofence monitoring.
    static final int NUM_MONITORS = 2;

    /**
     * Constant for geofence monitoring done by the GPS hardware.
     */
    public static final int MONITORING_TYPE_GPS_HARDWARE = 0;

    /**
     * Constant for geofence monitoring done by the Fused hardware.
     *
     * @hide
     */
    public static final int MONITORING_TYPE_FUSED_HARDWARE = 1;

    /**
     * Constant to indiciate that the monitoring system is currently
     * available for monitoring geofences.
     */
    public static final int MONITOR_CURRENTLY_AVAILABLE = 0;

    /**
     * Constant to indiciate that the monitoring system is currently
     * unavailable for monitoring geofences.
     */
    public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1;

    /**
     * Constant to indiciate that the monitoring system is unsupported
     * for hardware geofence monitoring.
     */
    public static final int MONITOR_UNSUPPORTED = 2;

    // The following constants need to match geofence flags in gps.h
    /**
     * The constant to indicate that the user has entered the geofence.
     */
    public static final int GEOFENCE_ENTERED = 1<<0L;

    /**
     * The constant to indicate that the user has exited the geofence.
     */
    public static final int GEOFENCE_EXITED = 1<<1L;

    /**
     * The constant to indicate that the user is uncertain with respect to a
     * geofence.                                                  nn
     */
    public static final int GEOFENCE_UNCERTAIN = 1<<2L;

    /**
     * The constant used to indicate success of the particular geofence call
     */
    public static final int GEOFENCE_SUCCESS = 0;

    /**
     * The constant used to indicate that too many geofences have been registered.
     */
    public static final int GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 1;

    /**
     * The constant used to indicate that the geofence id already exists.
     */
    public static final int GEOFENCE_ERROR_ID_EXISTS  = 2;

    /**
     * The constant used to indicate that the geofence id is unknown.
     */
    public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3;

    /**
     * The constant used to indicate that the transition requested for the geofence is invalid.
     */
    public static final int GEOFENCE_ERROR_INVALID_TRANSITION = 4;

    /**
     * The constant used to indicate that the geofence operation has failed.
     */
    public static final int GEOFENCE_FAILURE = 5;

    /**
     * The constant used to indicate that the operation failed due to insufficient memory.
     *
     * @hide
     */
    public static final int GEOFENCE_ERROR_INSUFFICIENT_MEMORY = 6;

    private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>
            mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>();
    private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
            mMonitorCallbacks = new HashMap<GeofenceHardwareMonitorCallback,
                    GeofenceHardwareMonitorCallbackWrapper>();
    /**
     * @hide
     */
    public GeofenceHardware(IGeofenceHardware service) {
        mService = service;
    }

    /**
     * Returns all the hardware geofence monitoring systems which are supported
     *
     * <p> Call {@link #getStatusOfMonitoringType(int)} to know the current state
     * of a monitoring system.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * @return An array of all the monitoring types.
     *         An array of length 0 is returned in case of errors.
     */
    public int[] getMonitoringTypes() {
        try {
            return mService.getMonitoringTypes();
        } catch (RemoteException e) {
        }
        return new int[0];
    }

    /**
     * Returns current status of a hardware geofence monitoring system.
     *
     * <p>Status can be one of {@link #MONITOR_CURRENTLY_AVAILABLE},
     * {@link #MONITOR_CURRENTLY_UNAVAILABLE} or {@link #MONITOR_UNSUPPORTED}
     *
     * <p> Some supported hardware monitoring systems might not be available
     * for monitoring geofences in certain scenarios. For example, when a user
     * enters a building, the GPS hardware subsystem might not be able monitor
     * geofences and will change from {@link #MONITOR_CURRENTLY_AVAILABLE} to
     * {@link #MONITOR_CURRENTLY_UNAVAILABLE}.
     *
     * @param monitoringType
     * @return Current status of the monitoring type.
     */
    public int getStatusOfMonitoringType(int monitoringType) {
        try {
            return mService.getStatusOfMonitoringType(monitoringType);
        } catch (RemoteException e) {
            return MONITOR_UNSUPPORTED;
        }
    }

    /**
     * Creates a circular geofence which is monitored by subsystems in the hardware.
     *
     * <p> When the device detects that is has entered, exited or is uncertain
     * about the area specified by the geofence, the given callback will be called.
     *
     * <p> If this call returns true, it means that the geofence has been sent to the hardware.
     * {@link GeofenceHardwareCallback#onGeofenceAdd} will be called with the result of the
     * add call from the hardware. The {@link GeofenceHardwareCallback#onGeofenceAdd} will be
     * called with the following parameters when a transition event occurs.
     * <ul>
     * <li> The geofence Id
     * <li> The location object indicating the last known location.
     * <li> The transition associated with the geofence. One of
     *      {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
     * <li> The timestamp when the geofence transition occured.
     * <li> The monitoring type ({@link #MONITORING_TYPE_GPS_HARDWARE} is one such example)
     *      that was used.
     * </ul>
     *
     * <p> The geofence will be monitored by the subsystem specified by monitoring_type parameter.
     * The application does not need to hold a wakelock when the monitoring
     * is being done by the underlying hardware subsystem. If the same geofence Id is being
     * monitored by two different monitoring systems, the same id can be used for both calls, as
     * long as the same callback object is used.
     *
     * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
     * {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * <p>This API should not be called directly by the app developers. A higher level api
     * which abstracts the hardware should be used instead. All the checks are done by the higher
     * level public API. Any needed locking should be handled by the higher level API.
     *
     * <p> Create a geofence request object using the methods in {@link GeofenceHardwareRequest} to
     * set all the characteristics of the geofence. Use the created GeofenceHardwareRequest object
     * in this call.
     *
     * @param geofenceId The id associated with the geofence.
     * @param monitoringType The type of the hardware subsystem that should be used
     *        to monitor the geofence.
     * @param geofenceRequest The {@link GeofenceHardwareRequest} object associated with the
     *        geofence.
     * @param callback {@link GeofenceHardwareCallback} that will be use to notify the
     *        transition.
     * @return true when the geofence is successfully sent to the hardware for addition.
     * @throws IllegalArgumentException when the geofence request type is not supported.
     */
    public boolean addGeofence(int geofenceId, int monitoringType, GeofenceHardwareRequest
            geofenceRequest, GeofenceHardwareCallback callback) {
        try {
            if (geofenceRequest.getType() == GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
                return mService.addCircularFence(geofenceId, monitoringType,
                        geofenceRequest.getLatitude(),
                        geofenceRequest.getLongitude(), geofenceRequest.getRadius(),
                        geofenceRequest.getLastTransition(),
                        geofenceRequest.getMonitorTransitions(),
                        geofenceRequest.getNotificationResponsiveness(),
                        geofenceRequest.getUnknownTimer(),
                        getCallbackWrapper(callback));
            } else {
                throw new IllegalArgumentException("Geofence Request type not supported");
            }
        } catch (RemoteException e) {
        }
        return false;
    }

    /**
     * Removes a geofence added by {@link #addGeofence} call.
     *
     * <p> If this call returns true, it means that the geofence has been sent to the hardware.
     * {@link GeofenceHardwareCallback#onGeofenceRemove} will be called with the result of the
     * remove call from the hardware.
     *
     * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
     * {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * <p>This API should not be called directly by the app developers. A higher level api
     * which abstracts the hardware should be used instead. All the checks are done by the higher
     * level public API. Any needed locking should be handled by the higher level API.
     *
     * @param geofenceId The id of the geofence.
     * @param monitoringType The type of the hardware subsystem that should be used
     *        to monitor the geofence.
     * @return true when the geofence is successfully sent to the hardware for removal.                     .
     */
   public boolean removeGeofence(int geofenceId, int monitoringType) {
       try {
           return mService.removeGeofence(geofenceId, monitoringType);
       } catch (RemoteException e) {
       }
       return false;
   }

    /**
     * Pauses the monitoring of a geofence added by {@link #addGeofence} call.
     *
     * <p> If this call returns true, it means that the geofence has been sent to the hardware.
     * {@link GeofenceHardwareCallback#onGeofencePause} will be called with the result of the
     * pause call from the hardware.
     *
     * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
     * {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * <p>This API should not be called directly by the app developers. A higher level api
     * which abstracts the hardware should be used instead. All the checks are done by the higher
     * level public API. Any needed locking should be handled by the higher level API.
     *
     * @param geofenceId The id of the geofence.
     * @param monitoringType The type of the hardware subsystem that should be used
     *        to monitor the geofence.
     * @return true when the geofence is successfully sent to the hardware for pausing.
     */
    public boolean pauseGeofence(int geofenceId, int monitoringType) {
        try {
            return mService.pauseGeofence(geofenceId, monitoringType);
        } catch (RemoteException e) {
        }
        return false;
    }

    /**
     * Resumes the monitoring of a geofence added by {@link #pauseGeofence} call.
     *
     * <p> If this call returns true, it means that the geofence has been sent to the hardware.
     * {@link GeofenceHardwareCallback#onGeofenceResume} will be called with the result of the
     * resume call from the hardware.
     *
     * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
     * {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * <p>This API should not be called directly by the app developers. A higher level api
     * which abstracts the hardware should be used instead. All the checks are done by the higher
     * level public API. Any needed locking should be handled by the higher level API.
     *
     * @param geofenceId The id of the geofence.
     * @param monitoringType The type of the hardware subsystem that should be used
     *        to monitor the geofence.
     * @param monitorTransition Bitwise OR of {@link #GEOFENCE_ENTERED},
     *        {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
     * @return true when the geofence is successfully sent to the hardware for resumption.
     */
    public boolean resumeGeofence(int geofenceId, int monitoringType, int monitorTransition) {
        try {
            return mService.resumeGeofence(geofenceId, monitoringType, monitorTransition);
        } catch (RemoteException e) {
        }
        return false;
    }

    /**
     * Register the callback to be notified when the state of a hardware geofence
     * monitoring system changes. For instance, it can change from
     * {@link #MONITOR_CURRENTLY_AVAILABLE} to {@link #MONITOR_CURRENTLY_UNAVAILABLE}
     *
     * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
     * {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * <p>This API should not be called directly by the app developers. A higher level api
     * which abstracts the hardware should be used instead. All the checks are done by the higher
     * level public API. Any needed locking should be handled by the higher level API.
     *
     * <p> The same callback object can be used to be informed of geofence transitions
     * and state changes of the underlying hardware subsystem.
     *
     * @param monitoringType Type of the monitor
     * @param callback Callback that will be called.
     * @return true on success
     */
    public boolean registerForMonitorStateChangeCallback(int monitoringType,
            GeofenceHardwareMonitorCallback callback) {
        try {
            return mService.registerForMonitorStateChangeCallback(monitoringType,
                    getMonitorCallbackWrapper(callback));
        } catch (RemoteException e) {
        }
        return false;
    }

    /**
     * Unregister the callback that was used with {@link #registerForMonitorStateChangeCallback}
     * to notify when the state of the hardware geofence monitoring system changes.
     *
     * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
     * {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
     *
     * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
     * geofencing in hardware.
     *
     * <p>This API should not be called directly by the app developers. A higher level api
     * which abstracts the hardware should be used instead. All the checks are done by the higher
     * level public API. Any needed locking should be handled by the higher level API.
     *
     * @param monitoringType Type of the monitor
     * @param callback Callback that will be called.
     * @return true on success
     */
    public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
            GeofenceHardwareMonitorCallback callback) {
        boolean  result = false;
        try {
            result = mService.unregisterForMonitorStateChangeCallback(monitoringType,
                    getMonitorCallbackWrapper(callback));
            if (result) removeMonitorCallback(callback);

        } catch (RemoteException e) {
        }
        return result;
    }


    private void removeCallback(GeofenceHardwareCallback callback) {
        synchronized (mCallbacks) {
            mCallbacks.remove(callback);
        }
    }

    private GeofenceHardwareCallbackWrapper getCallbackWrapper(GeofenceHardwareCallback callback) {
        synchronized (mCallbacks) {
            GeofenceHardwareCallbackWrapper wrapper = mCallbacks.get(callback);
            if (wrapper == null) {
                wrapper = new GeofenceHardwareCallbackWrapper(callback);
                mCallbacks.put(callback, wrapper);
            }
            return wrapper;
        }
    }

    private void removeMonitorCallback(GeofenceHardwareMonitorCallback callback) {
        synchronized (mMonitorCallbacks) {
            mMonitorCallbacks.remove(callback);
        }
    }

    private GeofenceHardwareMonitorCallbackWrapper getMonitorCallbackWrapper(
            GeofenceHardwareMonitorCallback callback) {
        synchronized (mMonitorCallbacks) {
            GeofenceHardwareMonitorCallbackWrapper wrapper = mMonitorCallbacks.get(callback);
            if (wrapper == null) {
                wrapper = new GeofenceHardwareMonitorCallbackWrapper(callback);
                mMonitorCallbacks.put(callback, wrapper);
            }
            return wrapper;
        }
    }

    class GeofenceHardwareMonitorCallbackWrapper extends IGeofenceHardwareMonitorCallback.Stub {
        private WeakReference<GeofenceHardwareMonitorCallback> mCallback;

        GeofenceHardwareMonitorCallbackWrapper(GeofenceHardwareMonitorCallback c) {
            mCallback = new WeakReference<GeofenceHardwareMonitorCallback>(c);
        }

        public void onMonitoringSystemChange(int monitoringType, boolean available,
                Location location) {
            GeofenceHardwareMonitorCallback c = mCallback.get();
            if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
        }
    }

    class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub {
        private WeakReference<GeofenceHardwareCallback> mCallback;

        GeofenceHardwareCallbackWrapper(GeofenceHardwareCallback c) {
            mCallback = new WeakReference<GeofenceHardwareCallback>(c);
        }

        public void onGeofenceTransition(int geofenceId, int transition, Location location,
                long timestamp, int monitoringType) {
            GeofenceHardwareCallback c = mCallback.get();
            if (c != null) {
                c.onGeofenceTransition(geofenceId, transition, location, timestamp,
                        monitoringType);
            }
        }

        public void onGeofenceAdd(int geofenceId, int status) {
            GeofenceHardwareCallback c = mCallback.get();
            if (c != null) c.onGeofenceAdd(geofenceId, status);
        }

        public void onGeofenceRemove(int geofenceId, int status) {
            GeofenceHardwareCallback c = mCallback.get();
            if (c != null) {
                c.onGeofenceRemove(geofenceId, status);
                removeCallback(c);
            }
        }

        public void onGeofencePause(int geofenceId, int status) {
            GeofenceHardwareCallback c = mCallback.get();
            if (c != null) {
                c.onGeofencePause(geofenceId, status);
            }
        }

        public void onGeofenceResume(int geofenceId, int status) {
            GeofenceHardwareCallback c = mCallback.get();
            if (c != null) c.onGeofenceResume(geofenceId, status);
        }
    }
}
