/*
 * 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 static android.content.Intent.ACTION_USER_SWITCHED;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationRequest.QUALITY_LOW_POWER;
import static android.location.provider.ProviderProperties.ACCURACY_FINE;
import static android.location.provider.ProviderProperties.POWER_USAGE_LOW;

import static com.android.location.provider.ProviderRequestUnbundled.INTERVAL_DISABLED;

import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.location.provider.LocationProviderBase;
import android.location.provider.ProviderProperties;
import android.location.provider.ProviderRequest;
import android.os.Bundle;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.Objects;

/** Basic fused location provider implementation. */
public class FusedLocationProvider extends LocationProviderBase {

    private static final String TAG = "FusedLocationProvider";

    private static final ProviderProperties PROPERTIES = new ProviderProperties.Builder()
                .setHasAltitudeSupport(true)
                .setHasSpeedSupport(true)
                .setHasBearingSupport(true)
                .setPowerUsage(POWER_USAGE_LOW)
                .setAccuracy(ACCURACY_FINE)
                .build();

    private static final long MAX_LOCATION_COMPARISON_NS = 11 * 1000000000L; // 11 seconds

    private final Object mLock = new Object();

    private final Context mContext;
    private final LocationManager mLocationManager;
    private final ChildLocationListener mGpsListener;
    private final ChildLocationListener mNetworkListener;
    private final BroadcastReceiver mUserChangeReceiver;

    @GuardedBy("mLock")
    private ProviderRequest mRequest;

    @GuardedBy("mLock")
    private @Nullable Location mFusedLocation;

    public FusedLocationProvider(Context context) {
        super(context, TAG, PROPERTIES);
        mContext = context;
        mLocationManager = Objects.requireNonNull(context.getSystemService(LocationManager.class));

        mGpsListener = new ChildLocationListener(GPS_PROVIDER);
        mNetworkListener = new ChildLocationListener(NETWORK_PROVIDER);

        mUserChangeReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!ACTION_USER_SWITCHED.equals(intent.getAction())) {
                    return;
                }

                onUserChanged();
            }
        };

        mRequest = ProviderRequest.EMPTY_REQUEST;
    }

    void start() {
        mContext.registerReceiver(mUserChangeReceiver, new IntentFilter(ACTION_USER_SWITCHED));
    }

    void stop() {
        mContext.unregisterReceiver(mUserChangeReceiver);

        synchronized (mLock) {
            mRequest = ProviderRequest.EMPTY_REQUEST;
            updateRequirementsLocked();
        }
    }

    @Override
    public void onSetRequest(ProviderRequest request) {
        synchronized (mLock) {
            mRequest = request;
            updateRequirementsLocked();
        }
    }

    @Override
    public void onFlush(OnFlushCompleteCallback callback) {
        OnFlushCompleteCallback wrapper = new OnFlushCompleteCallback() {
            private int mFlushCount = 2;

            @Override
            public void onFlushComplete() {
                if (--mFlushCount == 0) {
                    callback.onFlushComplete();
                }
            }
        };

        mGpsListener.flush(wrapper);
        mNetworkListener.flush(wrapper);
    }

    @Override
    public void onSendExtraCommand(String command, @Nullable Bundle extras) {}

    @GuardedBy("mLock")
    private void updateRequirementsLocked() {
        long gpsInterval = mRequest.getQuality() < QUALITY_LOW_POWER ? mRequest.getIntervalMillis()
                : INTERVAL_DISABLED;
        long networkInterval = mRequest.getIntervalMillis();

        mGpsListener.resetProviderRequest(gpsInterval);
        mNetworkListener.resetProviderRequest(networkInterval);
    }

    @GuardedBy("mLock")
    void reportBestLocationLocked() {
        Location bestLocation = chooseBestLocation(mGpsListener.getLocation(),
                mNetworkListener.getLocation());
        if (bestLocation == mFusedLocation) {
            return;
        }

        mFusedLocation = bestLocation;
        if (mFusedLocation == null) {
            return;
        }

        reportLocation(mFusedLocation);
    }

    void onUserChanged() {
        // clear cached locations when the user changes to prevent leaking user information
        synchronized (mLock) {
            mFusedLocation = null;
            mGpsListener.clearLocation();
            mNetworkListener.clearLocation();
        }
    }

    void dump(PrintWriter writer) {
        synchronized (mLock) {
            writer.println("request: " + mRequest);
            if (mGpsListener.getInterval() != INTERVAL_DISABLED) {
                writer.println("  gps interval: " + mGpsListener.getInterval());
            }
            if (mNetworkListener.getInterval() != INTERVAL_DISABLED) {
                writer.println("  network interval: " + mNetworkListener.getInterval());
            }
            if (mGpsListener.getLocation() != null) {
                writer.println("  last gps location: " + mGpsListener.getLocation());
            }
            if (mNetworkListener.getLocation() != null) {
                writer.println("  last network location: " + mNetworkListener.getLocation());
            }
        }
    }

    @Nullable
    private static Location chooseBestLocation(
            @Nullable Location locationA,
            @Nullable Location locationB) {
        if (locationA == null) {
            return locationB;
        }
        if (locationB == null) {
            return locationA;
        }

        if (locationA.getElapsedRealtimeNanos()
                > locationB.getElapsedRealtimeNanos() + MAX_LOCATION_COMPARISON_NS) {
            return locationA;
        }
        if (locationB.getElapsedRealtimeNanos()
                > locationA.getElapsedRealtimeNanos() + MAX_LOCATION_COMPARISON_NS) {
            return locationB;
        }

        if (!locationA.hasAccuracy()) {
            return locationB;
        }
        if (!locationB.hasAccuracy()) {
            return locationA;
        }
        return locationA.getAccuracy() < locationB.getAccuracy() ? locationA : locationB;
    }

    private class ChildLocationListener implements LocationListener {

        private final String mProvider;
        private final SparseArray<OnFlushCompleteCallback> mPendingFlushes;

        @GuardedBy("mLock")
        private int mNextFlushCode = 0;
        @GuardedBy("mLock")
        private @Nullable Location mLocation = null;
        @GuardedBy("mLock")
        private long mInterval = INTERVAL_DISABLED;

        ChildLocationListener(String provider) {
            mProvider = provider;
            mPendingFlushes = new SparseArray<>();
        }

        @Nullable Location getLocation() {
            synchronized (mLock) {
                return mLocation;
            }
        }

        long getInterval() {
            synchronized (mLock) {
                return mInterval;
            }
        }

        void clearLocation() {
            synchronized (mLock) {
                mLocation = null;
            }
        }

        private void resetProviderRequest(long newInterval) {
            synchronized (mLock) {
                if (newInterval == mInterval) {
                    return;
                }

                if (mInterval != INTERVAL_DISABLED && newInterval == INTERVAL_DISABLED) {
                    mLocationManager.removeUpdates(this);
                }

                mInterval = newInterval;

                if (mInterval != INTERVAL_DISABLED) {
                    LocationRequest request = new LocationRequest.Builder(mInterval)
                            .setMaxUpdateDelayMillis(mRequest.getMaxUpdateDelayMillis())
                            .setQuality(mRequest.getQuality())
                            .setLowPower(mRequest.isLowPower())
                            .setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored())
                            .setWorkSource(mRequest.getWorkSource())
                            .setHiddenFromAppOps(true)
                            .build();
                    mLocationManager.requestLocationUpdates(mProvider, request,
                            mContext.getMainExecutor(), this);
                }
            }
        }

        void flush(OnFlushCompleteCallback callback) {
            synchronized (mLock) {
                int requestCode = mNextFlushCode++;
                mPendingFlushes.put(requestCode, callback);
                mLocationManager.requestFlush(mProvider, this, requestCode);
            }
        }

        @Override
        public void onLocationChanged(Location location) {
            synchronized (mLock) {
                mLocation = location;
                reportBestLocationLocked();
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
            synchronized (mLock) {
                // if satisfying a bypass request, don't clear anything
                if (mRequest.isActive() && mRequest.isLocationSettingsIgnored()) {
                    return;
                }

                mLocation = null;
            }
        }

        @Override
        public void onFlushComplete(int requestCode) {
            synchronized (mLock) {
                OnFlushCompleteCallback callback = mPendingFlushes.removeReturnOld(requestCode);
                if (callback != null) {
                    callback.onFlushComplete();
                }
            }
        }
    }
}
