package com.android.launcher3.model;

import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.MutableInt;
import android.util.Pair;
import android.view.View;

import com.alibaba.fastjson.JSON;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.IconCache;
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PromiseAppInfo;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.manager.Constants;
import com.android.launcher3.manager.LauncherManager;
import com.android.launcher3.provider.ImportDataTask;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.Logger;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.TraceHelper;

import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.regex.Pattern;

import static com.android.launcher3.AllAppsList.DEFAULT_APPLICATIONS_NUMBER;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
import static com.android.launcher3.LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.model.LoaderResults.filterCurrentWorkspaceItems;

public class FirstInitWorkSpaceTask {
    private static final String TAG = "FirstInitWorkSpaceTask";
    private final LauncherAppState mApp;

    private final LauncherAppsCompat mLauncherApps;
    private final UserManagerCompat mUserManager;
    private final PackageInstallerCompat mPackageInstaller;

    public final ArrayList<AppInfo> data;


    private int initAppWidgetSize;

    //    将一些应用打包初始化为文件夹
    private FolderInfo initFolder[] = new FolderInfo[5];


    //    拨号 联系人( "", ) 短信 相机 浏览器
    public static final String[] HOTSEAT_APP_PACKAGENAME = {"com.samsung.android.dialer|com.android.dialer|com.samsung.android.contacts|com.android.contacts", "com.samsung.android.messaging|com.android.mms", "com.sec.android.app.sbrowser|com.android.browser|com.heytap.browser", "com.sec.android.app.camera|com.android.camera2|com.meizu.media.camera|com.oppo.camera|com.huawei.camera"};


    public static final String[] NEED_FILTER_PACKAGE_NAME = {};


//    public static final String[]

    public FirstInitWorkSpaceTask(LauncherAppState app) {
        mApp = app;
        data = new ArrayList<>(DEFAULT_APPLICATIONS_NUMBER);
        mLauncherApps = LauncherAppsCompat.getInstance(mApp.getContext());
        mUserManager = UserManagerCompat.getInstance(mApp.getContext());
        mPackageInstaller = PackageInstallerCompat.getInstance(mApp.getContext());

    }


    public synchronized void run() {

        if (Utilities.getPrefs(mApp.getContext()).getBoolean("launcher_init", false))
            return;
        Log.e(TAG, "step 1.1: loading workspace");

        loadAllApps();

        Log.e(TAG, "step 1.2: insertWorkspaceDB");

        insertWorkspaceDB();

        Log.e(TAG, "run complete");
    }


    private void loadAllApps() {


        final List<UserHandle> profiles = mUserManager.getUserProfiles();

        Log.e(TAG, "user profiles size " + profiles.size());
        // Clear the list of apps
        for (UserHandle user : profiles) {
            // Query for the set of apps
            final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
            // Fail if we don't have any apps
            // TODO: Fix this. Only fail for the current user.
            if (apps == null || apps.isEmpty()) {
                Log.e(TAG, "apps.isEmpty");
                continue;
            }
            boolean quietMode = mUserManager.isQuietModeEnabled(user);
            // Create the ApplicationInfos
            for (int i = 0; i < apps.size(); i++) {
                LauncherActivityInfo app = apps.get(i);
                // This builds the icon bitmaps.
                Log.e(TAG, "" + i);
                data.add(new AppInfo(app, user, quietMode));
            }
        }

        if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
            // get all active sessions and add them to the all apps list
            for (PackageInstaller.SessionInfo info :
                    mPackageInstaller.getAllVerifiedSessions()) {
                PackageInstallerCompat.PackageInstallInfo installInfo = PackageInstallerCompat.PackageInstallInfo.fromInstallingState(info);
                ApplicationInfo applicationInfo = LauncherAppsCompat.getInstance(mApp.getContext())
                        .getApplicationInfo(installInfo.packageName, 0, Process.myUserHandle());
                // only if not yet installed
                if (applicationInfo == null) {
                    PromiseAppInfo promiseAppInfo = new PromiseAppInfo(installInfo);
                    data.add(promiseAppInfo);
                }

            }
        }

        Log.e(TAG, "all app size = \t" + data.size());
    }

    /**
     * 单层桌面 第一次加载需要将应用全部加载在桌面上
     */
    private void insertWorkspaceDB() {

        InvariantDeviceProfile invariantDeviceProfile = mApp.getInvariantDeviceProfile();

        int screenRows = invariantDeviceProfile.numRows;
        int screenColunms = invariantDeviceProfile.numColumns;


//        在第一页留出两行放个appwidget
        initAppWidgetSize = 2 * (screenRows);
        // Get the list of workspace screens.  We need to append to this list and
        // can not use sBgWorkspaceScreens because loadWorkspace() may not have been
        // called.
        ArrayList<Long> workspaceScreens = LauncherModel.loadWorkspaceScreensDb(mApp.getContext());
        synchronized (data) {

            List<ItemInfo> filteredItems = new ArrayList<>();
            for (ItemInfo item : data) {
//                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
//                        item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
//                    // Short-circuit this logic if the icon exists somewhere on the workspace
//                    if (shortcutExists(data, item.getIntent(), item.user)) {
//                        continue;
//                    }
//                }

                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                    if (item instanceof AppInfo) {
                        item = ((AppInfo) item).makeShortcut();
                    }
                }
                if (item != null) {
                    filteredItems.add(item);
                }
            }
            // Save the ShortcutInfo for binding in the workspace
            final ContentWriter writer = new ContentWriter(mApp.getContext());
            final ContentResolver cr = mApp.getContext().getContentResolver();


            LauncherSettings.Settings.call(cr,
                    LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);

            int remain = (filteredItems.size() + initAppWidgetSize) % (screenColunms * screenRows) > 0 ? 1 : 0;

            int workSpaceSize = (filteredItems.size() + initAppWidgetSize) / (screenColunms * screenRows) + remain;
            Log.e(TAG, filteredItems.size() + "\t" + (screenColunms * screenRows) + "\t" + workSpaceSize);

            for (int i = 0; i < workSpaceSize; i++) {

                workspaceScreens.add(LauncherSettings.Settings.call(mApp.getContext().getContentResolver(),
                        LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
                        .getLong(LauncherSettings.Settings.EXTRA_VALUE));
            }

            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

            FolderInfo systemFolder = new FolderInfo();
            systemFolder.setTitle("系统应用");

            FolderInfo tencentFolder = new FolderInfo();
            tencentFolder.setTitle("腾讯");

            final Uri favoritesUri = LauncherSettings.Favorites.CONTENT_URI;


            List<String> filterPackageNmae = Arrays.asList(NEED_FILTER_PACKAGE_NAME);
            List<String> hotseatPackageNmae = Arrays.asList(HOTSEAT_APP_PACKAGENAME);

//            存储hotseat上是否已经存在应用
            boolean[] hasHotseatPackageName = new boolean[hotseatPackageNmae.size()];
//            桌面app的顺序
            int index = 0;
            for (int i = 0; i < filteredItems.size(); i++) {
                ItemInfo item = filteredItems.get(i);

                ItemInfo itemInfo;
                if (item instanceof ShortcutInfo || item instanceof FolderInfo ||
                        item instanceof LauncherAppWidgetInfo) {
                    itemInfo = item;
                } else if (item instanceof AppInfo) {
                    itemInfo = ((AppInfo) item).makeShortcut();
                } else {
                    throw new RuntimeException("Unexpected info type");
                }


                ShortcutInfo shortcutInfo = (ShortcutInfo) itemInfo;
                String packageName = shortcutInfo.getIntent().getComponent().getPackageName();


                if (getPatternInArray(filterPackageNmae, packageName) != -1) {
//                    Logger.e(TAG, "被过滤\t" + packageName);
                    continue;
                }

                Logger.e(TAG,packageName+"\t"+itemInfo.toString());

                itemInfo.screenId = workspaceScreens.get((index + initAppWidgetSize) / (screenColunms * screenRows));

                itemInfo.cellX = index % screenColunms;
                itemInfo.cellY = (index + initAppWidgetSize) % (screenRows * screenColunms) / screenRows;

                itemInfo.id = LauncherSettings.Settings.call(cr, LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getLong(LauncherSettings.Settings.EXTRA_VALUE);
                itemInfo.rank = index;
                itemInfo.container = CONTAINER_DESKTOP;
                itemInfo.spanX = 1;
                itemInfo.spanY = 1;

//                if (Constants.SYSTEM_SETTING_APP.equals(packageName) && !TextUtils.isEmpty(LauncherManager.getInstance().getSettingActivityName())) {
//                    PackageManager packageManager = LauncherManager.getContext().getPackageManager();
//                    try {
//                        Drawable drawable = packageManager.getActivityIcon("com.android.settings", PackageManager.MATCH_SYSTEM_ONLY);
//                    } catch (PackageManager.NameNotFoundException e) {
//                        e.printStackTrace();
//                    }
//                    ((ShortcutInfo) itemInfo).title = "设置";
//                    ((ShortcutInfo) itemInfo).itemType = ITEM_TYPE_SHORTCUT;
//                    ((ShortcutInfo) itemInfo).intent = new Intent();
//                    ((ShortcutInfo) itemInfo).intent.setComponent(new ComponentName("com.android.settings", LauncherManager.getInstance().getSettingActivityName()));
//                    ((ShortcutInfo) itemInfo).intent.setClassName(LauncherManager.getContext().getPackageName(), LauncherManager.getInstance().getSettingActivityName());
//                }

                int hotseatIndex = getPatternInArray(hotseatPackageNmae, packageName);

                if (Utilities.isSystemApp(mApp.getContext(), itemInfo.getIntent()) && hotseatIndex != -1) {
                    if (!hasHotseatPackageName[hotseatIndex]) {
                        itemInfo.cellX = hotseatIndex;
                        itemInfo.screenId = hotseatIndex;
                        itemInfo.cellY = 0;
                        itemInfo.container = CONTAINER_HOTSEAT;
                        index--;
                        hasHotseatPackageName[hotseatIndex] = true;
                    }
                }



                itemInfo.onAddToDatabase(writer);
                ContentValues values = writer.getValues(mApp.getContext());

                writer.put(LauncherSettings.Favorites._ID, itemInfo.id);
                writer.put(LauncherSettings.Favorites.CELLX, itemInfo.cellX);
                writer.put(LauncherSettings.Favorites.CELLY, itemInfo.cellY);
                writer.put(LauncherSettings.Favorites.INTENT, itemInfo.getIntent());
                writer.put(LauncherSettings.Favorites.TITLE, itemInfo.title);
                writer.put(LauncherSettings.Favorites.ITEM_TYPE, item.itemType);
                writer.put(LauncherSettings.Favorites.SPANX, itemInfo.spanX);
                writer.put(LauncherSettings.Favorites.SPANY, itemInfo.spanY);
                writer.put(LauncherSettings.Favorites.CONTAINER, itemInfo.container);


                ops.add(ContentProviderOperation.newInsert(favoritesUri).withValues(values).build());

                index++;

                Logger.e(TAG,itemInfo.toString());
            }
            try {
                cr.applyBatch(LauncherProvider.AUTHORITY, ops);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }


        }

        // Update the workspace screens
        updateScreens(mApp.getContext(), workspaceScreens);


    }

    protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) {
        LauncherModel.updateWorkspaceScreenOrder(context, workspaceScreens);
    }


    public int getPatternInArray(List<String> patterns, String packageName) {
        for (int i = 0; i < patterns.size(); i++) {

//            Logger.e(TAG, patterns.get(i) + "\t" + packageName);
            if (Pattern.matches(patterns.get(i), packageName)) {
                return i;
            }
        }
        return -1;
    }

}