/*
 * 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.providers.contacts;

import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.util.Log;

import com.google.android.collect.Maps;
import com.google.common.annotations.VisibleForTesting;

import java.util.Map;
import java.util.regex.Pattern;

/**
 * Cache for the "fast scrolling index".
 *
 * It's a cache from "keys" and "bundles" (see {@link #mCache} for what they are).  The cache
 * content is also persisted in the shared preferences, so it'll survive even if the process
 * is killed or the device reboots.
 *
 * All the content will be invalidated when the provider detects an operation that could potentially
 * change the index.
 *
 * There's no maximum number for cached entries.  It's okay because we store keys and values in
 * a compact form in both the in-memory cache and the preferences.  Also the query in question
 * (the query for contact lists) has relatively low number of variations.
 *
 * This class is thread-safe.
 */
public class FastScrollingIndexCache {
    private static final String TAG = "LetterCountCache";

    @VisibleForTesting
    static final String PREFERENCE_KEY = "LetterCountCache";

    /**
     * Separator used for in-memory structure.
     */
    private static final String SEPARATOR = "\u0001";
    private static final Pattern SEPARATOR_PATTERN = Pattern.compile(SEPARATOR);

    /**
     * Separator used for serializing values for preferences.
     */
    private static final String SAVE_SEPARATOR = "\u0002";
    private static final Pattern SAVE_SEPARATOR_PATTERN = Pattern.compile(SAVE_SEPARATOR);

    private final SharedPreferences mPrefs;

    private boolean mPreferenceLoaded;

    /**
     * In-memory cache.
     *
     * It's essentially a map from keys, which are query parameters passed to {@link #get}, to
     * values, which are {@link Bundle}s that will be appended to a {@link Cursor} as extras.
     *
     * However, in order to save memory, we store stringified keys and values in the cache.
     * Key strings are generated by {@link #buildCacheKey} and values are generated by
     * {@link #buildCacheValue}.
     *
     * We store those strings joined with {@link #SAVE_SEPARATOR} as the separator when saving
     * to shared preferences.
     */
    private final Map<String, String> mCache = Maps.newHashMap();

    private static FastScrollingIndexCache sSingleton;

    public static FastScrollingIndexCache getInstance(Context context) {
        if (sSingleton == null) {
            final StrictMode.ThreadPolicy old = StrictMode.allowThreadDiskReads();
            try {
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
                sSingleton = new FastScrollingIndexCache(prefs);
            } finally {
                StrictMode.setThreadPolicy(old);
            }
        }
        return sSingleton;
    }

    @VisibleForTesting
    static synchronized FastScrollingIndexCache getInstanceForTest(
            SharedPreferences prefs) {
        sSingleton = new FastScrollingIndexCache(prefs);
        return sSingleton;
    }

    private FastScrollingIndexCache(SharedPreferences prefs) {
        mPrefs = prefs;
    }

    /**
     * Append a {@link String} to a {@link StringBuilder}.
     *
     * Unlike the original {@link StringBuilder#append}, it does *not* append the string "null" if
     * {@code value} is null.
     */
    private static void appendIfNotNull(StringBuilder sb, Object value) {
        if (value != null) {
            sb.append(value.toString());
        }
    }

    private static String buildCacheKey(Uri queryUri, String selection, String[] selectionArgs,
            String sortOrder, String countExpression) {
        final StringBuilder sb = new StringBuilder();

        appendIfNotNull(sb, queryUri);
        appendIfNotNull(sb, SEPARATOR);
        appendIfNotNull(sb, selection);
        appendIfNotNull(sb, SEPARATOR);
        appendIfNotNull(sb, sortOrder);
        appendIfNotNull(sb, SEPARATOR);
        appendIfNotNull(sb, countExpression);

        if (selectionArgs != null) {
            for (int i = 0; i < selectionArgs.length; i++) {
                appendIfNotNull(sb, SEPARATOR);
                appendIfNotNull(sb, selectionArgs[i]);
            }
        }
        return sb.toString();
    }

    @VisibleForTesting
    static String buildCacheValue(String[] titles, int[] counts) {
        final StringBuilder sb = new StringBuilder();

        for (int i = 0; i < titles.length; i++) {
            if (i > 0) {
                appendIfNotNull(sb, SEPARATOR);
            }
            appendIfNotNull(sb, titles[i]);
            appendIfNotNull(sb, SEPARATOR);
            appendIfNotNull(sb, Integer.toString(counts[i]));
        }

        return sb.toString();
    }

    /**
     * Creates and returns a {@link Bundle} that is appended to a {@link Cursor} as extras.
     */
    public static final Bundle buildExtraBundle(String[] titles, int[] counts) {
        Bundle bundle = new Bundle();
        bundle.putStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles);
        bundle.putIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, counts);
        return bundle;
    }

    @VisibleForTesting
    static Bundle buildExtraBundleFromValue(String value) {
        final String[] values;
        if (TextUtils.isEmpty(value)) {
            values = new String[0];
        } else {
            values = SEPARATOR_PATTERN.split(value);
        }

        if ((values.length) % 2 != 0) {
            return null; // malformed
        }

        try {
            final int numTitles = values.length / 2;
            final String[] titles = new String[numTitles];
            final int[] counts = new int[numTitles];

            for (int i = 0; i < numTitles; i++) {
                titles[i] = values[i * 2];
                counts[i] = Integer.parseInt(values[i * 2 + 1]);
            }

            return buildExtraBundle(titles, counts);
        } catch (RuntimeException e) {
            Log.w(TAG, "Failed to parse cached value", e);
            return null; // malformed
        }
    }

    public Bundle get(Uri queryUri, String selection, String[] selectionArgs, String sortOrder,
            String countExpression) {
        synchronized (mCache) {
            ensureLoaded();
            final String key = buildCacheKey(queryUri, selection, selectionArgs, sortOrder,
                    countExpression);
            final String value = mCache.get(key);
            if (value == null) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "Miss: " + key);
                }
                return null;
            }

            final Bundle b = buildExtraBundleFromValue(value);
            if (b == null) {
                // Value was malformed for whatever reason.
                mCache.remove(key);
                save();
            } else {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "Hit:  " + key);
                }
            }
            return b;
        }
    }

    /**
     * Put a {@link Bundle} into the cache.  {@link Bundle} MUST be built with
     * {@link #buildExtraBundle(String[], int[])}.
     */
    public void put(Uri queryUri, String selection, String[] selectionArgs, String sortOrder,
            String countExpression, Bundle bundle) {
        synchronized (mCache) {
            ensureLoaded();
            final String key = buildCacheKey(queryUri, selection, selectionArgs, sortOrder,
                    countExpression);
            mCache.put(key, buildCacheValue(
                    bundle.getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES),
                    bundle.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS)));
            save();

            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Put: " + key);
            }
        }
    }

    public void invalidate() {
        synchronized (mCache) {
            mPrefs.edit().remove(PREFERENCE_KEY).commit();
            mCache.clear();
            mPreferenceLoaded = true;

            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Invalidated");
            }
        }
    }

    /**
     * Store the cache to the preferences.
     *
     * We concatenate all key+value pairs into one string and save it.
     */
    private void save() {
        final StringBuilder sb = new StringBuilder();
        for (String key : mCache.keySet()) {
            if (sb.length() > 0) {
                appendIfNotNull(sb, SAVE_SEPARATOR);
            }
            appendIfNotNull(sb, key);
            appendIfNotNull(sb, SAVE_SEPARATOR);
            appendIfNotNull(sb, mCache.get(key));
        }
        mPrefs.edit().putString(PREFERENCE_KEY, sb.toString()).apply();
    }

    private void ensureLoaded() {
        if (mPreferenceLoaded) return;

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Loading...");
        }

        // Even when we fail to load, don't retry loading again.
        mPreferenceLoaded = true;

        boolean successfullyLoaded = false;
        try {
            final String savedValue = mPrefs.getString(PREFERENCE_KEY, null);

            if (!TextUtils.isEmpty(savedValue)) {

                final String[] keysAndValues = SAVE_SEPARATOR_PATTERN.split(savedValue);

                if ((keysAndValues.length % 2) != 0) {
                    return; // malformed
                }

                for (int i = 1; i < keysAndValues.length; i += 2) {
                    final String key = keysAndValues[i - 1];
                    final String value = keysAndValues[i];

                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "Loaded: " + key);
                    }

                    mCache.put(key, value);
                }
            }
            successfullyLoaded = true;
        } catch (RuntimeException e) {
            Log.w(TAG, "Failed to load from preferences", e);
            // But don't crash apps!
        } finally {
            if (!successfullyLoaded) {
                invalidate();
            }
        }
    }
}
