/*
 * 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.content.Context;
import android.location.Location;
import android.os.RemoteException;
import android.util.Log;

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


/**
 * 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 = 1;

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

    /**
     * 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;

    static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
    static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;

    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);
        }
    }
}
