package com.android.launcher3.debug;

import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.R;
import com.android.launcher3.manager.ColumnDef;
import com.android.launcher3.manager.LauncherManager;
import com.android.launcher3.manager.ManagementInfo;
import com.android.launcher3.manager.TimeModeManager;
import com.android.launcher3.model.AppTimeConfig;
import com.android.launcher3.model.AppUseData;
import com.android.launcher3.model.TimeConfig;
import com.android.launcher3.model.TimeRegion;
import com.android.launcher3.util.Logger;
import com.android.launcher3.util.PermissionUtil;
import com.android.launcher3.util.TimeUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import androidx.annotation.Nullable;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * 查询应用是否可以使用
 */
public class SearchAppCanUseActivity extends BaseActivity implements View.OnClickListener {

    private ImageView ivBack;
    private Button btn_confirm;
    private EditText et_package;
    private TextView tv_reason;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_app_can_use);

        ivBack = findViewById(R.id.iv_back);
        btn_confirm = findViewById(R.id.btn_confirm);
        et_package = findViewById(R.id.et_package);
        tv_reason = findViewById(R.id.tv_reason);


        ivBack.setOnClickListener(this);
        btn_confirm.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.iv_back) {
            finish();
        } else if (id == R.id.btn_confirm) {
            if (TextUtils.isEmpty(et_package.getText().toString().trim())) {
                Toast.makeText(getApplicationContext(), "请输入包名", Toast.LENGTH_SHORT).show();
                return;
            }

            search(et_package.getText().toString().trim());

        }
    }

    private void search(String packageName) {
        ManagementInfo managementInfo = LauncherManager.getInstance().getManageAppInfo(packageName);
        if (managementInfo == null) {
            tv_reason.setText("应用未分类不可使用");
            return;
        }

        if (managementInfo.getUseType() == ColumnDef.AppUseType.UNCLASS_TYPE) {
            tv_reason.setText("应用未分类不可使用");
            return;
        }


        if (managementInfo.getUseType() == ColumnDef.AppUseType.LEARN_TYPE || managementInfo.getUseType() == ColumnDef.AppUseType.SAFE_TYPE) {
            tv_reason.setText("无需管控类或学习类可以正常使用");
            return;
        }

        Observable.just(packageName).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).map(new Function<String, String>() {
            @Override
            public String apply(String s) throws Exception {
                return canUse(s);
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Toast.makeText(getApplicationContext(), "正在查询请稍后", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNext(String s) {
                tv_reason.setText(s);
            }

            @Override
            public void onError(Throwable e) {
                Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onComplete() {

            }
        });

    }


    /**
     * 判断应用是否可以使用
     *
     * @param packageName
     * @return
     */
    public String canUse(String packageName) {
        ManagementInfo info = LauncherManager.getInstance().getManageAppInfo(packageName);
        int currentWorkModel = TimeModeManager.getInstance(this).getCurrentWorkModel();
        TimeConfig config = TimeModeManager.getInstance(this).getTimeConfig(TimeModeManager.getInstance(this).getCurrentWorkModel());
        Map<Integer, TimeConfig> configMap = TimeModeManager.getInstance(this).getConfigMap();

        if (config == null) {
            return "没有设置工作模式 App不可使用";
        }


        if (info.getLock() != ColumnDef.LockApp.LOCKED) {
            if (includeTimeRegion(config.getRegionList())) {

                //        判断金币是否充足
                if (LauncherManager.getInstance().getCoinNum() <= 0) {

                    return "金币不足 App不可使用";
                }

                long canUseTime = 0;

                // 获取某个应用类别下的使用时间
                if (currentWorkModel == ColumnDef.TimeManager.HOLIDAY_MODE) {
                    canUseTime = getUseTimeByAppType(config.getAppTimeConfigs(), info.getUseType());
                } else {
                    if (TimeUtils.isWeekend()) {
                        currentWorkModel = ColumnDef.TimeManager.WEEK_RESET;
                        canUseTime = getUseTimeByAppType(configMap.get(ColumnDef.TimeManager.WEEK_RESET).getAppTimeConfigs(), info.getUseType());
                    } else {
                        currentWorkModel = ColumnDef.TimeManager.WORK_DAY;
                        canUseTime = getUseTimeByAppType(configMap.get(ColumnDef.TimeManager.WORK_DAY).getAppTimeConfigs(), info.getUseType());
                    }
                }

                HashMap<Integer, Long> useTimestamp = getAppUseTimeStamp(this);

                long totalUseTimeByType = useTimestamp.get(info.getUseType());


                if (totalUseTimeByType > canUseTime) {

                    return "当前应用所属的分类时长已使用完毕\t" + "该分类下已使用的总时长\n" + totalUseTimeByType + "\t" + "该分类下可使用的总时长\n" + canUseTime;
                }

//                app自身的设置使用时长优先级更高
                if (info.getUseEndTimeStamp() > 0) {
//                    应用本身的使用时间
                    canUseTime = Math.min(canUseTime, info.getUseEndTimeStamp());
                }


                long hadUseTime = getAppUseTimeStampDay(this, packageName);
                if (canUseTime > 0 && hadUseTime > canUseTime) {
                    return "应用无法使用\t" + "该分类下已使用的总时长 =" + totalUseTimeByType + "\t" + "该分类下可使用的总时长=" + canUseTime + "\t应用自身的可使用时长=" + info.getUseEndTimeStamp() + "\t应用当天已使用时长=" + hadUseTime;
                }

                return "应用可以正常使用\t" + "该分类下已使用的总时长 =" + totalUseTimeByType + "\t" + "该分类下可使用的总时长=" + canUseTime + "\t应用自身的可使用时长=" + info.getUseEndTimeStamp() + "\t应用当天已使用时长=" + hadUseTime;
            }
        } else {
            return "应用已锁定 无法使用";
        }

        return "应用可以正常使用";
    }


    /**
     * 获取某个app当天的已使用时长
     *
     * @param context
     * @param packageName
     * @return
     */
    private long getAppUseTimeStampDay(Context context, String packageName) {
        long totalUseTimeStampDaliy = 0;
        if (PermissionUtil.checkAppUsagePermission(context)) {
            UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);


            Calendar beginCal = Calendar.getInstance();
            beginCal.set(Calendar.HOUR_OF_DAY, 0);
            beginCal.set(Calendar.MINUTE, 0);
            beginCal.set(Calendar.SECOND, 0);
            Calendar endCal = Calendar.getInstance();
            UsageEvents events = usageStatsManager.queryEvents(beginCal.getTimeInMillis(), endCal.getTimeInMillis());
            UsageEvents.Event event = new UsageEvents.Event();

            long startTime = beginCal.getTimeInMillis();
            boolean isForegounding = false;
            while (events.hasNextEvent()) {

                events.getNextEvent(event);
                int eventType = event.getEventType();
                long eventTime = event.getTimeStamp();
                String eventPackage = event.getPackageName();

                if (eventPackage.equals(packageName)) {
                    if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {

                        startTime = eventTime;
                        isForegounding = true;
                    }

                    if (eventType == UsageEvents.Event.MOVE_TO_BACKGROUND) {
                        isForegounding = false;
                        totalUseTimeStampDaliy += eventTime - startTime;
                    }

                }

            }

            if (isForegounding) {
                totalUseTimeStampDaliy += System.currentTimeMillis() - startTime;
            }

        }

        return totalUseTimeStampDaliy / 1000;
    }

    /**
     * 判断当前时间是否在选中的时间范围内
     *
     * @param regionList
     * @return
     */
    public boolean includeTimeRegion(List<TimeRegion> regionList) {

        if (regionList == null)
            return false;
        if (regionList.isEmpty())
            return false;

        long time = (System.currentTimeMillis() - TimeUtils.getTimeZeroClock()) / 1000;
        for (TimeRegion region : regionList) {
            if (region.containTime(time)) {
                return true;
            }
        }

        return false;
    }

    public long getUseTimeByAppType(List<AppTimeConfig> timeConfigs, @ColumnDef.AppUseType.UseTypeMode int appType) {

        if (timeConfigs == null)
            return 0;

        for (AppTimeConfig timeConfig : timeConfigs) {
            if (timeConfig.appType == appType) {
                return timeConfig.appUseTimeSecond;
            }
        }

        return 0;
    }


    /**
     * 获取各个分类的所有app下当天已使用的时长
     *
     * @return
     */
    public HashMap<Integer, Long> getAppUseTimeStamp(Context context) {
        ArrayMap<String, ManagementInfo> appInfo = LauncherManager.getInstance().getAppInfo();
        HashMap<Integer, Long> timeStamp = new HashMap<>();

        HashSet<String> usedPackaged = new HashSet<>();

        List<AppUseData> data = new ArrayList<>();
        if (PermissionUtil.checkAppUsagePermission(context)) {
            UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);


//            计算当天使用过的应用
            if (usageStatsManager != null) {

                Calendar beginCal = Calendar.getInstance();
                beginCal.set(Calendar.HOUR_OF_DAY, 0);
                beginCal.set(Calendar.MINUTE, 0);
                beginCal.set(Calendar.SECOND, 0);
                Calendar endCal = Calendar.getInstance();
                UsageEvents events = usageStatsManager.queryEvents(beginCal.getTimeInMillis(), endCal.getTimeInMillis());

                UsageEvents.Event event = new UsageEvents.Event();
                while (events.hasNextEvent()) {
                    events.getNextEvent(event);

                    if (event.getEventType() == UsageEvents.Event.MOVE_TO_BACKGROUND || event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
                        String eventPackage = event.getPackageName();

                        usedPackaged.add(eventPackage);
                    }

                }
            }
        }


        Iterator<String> iterator = usedPackaged.iterator();

        //计算当天使用过的应用 使用时长
        while (iterator.hasNext()) {
            String packageName = iterator.next();

            long useTimeStamp = getAppUseTimeStampDay(context, packageName);
            data.add(new AppUseData(packageName, useTimeStamp));
        }


        long totalUseTimeStampDaliyLearnType = 0;
        long totalUseTimeStampDaliyGameType = 0;
        long totalUseTimeStampDaliyUnclassType = 0;
        long totalUseTimeStampDaliySafeType = 0;

        if (data.size() > 0) {
            for (AppUseData useData : data) {

                long useTimestamp = useData.mUsageTime;

                ManagementInfo info = appInfo.get(useData.mPackageName);

                if (LauncherManager.getInstance().isSafePackageName(useData.mPackageName)) {
                    totalUseTimeStampDaliySafeType += useTimestamp;
                } else {
                    if (info != null) {
                        switch (info.getUseType()) {
                            case ColumnDef.AppUseType.LEARN_TYPE:
                                totalUseTimeStampDaliyLearnType += useTimestamp;
                                break;
                            case ColumnDef.AppUseType.GAME_LOCK_TYPE:
                                totalUseTimeStampDaliyGameType += useTimestamp;
                                break;
                            case ColumnDef.AppUseType.SAFE_TYPE:
                                totalUseTimeStampDaliySafeType += useTimestamp;
                                break;
                        }
                    } else {
                        totalUseTimeStampDaliyUnclassType += useTimestamp;
                    }
                }

            }

        }


        timeStamp.put(ColumnDef.AppUseType.LEARN_TYPE, totalUseTimeStampDaliyLearnType);

        timeStamp.put(ColumnDef.AppUseType.GAME_LOCK_TYPE, totalUseTimeStampDaliyGameType);

        timeStamp.put(ColumnDef.AppUseType.SAFE_TYPE, totalUseTimeStampDaliySafeType);

        timeStamp.put(ColumnDef.AppUseType.UNCLASS_TYPE, totalUseTimeStampDaliyUnclassType);

        return timeStamp;

    }


}
