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

import com.android.common.SharedPreferencesCompat;

import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

/**
 * Manages user settings.
 */
public class SearchSettingsImpl implements SearchSettings {

    private static final boolean DBG = false;
    private static final String TAG = "QSB.SearchSettingsImpl";

    // Name of the preferences file used to store search preference
    public static final String PREFERENCES_NAME = "SearchSettings";

    // Intent action that opens the "Searchable Items" preference
    private static final String ACTION_SEARCHABLE_ITEMS =
            "com.android.quicksearchbox.action.SEARCHABLE_ITEMS";

    /**
     * Preference key used for storing the index of the next voice search hint to show.
     */
    private static final String NEXT_VOICE_SEARCH_HINT_INDEX_PREF = "next_voice_search_hint";

    /**
     * Preference key used to store the time at which the first voice search hint was displayed.
     */
    private static final String FIRST_VOICE_HINT_DISPLAY_TIME = "first_voice_search_hint_time";

    /**
     * Preference key for the version of voice search we last got hints from.
     */
    private static final String LAST_SEEN_VOICE_SEARCH_VERSION = "voice_search_version";

    /**
     * Preference key for storing whether searches always go to google.com. Public
     * so that it can be used by PreferenceControllers.
     */
    public static final String USE_GOOGLE_COM_PREF = "use_google_com";

    /**
     * Preference key for the base search URL. This value is normally set by
     * a SearchBaseUrlHelper instance. Public so classes can listen to changes
     * on this key.
     */
    public static final String SEARCH_BASE_DOMAIN_PREF = "search_base_domain";

    /**
     * This is the time at which the base URL was stored, and is set using
     * @link{System.currentTimeMillis()}.
     */
    private static final String SEARCH_BASE_DOMAIN_APPLY_TIME = "search_base_domain_apply_time";

    /**
     * Prefix of per-corpus enable preference
     */
    private static final String CORPUS_ENABLED_PREF_PREFIX = "enable_corpus_";

    private final Context mContext;

    private final Config mConfig;

    public SearchSettingsImpl(Context context, Config config) {
        mContext = context;
        mConfig = config;
    }

    protected Context getContext() {
        return mContext;
    }

    protected Config getConfig() {
        return mConfig;
    }

    public void upgradeSettingsIfNeeded() {
    }

    public Intent getSearchableItemsIntent() {
        Intent intent = new Intent(ACTION_SEARCHABLE_ITEMS);
        intent.setPackage(getContext().getPackageName());
        return intent;
    }

    /**
     * Gets the preference key of the preference for whether the given corpus
     * is enabled. The preference is stored in the {@link #PREFERENCES_NAME}
     * preferences file.
     */
    public static String getCorpusEnabledPreference(Corpus corpus) {
        return CORPUS_ENABLED_PREF_PREFIX + corpus.getName();
    }

    public boolean isCorpusEnabled(Corpus corpus) {
        boolean defaultEnabled = corpus.isCorpusDefaultEnabled();
        String sourceEnabledPref = getCorpusEnabledPreference(corpus);
        return getSearchPreferences().getBoolean(sourceEnabledPref, defaultEnabled);
    }

    public SharedPreferences getSearchPreferences() {
        return getContext().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
    }

    protected void storeBoolean(String name, boolean value) {
        SharedPreferencesCompat.apply(getSearchPreferences().edit().putBoolean(name, value));
    }

    protected void storeInt(String name, int value) {
        SharedPreferencesCompat.apply(getSearchPreferences().edit().putInt(name, value));
    }

    protected void storeLong(String name, long value) {
        SharedPreferencesCompat.apply(getSearchPreferences().edit().putLong(name, value));
    }

    protected void storeString(String name, String value) {
        SharedPreferencesCompat.apply(getSearchPreferences().edit().putString(name, value));
    }

    protected void removePref(String name) {
        SharedPreferencesCompat.apply(getSearchPreferences().edit().remove(name));
    }

    /**
     * Informs our listeners about the updated settings data.
     */
    public void broadcastSettingsChanged() {
        // We use a message broadcast since the listeners could be in multiple processes.
        Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS_CHANGED);
        Log.i(TAG, "Broadcasting: " + intent);
        getContext().sendBroadcast(intent);
    }

    public void addMenuItems(Menu menu, boolean showDisabled) {
        MenuInflater inflater = new MenuInflater(getContext());
        inflater.inflate(R.menu.settings, menu);
        MenuItem item = menu.findItem(R.id.menu_settings);
        item.setIntent(getSearchSettingsIntent());
    }

    public Intent getSearchSettingsIntent() {
        Intent settings = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS);
        settings.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        settings.setPackage(getContext().getPackageName());
        return settings;
    }

    public int getNextVoiceSearchHintIndex(int size) {
            int i = getAndIncrementIntPreference(getSearchPreferences(),
                    NEXT_VOICE_SEARCH_HINT_INDEX_PREF);
            return i % size;
    }

    // TODO: Could this be made atomic to avoid races?
    private int getAndIncrementIntPreference(SharedPreferences prefs, String name) {
        int i = prefs.getInt(name, 0);
        storeInt(name, i + 1);
        return i;
    }

    public void resetVoiceSearchHintFirstSeenTime() {
        storeLong(FIRST_VOICE_HINT_DISPLAY_TIME, System.currentTimeMillis());
    }

    public boolean haveVoiceSearchHintsExpired(int currentVoiceSearchVersion) {
        SharedPreferences prefs = getSearchPreferences();

        if (currentVoiceSearchVersion != 0) {
            long currentTime = System.currentTimeMillis();
            int lastVoiceSearchVersion = prefs.getInt(LAST_SEEN_VOICE_SEARCH_VERSION, 0);
            long firstHintTime = prefs.getLong(FIRST_VOICE_HINT_DISPLAY_TIME, 0);
            if (firstHintTime == 0 || currentVoiceSearchVersion != lastVoiceSearchVersion) {
                SharedPreferencesCompat.apply(prefs.edit()
                        .putInt(LAST_SEEN_VOICE_SEARCH_VERSION, currentVoiceSearchVersion)
                        .putLong(FIRST_VOICE_HINT_DISPLAY_TIME, currentTime));
                firstHintTime = currentTime;
            }
            if (currentTime - firstHintTime > getConfig().getVoiceSearchHintActivePeriod()) {
                if (DBG) Log.d(TAG, "Voice seach hint period expired; not showing hints.");
                return true;
            } else {
                return false;
            }
        } else {
            if (DBG) Log.d(TAG, "Could not determine voice search version; not showing hints.");
            return true;
        }
    }

    public boolean allowWebSearchShortcuts() {
        return true;
    }

    /**
     * @return true if user searches should always be based at google.com, false
     *     otherwise.
     */
    @Override
    public boolean shouldUseGoogleCom() {
        // Note that this preserves the old behaviour of using google.com
        // for searches, with the gl= parameter set.
        return getSearchPreferences().getBoolean(USE_GOOGLE_COM_PREF, true);
    }

    @Override
    public void setUseGoogleCom(boolean useGoogleCom) {
        storeBoolean(USE_GOOGLE_COM_PREF, useGoogleCom);
    }

    @Override
    public long getSearchBaseDomainApplyTime() {
        return getSearchPreferences().getLong(SEARCH_BASE_DOMAIN_APPLY_TIME, -1);
    }

    @Override
    public String getSearchBaseDomain() {
        // Note that the only time this will return null is on the first run
        // of the app, or when settings have been cleared. Callers should
        // ideally check that getSearchBaseDomainApplyTime() is not -1 before
        // calling this function.
        return getSearchPreferences().getString(SEARCH_BASE_DOMAIN_PREF, null);
    }

    @Override
    public void setSearchBaseDomain(String searchBaseUrl) {
        Editor sharedPrefEditor = getSearchPreferences().edit();
        sharedPrefEditor.putString(SEARCH_BASE_DOMAIN_PREF, searchBaseUrl);
        sharedPrefEditor.putLong(SEARCH_BASE_DOMAIN_APPLY_TIME, System.currentTimeMillis());

        SharedPreferencesCompat.apply(sharedPrefEditor);
    }
}
