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

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;

import com.android.location.provider.LocationProviderBase;
import com.android.location.provider.LocationRequestUnbundled;
import com.android.location.provider.ProviderRequestUnbundled;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.WorkSource;
import android.util.Log;

public class FusionEngine implements LocationListener {
    public interface Callback {
        public void reportLocation(Location location);
    }

    private static final String TAG = "FusedLocation";
    private static final String NETWORK = LocationManager.NETWORK_PROVIDER;
    private static final String GPS = LocationManager.GPS_PROVIDER;
    private static final String FUSED = LocationProviderBase.FUSED_PROVIDER;

    public static final long SWITCH_ON_FRESHNESS_CLIFF_NS = 11 * 1000000000; // 11 seconds

    private final Context mContext;
    private final LocationManager mLocationManager;
    private final Looper mLooper;

    // all fields are only used on mLooper thread. except for in dump() which is not thread-safe
    private Callback mCallback;
    private Location mFusedLocation;
    private Location mGpsLocation;
    private Location mNetworkLocation;

    private boolean mEnabled;
    private ProviderRequestUnbundled mRequest;

    private final HashMap<String, ProviderStats> mStats = new HashMap<String, ProviderStats>();

    public FusionEngine(Context context, Looper looper) {
        mContext = context;
        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        mNetworkLocation = new Location("");
        mNetworkLocation.setAccuracy(Float.MAX_VALUE);
        mGpsLocation = new Location("");
        mGpsLocation.setAccuracy(Float.MAX_VALUE);
        mLooper = looper;

        mStats.put(GPS, new ProviderStats());
        mStats.get(GPS).available = mLocationManager.isProviderEnabled(GPS);
        mStats.put(NETWORK, new ProviderStats());
        mStats.get(NETWORK).available = mLocationManager.isProviderEnabled(NETWORK);

    }

    public void init(Callback callback) {
        Log.i(TAG, "engine started (" + mContext.getPackageName() + ")");
        mCallback = callback;
    }

    /**
     * Called to stop doing any work, and release all resources
     * This can happen when a better fusion engine is installed
     * in a different package, and this one is no longer needed.
     * Called on mLooper thread
     */
    public void deinit() {
        mRequest = null;
        disable();
        Log.i(TAG, "engine stopped (" + mContext.getPackageName() + ")");
    }

    /** Called on mLooper thread */
    public void enable() {
        mEnabled = true;
        updateRequirements();
    }

    /** Called on mLooper thread */
    public void disable() {
        mEnabled = false;
        updateRequirements();
    }

    /** Called on mLooper thread */
    public void setRequest(ProviderRequestUnbundled request, WorkSource source) {
        mRequest = request;
        mEnabled = request.getReportLocation();
        updateRequirements();
    }

    private static class ProviderStats {
        public boolean available;
        public boolean requested;
        public long requestTime;
        public long minTime;
        @Override
        public String toString() {
            StringBuilder s = new StringBuilder();
            s.append(available ? "AVAILABLE" : "UNAVAILABLE");
            s.append(requested ? " REQUESTED" : " ---");
            return s.toString();
        }
    }

    private void enableProvider(String name, long minTime) {
        ProviderStats stats = mStats.get(name);

        if (stats.available) {
            if (!stats.requested) {
                stats.requestTime = SystemClock.elapsedRealtime();
                stats.requested = true;
                stats.minTime = minTime;
                mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
            } else if (stats.minTime != minTime) {
                stats.minTime = minTime;
                mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
            }
        }
    }

    private void disableProvider(String name) {
        ProviderStats stats = mStats.get(name);

        if (stats.requested) {
            stats.requested = false;
            mLocationManager.removeUpdates(this);  //TODO GLOBAL
        }
    }

    private void updateRequirements() {
        if (mEnabled == false || mRequest == null) {
            mRequest = null;
            disableProvider(NETWORK);
            disableProvider(GPS);
            return;
        }

        long networkInterval = Long.MAX_VALUE;
        long gpsInterval = Long.MAX_VALUE;
        for (LocationRequestUnbundled request : mRequest.getLocationRequests()) {
            switch (request.getQuality()) {
                case LocationRequestUnbundled.ACCURACY_FINE:
                case LocationRequestUnbundled.POWER_HIGH:
                    if (request.getInterval() < gpsInterval) {
                        gpsInterval = request.getInterval();
                    }
                    if (request.getInterval() < networkInterval) {
                        networkInterval = request.getInterval();
                    }
                    break;
                case LocationRequestUnbundled.ACCURACY_BLOCK:
                case LocationRequestUnbundled.ACCURACY_CITY:
                case LocationRequestUnbundled.POWER_LOW:
                    if (request.getInterval() < networkInterval) {
                        networkInterval = request.getInterval();
                    }
                    break;
            }
        }

        if (gpsInterval < Long.MAX_VALUE) {
            enableProvider(GPS, gpsInterval);
        } else {
            disableProvider(GPS);
        }
        if (networkInterval < Long.MAX_VALUE) {
            enableProvider(NETWORK, networkInterval);
        } else {
            disableProvider(NETWORK);
        }
    }

    /**
     * Test whether one location (a) is better to use than another (b).
     */
    private static boolean isBetterThan(Location locationA, Location locationB) {
      if (locationA == null) {
        return false;
      }
      if (locationB == null) {
        return true;
      }
      // A provider is better if the reading is sufficiently newer.  Heading
      // underground can cause GPS to stop reporting fixes.  In this case it's
      // appropriate to revert to cell, even when its accuracy is less.
      if (locationA.getElapsedRealtimeNanos() > locationB.getElapsedRealtimeNanos() + SWITCH_ON_FRESHNESS_CLIFF_NS) {
        return true;
      }

      // A provider is better if it has better accuracy.  Assuming both readings
      // are fresh (and by that accurate), choose the one with the smaller
      // accuracy circle.
      if (!locationA.hasAccuracy()) {
        return false;
      }
      if (!locationB.hasAccuracy()) {
        return true;
      }
      return locationA.getAccuracy() < locationB.getAccuracy();
    }

    private void updateFusedLocation() {
        // may the best location win!
        if (isBetterThan(mGpsLocation, mNetworkLocation)) {
            mFusedLocation = new Location(mGpsLocation);
        } else {
            mFusedLocation = new Location(mNetworkLocation);
        }
        mFusedLocation.setProvider(FUSED);
        if (mNetworkLocation != null) {
            // copy NO_GPS_LOCATION extra from mNetworkLocation into mFusedLocation
            Bundle srcExtras = mNetworkLocation.getExtras();
            if (srcExtras != null) {
                Parcelable srcParcelable =
                        srcExtras.getParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION);
                if (srcParcelable instanceof Location) {
                    Bundle dstExtras = mFusedLocation.getExtras();
                    if (dstExtras == null) {
                        dstExtras = new Bundle();
                        mFusedLocation.setExtras(dstExtras);
                    }
                    dstExtras.putParcelable(LocationProviderBase.EXTRA_NO_GPS_LOCATION,
                            (Location) srcParcelable);
                }
            }
        }

        if (mCallback != null) {
          mCallback.reportLocation(mFusedLocation);
        } else {
          Log.w(TAG, "Location updates received while fusion engine not started");
        }
    }

    /** Called on mLooper thread */
    @Override
    public void onLocationChanged(Location location) {
        if (GPS.equals(location.getProvider())) {
            mGpsLocation = location;
            updateFusedLocation();
        } else if (NETWORK.equals(location.getProvider())) {
            mNetworkLocation = location;
            updateFusedLocation();
        }
    }

    /** Called on mLooper thread */
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {  }

    /** Called on mLooper thread */
    @Override
    public void onProviderEnabled(String provider) {
        ProviderStats stats = mStats.get(provider);
        if (stats == null) return;

        stats.available = true;
    }

    /** Called on mLooper thread */
    @Override
    public void onProviderDisabled(String provider) {
        ProviderStats stats = mStats.get(provider);
        if (stats == null) return;

        stats.available = false;
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        StringBuilder s = new StringBuilder();
        s.append("mEnabled=" + mEnabled).append(' ').append(mRequest).append('\n');
        s.append("fused=").append(mFusedLocation).append('\n');
        s.append(String.format("gps %s\n", mGpsLocation));
        s.append("    ").append(mStats.get(GPS)).append('\n');
        s.append(String.format("net %s\n", mNetworkLocation));
        s.append("    ").append(mStats.get(NETWORK)).append('\n');
        pw.append(s);
    }

    /** Called on mLooper thread */
    public void switchUser() {
        // reset state to prevent location data leakage
        mFusedLocation = null;
        mGpsLocation = null;
        mNetworkLocation = null;
    }
}
