/*
 * Copyright 2018 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.internal.app;

import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.util.Log;

import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * Used to sort resolved activities in {@link ResolverListController}.
 *
 * @hide
 */
public abstract class AbstractResolverComparator implements Comparator<ResolvedComponentInfo> {

    private static final int NUM_OF_TOP_ANNOTATIONS_TO_USE = 3;
    private static final boolean DEBUG = false;
    private static final String TAG = "AbstractResolverComp";

    protected AfterCompute mAfterCompute;
    protected final PackageManager mPm;
    protected final UsageStatsManager mUsm;
    protected String[] mAnnotations;
    protected String mContentType;

    // True if the current share is a link.
    private final boolean mHttp;
    // can be null if mHttp == false or current user has no default browser package
    private final String mDefaultBrowserPackageName;

    // message types
    static final int RANKER_SERVICE_RESULT = 0;
    static final int RANKER_RESULT_TIMEOUT = 1;

    // timeout for establishing connections with a ResolverRankerService, collecting features and
    // predicting ranking scores.
    private static final int WATCHDOG_TIMEOUT_MILLIS = 500;

    private final Comparator<ResolveInfo> mAzComparator;

    protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case RANKER_SERVICE_RESULT:
                    if (DEBUG) {
                        Log.d(TAG, "RANKER_SERVICE_RESULT");
                    }
                    if (mHandler.hasMessages(RANKER_RESULT_TIMEOUT)) {
                        handleResultMessage(msg);
                        mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
                        afterCompute();
                    }
                    break;

                case RANKER_RESULT_TIMEOUT:
                    if (DEBUG) {
                        Log.d(TAG, "RANKER_RESULT_TIMEOUT; unbinding services");
                    }
                    mHandler.removeMessages(RANKER_SERVICE_RESULT);
                    afterCompute();
                    break;

                default:
                    super.handleMessage(msg);
            }
        }
    };

    public AbstractResolverComparator(Context context, Intent intent) {
        String scheme = intent.getScheme();
        mHttp = "http".equals(scheme) || "https".equals(scheme);
        mContentType = intent.getType();
        getContentAnnotations(intent);
        mPm = context.getPackageManager();
        mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
        mDefaultBrowserPackageName = mHttp
                ? mPm.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId())
                : null;
        mAzComparator = new AzInfoComparator(context);
    }

    // get annotations of content from intent.
    private void getContentAnnotations(Intent intent) {
        ArrayList<String> annotations = intent.getStringArrayListExtra(
                Intent.EXTRA_CONTENT_ANNOTATIONS);
        if (annotations != null) {
            int size = annotations.size();
            if (size > NUM_OF_TOP_ANNOTATIONS_TO_USE) {
                size = NUM_OF_TOP_ANNOTATIONS_TO_USE;
            }
            mAnnotations = new String[size];
            for (int i = 0; i < size; i++) {
                mAnnotations[i] = annotations.get(i);
            }
        }
    }

    /**
     * Callback to be called when {@link #compute(List)} finishes. This signals to stop waiting.
     */
    interface AfterCompute {

        void afterCompute();
    }

    void setCallBack(AfterCompute afterCompute) {
        mAfterCompute = afterCompute;
    }

    protected final void afterCompute() {
        final AfterCompute afterCompute = mAfterCompute;
        if (afterCompute != null) {
            afterCompute.afterCompute();
        }
    }

    @Override
    public final int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
        final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
        final ResolveInfo rhs = rhsp.getResolveInfoAt(0);

        // We want to put the one targeted to another user at the end of the dialog.
        if (lhs.targetUserId != UserHandle.USER_CURRENT) {
            return rhs.targetUserId != UserHandle.USER_CURRENT ? 0 : 1;
        }
        if (rhs.targetUserId != UserHandle.USER_CURRENT) {
            return -1;
        }

        if (mHttp) {
            // Special case: we want filters that match URI paths/schemes to be
            // ordered before others.  This is for the case when opening URIs,
            // to make native apps go above browsers - except for 1 even more special case
            // which is the default browser, as we want that to go above them all.
            if (isDefaultBrowser(lhs)) {
                return -1;
            }

            if (isDefaultBrowser(rhs)) {
                return 1;
            }
            final boolean lhsSpecific = ResolverActivity.isSpecificUriMatch(lhs.match);
            final boolean rhsSpecific = ResolverActivity.isSpecificUriMatch(rhs.match);
            if (lhsSpecific != rhsSpecific) {
                return lhsSpecific ? -1 : 1;
            }
        }

        final boolean lPinned = lhsp.isPinned();
        final boolean rPinned = rhsp.isPinned();

        // Pinned items always receive priority.
        if (lPinned && !rPinned) {
            return -1;
        } else if (!lPinned && rPinned) {
            return 1;
        } else if (lPinned && rPinned) {
            // If both items are pinned, resolve the tie alphabetically.
            return mAzComparator.compare(lhsp.getResolveInfoAt(0), rhsp.getResolveInfoAt(0));
        }

        return compare(lhs, rhs);
    }

    /**
     * Delegated to when used as a {@link Comparator<ResolvedComponentInfo>} if there is not a
     * special case. The {@link ResolveInfo ResolveInfos} are the first {@link ResolveInfo} in
     * {@link ResolvedComponentInfo#getResolveInfoAt(int)} from the parameters of {@link
     * #compare(ResolvedComponentInfo, ResolvedComponentInfo)}
     */
    abstract int compare(ResolveInfo lhs, ResolveInfo rhs);

    /**
     * Computes features for each target. This will be called before calls to {@link
     * #getScore(ComponentName)} or {@link #compare(Object, Object)}, in order to prepare the
     * comparator for those calls. Note that {@link #getScore(ComponentName)} uses {@link
     * ComponentName}, so the implementation will have to be prepared to identify a {@link
     * ResolvedComponentInfo} by {@link ComponentName}. {@link #beforeCompute()} will be called
     * before doing any computing.
     */
    final void compute(List<ResolvedComponentInfo> targets) {
        beforeCompute();
        doCompute(targets);
    }

    /** Implementation of compute called after {@link #beforeCompute()}. */
    abstract void doCompute(List<ResolvedComponentInfo> targets);

    /**
     * Returns the score that was calculated for the corresponding {@link ResolvedComponentInfo}
     * when {@link #compute(List)} was called before this.
     */
    abstract float getScore(ComponentName name);

    /** Handles result message sent to mHandler. */
    abstract void handleResultMessage(Message message);

    /**
     * Reports to UsageStats what was chosen.
     */
    final void updateChooserCounts(String packageName, int userId, String action) {
        if (mUsm != null) {
            mUsm.reportChooserSelection(packageName, userId, mContentType, mAnnotations, action);
        }
    }

    /**
     * Updates the model used to rank the componentNames.
     *
     * <p>Default implementation does nothing, as we could have simple model that does not train
     * online.
     *
     * @param componentName the component that the user clicked
     */
    void updateModel(ComponentName componentName) {
    }

    /** Called before {@link #doCompute(List)}. Sets up 500ms timeout. */
    void beforeCompute() {
        if (DEBUG) Log.d(TAG, "Setting watchdog timer for " + WATCHDOG_TIMEOUT_MILLIS + "ms");
        if (mHandler == null) {
            Log.d(TAG, "Error: Handler is Null; Needs to be initialized.");
            return;
        }
        mHandler.sendEmptyMessageDelayed(RANKER_RESULT_TIMEOUT, WATCHDOG_TIMEOUT_MILLIS);
    }

    /**
     * Called when the {@link ResolverActivity} is destroyed. This calls {@link #afterCompute()}. If
     * this call needs to happen at a different time during destroy, the method should be
     * overridden.
     */
    void destroy() {
        mHandler.removeMessages(RANKER_SERVICE_RESULT);
        mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
        afterCompute();
    }

    private boolean isDefaultBrowser(ResolveInfo ri) {
        // It makes sense to prefer the default browser
        // only if the targeted user is the current user
        if (ri.targetUserId != UserHandle.USER_CURRENT) {
            return false;
        }

        if (ri.activityInfo.packageName != null
                    && ri.activityInfo.packageName.equals(mDefaultBrowserPackageName)) {
            return true;
        }
        return false;
    }


    /**
     * Sort intents alphabetically based on package name.
     */
    class AzInfoComparator implements Comparator<ResolveInfo> {
        Collator mCollator;
        AzInfoComparator(Context context) {
            mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
        }

        @Override
        public int compare(ResolveInfo lhsp, ResolveInfo rhsp) {
            if (lhsp == null) {
                return -1;
            } else if (rhsp == null) {
                return 1;
            }
            return mCollator.compare(lhsp.activityInfo.packageName, rhsp.activityInfo.packageName);
        }
    }

}
