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

import android.content.Context;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.webkit.GeolocationPermissions;
import android.webkit.ValueCallback;

import java.util.HashSet;
import java.util.Set;

/**
 * Manages the interaction between the secure system setting for default geolocation
 * permissions and the browser.
 */
class SystemAllowGeolocationOrigins {

    // Preference key for the value of the system setting last read by the browser
    private final static String LAST_READ_ALLOW_GEOLOCATION_ORIGINS =
            "last_read_allow_geolocation_origins";

    // The application context
    private final Context mContext;

    // The observer used to listen to the system setting.
    private final SettingObserver mSettingObserver;

    public SystemAllowGeolocationOrigins(Context context) {
        mContext = context;
        mSettingObserver = new SettingObserver();
    }

    /**
     * Checks whether the setting has changed and installs an observer to listen for
     * future changes. Must be called on the application main thread.
     */
    public void start() {
        // Register to receive notifications when the system settings change.
        Uri uri = Settings.Secure.getUriFor(Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS);
        mContext.getContentResolver().registerContentObserver(uri, false, mSettingObserver);

        // Read and apply the setting if needed.
        maybeApplySettingAsync();
    }

    /**
     * Stops the manager.
     */
    public void stop() {
        mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
    }

    void maybeApplySettingAsync() {
        new AsyncTask<Void,Void,Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                maybeApplySetting();
                return null;
            }
        }.execute();
    }

    /**
     * Checks to see if the system setting has changed and if so,
     * updates the Geolocation permissions accordingly.
     */
    private void maybeApplySetting() {
        // Get the new value
        String newSetting = getSystemSetting();

        // Get the last read value
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        String lastReadSetting =
                preferences.getString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, "");

        // If the new value is the same as the last one we read, we're done.
        if (TextUtils.equals(lastReadSetting, newSetting)) {
            return;
        }

        // Save the new value as the last read value
        preferences.edit()
                .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting)
                .apply();

        Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting);
        Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting);
        Set<String> addedOrigins = setMinus(newOrigins, oldOrigins);
        Set<String> removedOrigins = setMinus(oldOrigins, newOrigins);

        // Remove the origins in the last read value
        removeOrigins(removedOrigins);

        // Add the origins in the new value
        addOrigins(addedOrigins);
    }

    /**
     * Parses the value of the default geolocation permissions setting.
     *
     * @param setting A space-separated list of origins.
     * @return A mutable set of origins.
     */
    private static HashSet<String> parseAllowGeolocationOrigins(String setting) {
        HashSet<String> origins = new HashSet<String>();
        if (!TextUtils.isEmpty(setting)) {
            for (String origin : setting.split("\\s+")) {
                if (!TextUtils.isEmpty(origin)) {
                    origins.add(origin);
                }
            }
        }
        return origins;
    }

    /**
     * Gets the difference between two sets. Does not modify any of the arguments.
     *
     * @return A set containing all elements in {@code x} that are not in {@code y}.
     */
    private <A> Set<A> setMinus(Set<A> x, Set<A> y) {
        HashSet<A> z = new HashSet<A>(x.size());
        for (A a : x) {
            if (!y.contains(a)) {
                z.add(a);
            }
        }
        return z;
    }

    /**
     * Gets the current system setting for default allowed geolocation origins.
     *
     * @return The default allowed origins. Returns {@code ""} if not set.
     */
    private String getSystemSetting() {
        String value = Settings.Secure.getString(mContext.getContentResolver(),
                Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS);
        return value == null ? "" : value;
    }

    /**
     * Adds geolocation permissions for the given origins.
     */
    private void addOrigins(Set<String> origins) {
        for (String origin : origins) {
            GeolocationPermissions.getInstance().allow(origin);
        }
    }

    /**
     * Removes geolocation permissions for the given origins, if they are allowed.
     * If they are denied or not set, nothing is done.
     */
    private void removeOrigins(Set<String> origins) {
        for (final String origin : origins) {
            GeolocationPermissions.getInstance().getAllowed(origin, new ValueCallback<Boolean>() {
                public void onReceiveValue(Boolean value) {
                    if (value != null && value.booleanValue()) {
                        GeolocationPermissions.getInstance().clear(origin);
                    }
                }
            });
        }
    }

    /**
     * Listens for changes to the system setting.
     */
    private class SettingObserver extends ContentObserver {

        SettingObserver() {
            super(new Handler());
        }

        @Override
        public void onChange(boolean selfChange) {
            maybeApplySettingAsync();
        }
    }

}
