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

import android.database.Cursor;
import android.content.Context;
import android.content.ComponentName;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import java.util.concurrent.Executor;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.HashSet;
import java.util.Iterator;

/**
 * Holds onto the current {@link SuggestionSession} and manages its lifecycle.  When a session ends,
 * it gets the session stats and reports them to the {@link ShortcutRepository}.
 */
public class SessionManager implements SuggestionSession.SessionCallback {

    private static final String TAG = "SessionManager";
    private static final boolean DBG = false;
    private static SessionManager sInstance;

    private final Context mContext;

    public static synchronized SessionManager getInstance() {
        return sInstance;
    }

    /**
     * Refreshes the global session manager.
     *
     * @param sources The suggestion sources.
     * @param shortcutRepo The shortcut repository.
     * @param queryExecutor The executor used to execute search suggestion tasks.
     * @param refreshExecutor The executor used execute shortcut refresh tasks.
     * @param handler The handler passed along to the session.
     * @return The up to date session manager.
     */
    public static synchronized SessionManager refreshSessionmanager(Context context,
            SuggestionSources sources, ShortcutRepository shortcutRepo,
            PerTagExecutor queryExecutor,
            Executor refreshExecutor, Handler handler) {
        if (DBG) Log.d(TAG, "refreshSessionmanager()");

        sInstance = new SessionManager(context, sources, shortcutRepo,
                queryExecutor, refreshExecutor, handler);
        return sInstance;
    }

    private SessionManager(Context context,
            SuggestionSources sources, ShortcutRepository shortcutRepo,
            PerTagExecutor queryExecutor, Executor refreshExecutor, Handler handler) {
        mContext = context;
        mSources = sources;
        mShortcutRepo = shortcutRepo;
        mQueryExecutor = queryExecutor;
        mRefreshExecutor = refreshExecutor;
        mHandler = handler;
    }

    private final SuggestionSources mSources;
    private final ShortcutRepository mShortcutRepo;
    private final PerTagExecutor mQueryExecutor;
    private final Executor mRefreshExecutor;
    private final Handler mHandler;
    private SuggestionSession mSession;

    /**
     * Queries the current session for results.
     *
     * @see SuggestionSession#query(String)
     */
    public synchronized Cursor query(Context context, String query) {
        // create a new session if there is none,
        // or when starting a new typing session
        if (mSession == null || TextUtils.isEmpty(query)) {
            mSession = createSession();
        }

        return mSession.query(query);
    }

    /** {@inheritDoc} */
    public synchronized void closeSession() {
        if (DBG) Log.d(TAG, "closeSession()");
        mSession = null;
    }

    private SuggestionSession createSession() {
        if (DBG) Log.d(TAG, "createSession()");
        final SuggestionSource webSearchSource = mSources.getSelectedWebSearchSource();
        
        // Fire off a warm-up query to the web search source, which that source can use for
        // whatever it sees fit. For example, EnhancedGoogleSearchProvider uses this to
        // determine whether a opt-in needs to be shown for use of location.
        if (webSearchSource != null) {
            warmUpWebSource(webSearchSource);
        }

        Sources sources = orderSources(
                mSources.getEnabledSuggestionSources(),
                webSearchSource,
                mShortcutRepo.getSourceRanking(),
                SuggestionSession.NUM_PROMOTED_SOURCES);

        // implement the delayed executor using the handler
        final DelayedExecutor delayedExecutor = new DelayedExecutor() {
            public void postDelayed(Runnable runnable, long delayMillis) {
                mHandler.postDelayed(runnable, delayMillis);
            }

            public void postAtTime(Runnable runnable, long uptimeMillis) {
                mHandler.postAtTime(runnable, uptimeMillis);
            }
        };

        SuggestionSession session = new SuggestionSession(
                mSources, sources.mPromotableSources, sources.mUnpromotableSources,
                mQueryExecutor,
                mRefreshExecutor,
                delayedExecutor, new SuggestionFactoryImpl(mContext),
                SuggestionSession.CACHE_SUGGESTION_RESULTS);
        session.setListener(this);
        session.setShortcutRepo(mShortcutRepo);
        return session;
    }

    private void warmUpWebSource(final SuggestionSource webSearchSource) {
        mQueryExecutor.execute("warmup", new Runnable() {
            public void run() {
                try {
                    webSearchSource.getSuggestionTask("", 0, 0).call();
                } catch (Exception e) {
                    Log.e(TAG, "exception from web search warm-up query", e);
                }
            }
        });
    }

    /**
     * Orders sources by source ranking.  The ordering is as follows:
     * - the web source is first regardless
     * - the rest of the promoted sources are filled based on the ranking passed in
     * - any unranked sources
     * The above are put in mPromotableSources.
     *
     * The rest of the ranked sources are put in mUnpromotableSources.
     *
     * The idea is that unranked sources get a bump until they have enough data to be ranked like
     * the rest, and at the same time, no source can be in the promoted list unless it has a high
     * click through rate for a sustained amount of impressions.
     *
     * @param enabledSources The enabled sources.
     * @param webSearchSource The name of the web search source, or <code>null</code> otherwise.
     * @param sourceRanking The order the sources should be in.
     * @param numPromoted  The number of promoted sources.
     */
    static Sources orderSources(
            List<SuggestionSource> enabledSources,
            SuggestionSource webSearchSource,
            ArrayList<ComponentName> sourceRanking,
            int numPromoted) {

        // get any sources that are in the enabled sources in the order
        final int numSources = enabledSources.size();
        HashMap<ComponentName, SuggestionSource> linkMap =
                new LinkedHashMap<ComponentName, SuggestionSource>(numSources);
        for (int i = 0; i < numSources; i++) {
            final SuggestionSource source = enabledSources.get(i);
            linkMap.put(source.getComponentName(), source);
        }

        Sources sources = new Sources();

        // gather set of ranked
        final HashSet<ComponentName> allRanked = new HashSet<ComponentName>(sourceRanking);

        // start with the web source if it exists
        if (webSearchSource != null) {
            if (DBG) Log.d(TAG, "Adding web search source: " + webSearchSource);
            sources.add(webSearchSource, true);
        }

        // add ranked for rest of promoted slots
        final int numRanked = sourceRanking.size();
        int nextRanked = 0;
        for (; nextRanked < numRanked && sources.mPromotableSources.size() < numPromoted;
                nextRanked++) {
            final ComponentName ranked = sourceRanking.get(nextRanked);
            final SuggestionSource source = linkMap.remove(ranked);
            if (DBG) Log.d(TAG, "Adding promoted ranked source: (" + ranked + ") " + source);
            sources.add(source, true);
        }

        // now add the unranked
        final Iterator<SuggestionSource> sourceIterator = linkMap.values().iterator();
        while (sourceIterator.hasNext()) {
            SuggestionSource source = sourceIterator.next();
            if (!allRanked.contains(source.getComponentName())) {
                if (DBG) Log.d(TAG, "Adding unranked source: " + source);
                sources.add(source, false);
                sourceIterator.remove();
            }
        }

        // finally, add any remaining ranked to mUnpromotableSources
        for (int i = nextRanked; i < numRanked; i++) {
            final ComponentName ranked = sourceRanking.get(i);
            final SuggestionSource source = linkMap.get(ranked);
            if (DBG) Log.d(TAG, "Adding ranked source: (" + ranked + ") " + source);
            sources.add(source, false);
        }

        if (DBG) Log.d(TAG, "Promotable sources: " + sources.mPromotableSources);
        if (DBG) Log.d(TAG, "Unpromotable sources: " + sources.mUnpromotableSources);

        return sources;
    }

    static class Sources {
        public final ArrayList<SuggestionSource> mPromotableSources;
        public final ArrayList<SuggestionSource> mUnpromotableSources;
        public Sources() {
            mPromotableSources = new ArrayList<SuggestionSource>();
            mUnpromotableSources = new ArrayList<SuggestionSource>();
        }
        public void add(SuggestionSource source, boolean forcePromotable) {
            if (source == null) return;
            if (forcePromotable || shouldBePromotableWhenLowRanked(source)) {
                if (DBG) Log.d(TAG, "  Promotable: " + source);
                mPromotableSources.add(source);
            } else {
                if (DBG) Log.d(TAG, "  Unpromotable: " + source);
                mUnpromotableSources.add(source);
            }
        }
    }

    private static boolean shouldBePromotableWhenLowRanked(SuggestionSource source) {
        // TODO: this is an ugly hack to make sure the Music source is unpromotable unless
        // it is ranked highly. (as long as there are at least
        // SuggestionSession.NUM_PROMOTED_SOURCES other sources)
        // Once the Music app returns better suggestions (i.e. token prefix matches, rather
        // than string infix matches) this should be removed.
        return !"com.android.music".equals(source.getComponentName().getPackageName());
    }
}
