// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.document;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.AppTask;
import android.app.ActivityManager.RecentTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import org.chromium.base.ContextUtils;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelImpl;

import java.util.ArrayList;
import java.util.List;

/**
 * Deals with Document-related API calls.
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class DocumentUtils {
    public static final String TAG = "DocumentUtilities";

    /**
     * Finishes tasks other than the one with the given ID that were started with the given data
     * in the Intent, removing those tasks from Recents and leaving a unique task with the data.
     * @param data Passed in as part of the Intent's data when starting the Activity.
     * @param canonicalTaskId ID of the task will be the only one left with the ID.
     * @return Intent of one of the tasks that were finished.
     */
    public static Intent finishOtherTasksWithData(Uri data, int canonicalTaskId) {
        if (data == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null;

        String dataString = data.toString();
        Context context = ContextUtils.getApplicationContext();

        ActivityManager manager =
                (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.AppTask> tasksToFinish = new ArrayList<ActivityManager.AppTask>();
        for (ActivityManager.AppTask task : manager.getAppTasks()) {
            RecentTaskInfo taskInfo = getTaskInfoFromTask(task);
            if (taskInfo == null) continue;
            int taskId = taskInfo.id;

            Intent baseIntent = taskInfo.baseIntent;
            String taskData = baseIntent == null ? null : taskInfo.baseIntent.getDataString();

            if (TextUtils.equals(dataString, taskData)
                    && (taskId == -1 || taskId != canonicalTaskId)) {
                tasksToFinish.add(task);
            }
        }
        return finishAndRemoveTasks(tasksToFinish);
    }

    private static Intent finishAndRemoveTasks(List<ActivityManager.AppTask> tasksToFinish) {
        Intent removedIntent = null;
        for (ActivityManager.AppTask task : tasksToFinish) {
            Log.d(TAG, "Removing task with duplicated data: " + task);
            removedIntent = getBaseIntentFromTask(task);
            task.finishAndRemoveTask();
        }
        return removedIntent;
    }

    /**
     * Returns the RecentTaskInfo for the task, if the ActivityManager succeeds in finding the task.
     * @param task AppTask containing information about a task.
     * @return The RecentTaskInfo associated with the task, or null if it couldn't be found.
     */
    public static RecentTaskInfo getTaskInfoFromTask(AppTask task) {
        RecentTaskInfo info = null;
        try {
            info = task.getTaskInfo();
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Failed to retrieve task info: ", e);
        }
        return info;
    }

    /**
     * Returns the baseIntent of the RecentTaskInfo associated with the given task.
     * @param task Task to get the baseIntent for.
     * @return The baseIntent, or null if it couldn't be retrieved.
     */
    public static Intent getBaseIntentFromTask(AppTask task) {
        RecentTaskInfo info = getTaskInfoFromTask(task);
        return info == null ? null : info.baseIntent;
    }

    /**
     * Given an AppTask retrieves the task class name.
     * @param task The app task to use.
     * @param pm The package manager to use for resolving intent.
     * @return Fully qualified class name or null if we were not able to
     * determine it.
     */
    public static String getTaskClassName(AppTask task, PackageManager pm) {
        RecentTaskInfo info = getTaskInfoFromTask(task);
        if (info == null) return null;

        Intent baseIntent = info.baseIntent;
        if (baseIntent == null) {
            return null;
        } else if (baseIntent.getComponent() != null) {
            return baseIntent.getComponent().getClassName();
        } else {
            ResolveInfo resolveInfo = pm.resolveActivity(baseIntent, 0);
            if (resolveInfo == null) return null;
            return resolveInfo.activityInfo.name;
        }
    }

    /**
     * Returns the ID of the last shown Tab for the given DocumentTabModel type.
     * @param context     Context to pull SharedPrefs from.
     * @param isIncognito Whether to get the ID for the regular or Incognito TabModel.
     * @return ID of the last shown Tab for the given TabModel type.
     */
    public static int getLastShownTabIdFromPrefs(Context context, boolean isIncognito) {
        SharedPreferences prefs = context.getSharedPreferences(
                DocumentTabModelImpl.PREF_PACKAGE, Context.MODE_PRIVATE);
        String prefName = isIncognito
                ? DocumentTabModelImpl.PREF_LAST_SHOWN_TAB_ID_INCOGNITO
                : DocumentTabModelImpl.PREF_LAST_SHOWN_TAB_ID_REGULAR;
        return prefs.getInt(prefName, Tab.INVALID_TAB_ID);
    }
}