/*
 * 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.dialer.dialpad;

import static com.android.dialer.dialpad.SmartDialAdapter.LOG_TAG;

import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
import android.util.Log;

import com.android.contacts.common.util.StopWatch;

import com.google.common.base.Preconditions;

import java.util.Comparator;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Cache object used to cache Smart Dial contacts that handles various states of the cache at the
 * point in time when getContacts() is called
 * 1) Cache is currently empty and there is no caching thread running - getContacts() starts a
 * caching thread and returns the cache when completed
 * 2) The cache is currently empty, but a caching thread has been started - getContacts() waits
 * till the existing caching thread is completed before immediately returning the cache
 * 3) The cache has already been populated, and there is no caching thread running - getContacts()
 * returns the existing cache immediately
 * 4) The cache has already been populated, but there is another caching thread running (due to
 * a forced cache refresh due to content updates - getContacts() returns the existing cache
 * immediately
 */
public class SmartDialCache {

    public static class ContactNumber {
        public final String displayName;
        public final String lookupKey;
        public final long id;
        public final int affinity;
        public final String phoneNumber;

        public ContactNumber(long id, String displayName, String phoneNumber, String lookupKey,
                int affinity) {
            this.displayName = displayName;
            this.lookupKey = lookupKey;
            this.id = id;
            this.affinity = affinity;
            this.phoneNumber = phoneNumber;
        }
    }

    public static interface PhoneQuery {

       Uri URI = Phone.CONTENT_URI.buildUpon().
               appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
               String.valueOf(Directory.DEFAULT)).
               appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").
               build();

       final String[] PROJECTION_PRIMARY = new String[] {
            Phone._ID,                          // 0
            Phone.TYPE,                         // 1
            Phone.LABEL,                        // 2
            Phone.NUMBER,                       // 3
            Phone.CONTACT_ID,                   // 4
            Phone.LOOKUP_KEY,                   // 5
            Phone.DISPLAY_NAME_PRIMARY,         // 6
        };

        final String[] PROJECTION_ALTERNATIVE = new String[] {
            Phone._ID,                          // 0
            Phone.TYPE,                         // 1
            Phone.LABEL,                        // 2
            Phone.NUMBER,                       // 3
            Phone.CONTACT_ID,                   // 4
            Phone.LOOKUP_KEY,                   // 5
            Phone.DISPLAY_NAME_ALTERNATIVE,     // 6
        };

        public static final int PHONE_ID           = 0;
        public static final int PHONE_TYPE         = 1;
        public static final int PHONE_LABEL        = 2;
        public static final int PHONE_NUMBER       = 3;
        public static final int PHONE_CONTACT_ID   = 4;
        public static final int PHONE_LOOKUP_KEY   = 5;
        public static final int PHONE_DISPLAY_NAME = 6;

        public static final String SORT_ORDER = Contacts.LAST_TIME_CONTACTED + " DESC";
    }

    private SmartDialTrie mContactsCache;
    private static AtomicInteger mCacheStatus;
    private final int mNameDisplayOrder;
    private final Context mContext;
    private final static Object mLock = new Object();

    public static final int CACHE_NEEDS_RECACHE = 1;
    public static final int CACHE_IN_PROGRESS = 2;
    public static final int CACHE_COMPLETED = 3;

    private static final boolean DEBUG = true;

    private SmartDialCache(Context context, int nameDisplayOrder) {
        mNameDisplayOrder = nameDisplayOrder;
        Preconditions.checkNotNull(context, "Context must not be null");
        mContext = context.getApplicationContext();
        mCacheStatus = new AtomicInteger(CACHE_NEEDS_RECACHE);
    }

    private static SmartDialCache instance;

    /**
     * Returns an instance of SmartDialCache.
     *
     * @param context A context that provides a valid ContentResolver.
     * @param nameDisplayOrder One of the two name display order integer constants (1 or 2) as saved
     *        in settings under the key
     *        {@link android.provider.ContactsContract.Preferences#DISPLAY_ORDER}.
     * @return An instance of SmartDialCache
     */
    public static synchronized SmartDialCache getInstance(Context context, int nameDisplayOrder) {
        if (instance == null) {
            instance = new SmartDialCache(context, nameDisplayOrder);
        }
        return instance;
    }

    /**
     * Performs a database query, iterates through the returned cursor and saves the retrieved
     * contacts to a local cache.
     */
    private void cacheContacts(Context context) {
        mCacheStatus.set(CACHE_IN_PROGRESS);
        synchronized(mLock) {
            if (DEBUG) {
                Log.d(LOG_TAG, "Starting caching thread");
            }
            final StopWatch stopWatch = DEBUG ? StopWatch.start("SmartDial Cache") : null;
            final Cursor c = context.getContentResolver().query(PhoneQuery.URI,
                    (mNameDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY)
                        ? PhoneQuery.PROJECTION_PRIMARY : PhoneQuery.PROJECTION_ALTERNATIVE,
                    null, null, PhoneQuery.SORT_ORDER);
            if (DEBUG) {
                stopWatch.lap("SmartDial query complete");
            }
            if (c == null) {
                Log.w(LOG_TAG, "SmartDial query received null for cursor");
                if (DEBUG) {
                    stopWatch.stopAndLog("SmartDial query received null for cursor", 0);
                }
                mCacheStatus.getAndSet(CACHE_NEEDS_RECACHE);
                return;
            }
            final SmartDialTrie cache = new SmartDialTrie(
                    SmartDialNameMatcher.LATIN_LETTERS_TO_DIGITS);
            try {
                c.moveToPosition(-1);
                int affinityCount = 0;
                while (c.moveToNext()) {
                    final String displayName = c.getString(PhoneQuery.PHONE_DISPLAY_NAME);
                    final String phoneNumber = c.getString(PhoneQuery.PHONE_NUMBER);
                    final long id = c.getLong(PhoneQuery.PHONE_CONTACT_ID);
                    final String lookupKey = c.getString(PhoneQuery.PHONE_LOOKUP_KEY);
                    cache.put(new ContactNumber(id, displayName, phoneNumber, lookupKey,
                            affinityCount));
                    affinityCount++;
                }
            } finally {
                c.close();
                mContactsCache = cache;
                if (DEBUG) {
                    stopWatch.stopAndLog("SmartDial caching completed", 0);
                }
            }
        }
        if (DEBUG) {
            Log.d(LOG_TAG, "Caching thread completed");
        }
        mCacheStatus.getAndSet(CACHE_COMPLETED);
    }

    /**
     * Returns the list of cached contacts. This is blocking so it should not be called from the UI
     * thread. There are 4 possible scenarios:
     *
     * 1) Cache is currently empty and there is no caching thread running - getContacts() starts a
     * caching thread and returns the cache when completed
     * 2) The cache is currently empty, but a caching thread has been started - getContacts() waits
     * till the existing caching thread is completed before immediately returning the cache
     * 3) The cache has already been populated, and there is no caching thread running -
     * getContacts() returns the existing cache immediately
     * 4) The cache has already been populated, but there is another caching thread running (due to
     * a forced cache refresh due to content updates - getContacts() returns the existing cache
     * immediately
     *
     * @return List of already cached contacts, or an empty list if the caching failed for any
     * reason.
     */
    public SmartDialTrie getContacts() {
        // Either scenario 3 or 4 - This means just go ahead and return the existing cache
        // immediately even if there is a caching thread currently running. We are guaranteed to
        // have the newest value of mContactsCache at this point because it is volatile.
        if (mContactsCache != null) {
            return mContactsCache;
        }
        // At this point we are forced to wait for cacheContacts to complete in another thread(if
        // one currently exists) because of mLock.
        synchronized(mLock) {
            // If mContactsCache is still null at this point, either there was never any caching
            // process running, or it failed (Scenario 1). If so, just go ahead and try to cache
            // the contacts again.
            if (mContactsCache == null) {
                cacheContacts(mContext);
                return (mContactsCache == null) ? new SmartDialTrie(
                        SmartDialNameMatcher.LATIN_LETTERS_TO_DIGITS) : mContactsCache;
            } else {
                // After waiting for the lock on mLock to be released, mContactsCache is now
                // non-null due to the completion of the caching thread (Scenario 2). Go ahead
                // and return the existing cache.
                return mContactsCache;
            }
        }
    }

    /**
     * Cache contacts only if there is a need to (forced cache refresh or no attempt to cache yet).
     * This method is called in 2 places: whenever the DialpadFragment comes into view, and when the
     * ContentObserver observes a change in contacts.
     *
     * @param forceRecache If true, force a cache refresh.
     */

    public void cacheIfNeeded(boolean forceRecache) {
        if (DEBUG) {
            Log.d("SmartDial", "cacheIfNeeded called with " + String.valueOf(forceRecache));
        }
        if (mCacheStatus.get() == CACHE_IN_PROGRESS) {
            return;
        }
        if (forceRecache || mCacheStatus.get() == CACHE_NEEDS_RECACHE) {
            // Because this method can be possibly be called multiple times in rapid succession,
            // set the cache status even before starting a caching thread to avoid unnecessarily
            // spawning extra threads.
            mCacheStatus.set(CACHE_IN_PROGRESS);
            startCachingThread();
        }
    }

    private void startCachingThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                cacheContacts(mContext);
            }
        }).start();
    }

    public static class ContactAffinityComparator implements Comparator<ContactNumber> {
        @Override
        public int compare(ContactNumber lhs, ContactNumber rhs) {
            // Smaller affinity is better because they are numbered in ascending order in
            // the order the contacts were returned from the ContactsProvider (sorted by
            // frequency of use and time last used
            return Integer.compare(lhs.affinity, rhs.affinity);
        }

    }

    public static class SmartDialContentObserver extends ContentObserver {
        private final SmartDialCache mCache;
        // throttle updates in case onChange is called too often due to syncing, etc.
        private final long mThresholdBetweenUpdates = 5000;
        private long mLastCalled = 0;
        private long mLastUpdated = 0;
        public SmartDialContentObserver(Handler handler, SmartDialCache cache) {
            super(handler);
            mCache = cache;
        }

        @Override
        public void onChange(boolean selfChange) {
            mLastCalled = System.currentTimeMillis();
            if (DEBUG) {
                Log.d(LOG_TAG, "Contacts change observed");
            }
            if (mLastCalled - mLastUpdated > mThresholdBetweenUpdates) {
                mLastUpdated = mLastCalled;
                if (DEBUG) {
                    Log.d(LOG_TAG, "More than 5 seconds since last cache, forcing recache");
                }
                mCache.cacheIfNeeded(true);
            }
            super.onChange(selfChange);
        }
    }
}
