package com.meeting.demo.utils;

import static com.meeting.demo.constant.ConfigConstant.KEY_DISABLE_MENU_CONFIG;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.RecyclerView;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.huawei.cloudlink.openapi.HWMSdk;
import com.huawei.cloudlink.openapi.model.HWMEnableFeatureType;
import com.huawei.hwmbiz.HWMBizSdk;
import com.huawei.hwmcommonui.ui.popup.dialog.base.BaseDialogBuilder;
import com.huawei.hwmcommonui.utils.DateUtil;
import com.huawei.hwmconf.presentation.dependency.menu.IConfMenu;
import com.huawei.hwmconf.sdk.model.conf.entity.AttendeeModel;
import com.huawei.hwmconf.sdk.model.conf.entity.ConfBaseInfo;
import com.huawei.hwmconf.sdk.model.conf.entity.ConfInfo;
import com.huawei.hwmconf.sdk.util.BaseDateUtil;
import com.meeting.demo.constant.ConfigConstant;
import com.meeting.demo.dependency.NeedCustomType;
import com.meeting.demo.model.ApiPageModel;
import com.meeting.demo.model.ConfItemModel;
import com.meeting.demo.view.DemoActivity;
import com.meeting.demo.view.sdkconfig.menu.DisabledMenuConfig;
import com.huawei.hwmfoundation.HwmContext;
import com.huawei.hwmfoundation.utils.PreferenceUtils;
import com.huawei.hwmfoundation.utils.route.HCActivityManager;
import com.huawei.hwmlogger.HCLog;
import com.huawei.hwmsdk.enums.ConfMediaType;
import com.huawei.hwmsdk.enums.ConferenceType;
import com.huawei.hwmsdk.enums.DeployType;
import com.huawei.hwmsdk.enums.HardCodecMode;
import com.huawei.hwmsdk.enums.NetworkAccessType;
import com.huawei.hwmsdk.model.param.SubCycleConfParam;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

public class DemoUtil {
    private static final String TAG = DemoUtil.class.getSimpleName();

    private static DemoUtil mInstance = null;

    private static Application application;

    private volatile static DisabledMenuConfig disabledMenuConfig;

    private static final LinkedList<String> toastLogs = new LinkedList<>();

    public synchronized static DemoUtil getInstance() {
        if (mInstance == null) {
            mInstance = new DemoUtil();
        }
        return mInstance;
    }

    public static List<AttendeeModel> attendeeModels;

    public static List<AttendeeModel> selectModels;

    public static ConfInfo customizeQR;

    public static void clearSelectModels() {
        if (selectModels != null) {
            selectModels.clear();
        }
    }

    public static String getCustomSiteAddress() {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_ADDRESS_CUSTOM, "", DemoUtil.getApplication());
    }

    public static int getCustomSitePort() {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_PORT_CUSTOM, 0, DemoUtil.getApplication());
    }

    public static NetworkAccessType getCustomSiteProxy() {
        int proxyValue = PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_PROXY_CUSTOM, NetworkAccessType.ACCESS_TYPE_AUTO.getValue(), DemoUtil.getApplication());
        return NetworkAccessType.enumOf(proxyValue);
    }

    public static void setCustomSiteAddress(String customSiteAddress) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_ADDRESS_CUSTOM, customSiteAddress, DemoUtil.getApplication());
    }

    public static void setCustomSitePort(int customSitePort) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_PORT_CUSTOM, customSitePort, DemoUtil.getApplication());
    }

    public static void setCustomSiteProxy(NetworkAccessType customSiteProxy) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_PROXY_CUSTOM, customSiteProxy.getValue(), DemoUtil.getApplication());
    }

    public static String getDeployInfoSiteAddress() {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_ADDRESS_DEPLOY_INFO, "", DemoUtil.getApplication());
    }

    public static int getDeployInfoSitePort() {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_PORT_DEPLOY_INFO, 0, DemoUtil.getApplication());
    }

    public static DeployType getDeployType() {
        int type = PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.DEPLOY_TYPE, 0, DemoUtil.getApplication());
        return DeployType.enumOf(type);
    }

    public static void setDeployInfoSiteAddress(String siteAddress) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_ADDRESS_DEPLOY_INFO, siteAddress, DemoUtil.getApplication());
    }

    public static void setDeployInfoSitePort(int sitePort) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.SITE_PORT_DEPLOY_INFO, sitePort, DemoUtil.getApplication());
    }

    public static void setDeployType(DeployType deployType) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.DEPLOY_TYPE, deployType.getValue(), DemoUtil.getApplication());
    }

    public static HardCodecMode getHardCodecMode() {
        int hardCodecValue = PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.HARD_CODEC_MODE, 0, DemoUtil.getApplication());
        return HardCodecMode.values()[hardCodecValue];
    }

    public static void setHardCodecMode(HardCodecMode hardCodecMode) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.HARD_CODEC_MODE, hardCodecMode.ordinal(), DemoUtil.getApplication());
    }

    public static boolean needCustom(String customStr) {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, customStr, false, DemoUtil.getApplication());
    }

    public static boolean needCustom(String customStr, boolean defaultValue) {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, customStr, defaultValue, DemoUtil.getApplication());
    }

    public static void setCustom(String customStr, ApiPageModel model) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, customStr, !model.checkStyle, DemoUtil.getApplication());
    }

    public static void setCustom(String customStr, boolean enable) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, customStr, enable, DemoUtil.getApplication());
    }
    
    public static void saveString(String customKey, String customValue) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, customKey, customValue, DemoUtil.getApplication());
    }

    public static String readString(String customKey) {
        return PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, customKey, "", DemoUtil.getApplication());
    }

    public static String getCustomLanguage() {
        String language = PreferenceUtils.read(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.LANGUAGE_CUSTOM, "", DemoUtil.getApplication());
        return language;
    }

    public static void settCustomLanguage(String customLanguage) {
        PreferenceUtils.save(PreferenceUtils.PREFERENCES_NAME, NeedCustomType.LANGUAGE_CUSTOM, customLanguage, DemoUtil.getApplication());
    }

    private static boolean packageInstalled(Context context, String packageName) {
        PackageInfo packageInfo = null;
        try {
            packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
        return packageInfo != null;
    }

    public static void openAppWithURL(Context context, String url) {
        try {
            Intent intent = new Intent();
            intent.setData(Uri.parse(url));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            context.startActivity(intent);
        } catch (Exception e) {
            HCLog.e(TAG, " openAppWithURL error " + e);
        }
    }

    public static void showToast(String msg) {
        showToast(msg, Toast.LENGTH_LONG);
    }

    public static void addConsoleLog(String logMsg) {
        String toastTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(System.currentTimeMillis());
        toastLogs.add(toastTime + "---> " + logMsg);
        if (toastLogs.size() > 500) {
            toastLogs.removeFirst();
        }
    }

    public static void showToast(String msg, int duration) {
        addConsoleLog(msg);
        if (DemoUtil.needCustom(NeedCustomType.IGNORE_DEMO_TOAST)) {
            return;
        }
        HwmContext.getInstance().runOnMainThread(() -> Toast.makeText(HWMSdk.getApplicationContext(), msg, duration).show());
    }
    public static RecyclerView.ItemDecoration getRecyclerViewDivider(Context context, @DrawableRes int drawableId) {
        DividerItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
        itemDecoration.setDrawable(context.getResources().getDrawable(drawableId));
        return itemDecoration;
    }

    public static boolean isApkInDebug(Context context) {
        try {
            ApplicationInfo info = context.getApplicationInfo();
            return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        } catch (Exception e) {
            return false;
        }
    }

    private ConfItemModel transform(ConfBaseInfo ckConfListInfo) {
        ConfItemModel confItemModel = new ConfItemModel();
        String startTime = DateUtil.getLocalTimeString(ckConfListInfo.getStartTimeStamp());
        confItemModel.setStartTime(startTime);
        DemoUtil.addConsoleLog("ConfBaseInfo startTimeStamp: " + ckConfListInfo.getStartTimeStamp());
        String endTime = DateUtil.getLocalTimeString(ckConfListInfo.getEndTimeStamp());
        confItemModel.setEndTime(endTime);
        DemoUtil.addConsoleLog("ConfBaseInfo endTimeStamp: " + ckConfListInfo.getEndTimeStamp());
        confItemModel.setConfId(ckConfListInfo.getConfId());
        confItemModel.setVmrConferenceId(ckConfListInfo.getVmrConferenceId());
        confItemModel.setConfSubject(ckConfListInfo.getConfSubject());
        confItemModel.setMediaType(ckConfListInfo.getMediaType());
        confItemModel.setScheduserName(ckConfListInfo.getScheduserName());
        confItemModel.setAccessNumber(ckConfListInfo.getAccessNumber());
        confItemModel.setChairmanPwd(ckConfListInfo.getChairmanPwd());
        confItemModel.setGeneralPwd(ckConfListInfo.getGuestPwd());
        confItemModel.setCycleConf(ckConfListInfo.getConferenceType() == ConferenceType.CONF_TYPE_CYCLE);

        return confItemModel;
    }

    private ConfItemModel transformSubCycleConf(SubCycleConfParam subCycleConfParam) {
        ConfItemModel confItemModel = new ConfItemModel();
        String startTime = DateUtil.getLocalTimeString(subCycleConfParam.getStartTimeStamp());
        confItemModel.setStartTime(startTime);
        DemoUtil.addConsoleLog("SubCycleConfParam startTimeStamp: " + subCycleConfParam.getStartTimeStamp());
        String endTime = DateUtil.getLocalTimeString(subCycleConfParam.getEndTimeStamp());
        DemoUtil.addConsoleLog("SubCycleConfParam endTimeStamp: " + subCycleConfParam.getEndTimeStamp());
        confItemModel.setEndTime(endTime);
        confItemModel.setMediaType(subCycleConfParam.getConfMediaType() == ConfMediaType.CONF_MEDIA_VIDEO ? 21 : 17);
        confItemModel.setConfId(subCycleConfParam.getSubConfID());
        confItemModel.setConfSubject(startTime);
        confItemModel.setSubCycleConf(true);
        return confItemModel;
    }

    public List<ConfItemModel> transform(List<ConfBaseInfo> ckConfListInfos) {
        if (ckConfListInfos == null || ckConfListInfos.size() == 0) {
            return null;
        }
        List<ConfBaseInfo> temp = new ArrayList<>(ckConfListInfos);
        Collections.sort(temp, (ckConfListInfo1, ckConfListInfo2) -> {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
            try {
                Date dt1 = format.parse(
                    BaseDateUtil.timeStamp2GMTDate(ckConfListInfo1.getStartTimeStamp(), BaseDateUtil.FMT_YMDHM));
                Date dt2 = format.parse(
                    BaseDateUtil.timeStamp2GMTDate(ckConfListInfo2.getStartTimeStamp(), BaseDateUtil.FMT_YMDHM));
                if (dt1.getTime() > dt2.getTime()) {
                    return 1;
                } else if (dt1.getTime() < dt2.getTime()) {
                    return -1;
                } else {
                    return 0;
                }
            } catch (Exception e) {
                HCLog.e(TAG, " transform error ");
            }
            return 0;
        });

        ckConfListInfos.clear();
        ckConfListInfos.addAll(temp);

        List<ConfItemModel> confItemModels = new ArrayList<>();
        if (!ckConfListInfos.isEmpty()) {
            for (ConfBaseInfo ckConfListInfo : ckConfListInfos) {
                confItemModels.add(transform(ckConfListInfo));
            }
        }
        return confItemModels;
    }

    public List<ConfItemModel> transformSubCycleConfList(List<SubCycleConfParam> subCycleConfList) {
        if (subCycleConfList == null || subCycleConfList.size() == 0) {
            return null;
        }
        List<SubCycleConfParam> temp = new ArrayList<>(subCycleConfList);
        Collections.sort(temp, (ckConfListInfo1, ckConfListInfo2) -> {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
            try {
                Date dt1 = format.parse(
                    BaseDateUtil.timeStamp2GMTDate(ckConfListInfo1.getStartTimeStamp(), BaseDateUtil.FMT_YMDHM));
                Date dt2 = format.parse(
                    BaseDateUtil.timeStamp2GMTDate(ckConfListInfo2.getStartTimeStamp(), BaseDateUtil.FMT_YMDHM));
                if (dt1.getTime() > dt2.getTime()) {
                    return 1;
                } else if (dt1.getTime() < dt2.getTime()) {
                    return -1;
                } else {
                    return 0;
                }
            } catch (Exception e) {
                HCLog.e(TAG, " transform error ");
            }
            return 0;
        });

        subCycleConfList.clear();
        subCycleConfList.addAll(temp);

        List<ConfItemModel> confItemModels = new ArrayList<>();
        if (!subCycleConfList.isEmpty()) {
            for (SubCycleConfParam subConf : subCycleConfList) {
                confItemModels.add(transformSubCycleConf(subConf));
            }
        }
        return confItemModels;
    }

    public static String getRandomString(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        SecureRandom secureRandom = new SecureRandom();
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            try {
                secureRandom = SecureRandom.getInstanceStrong();
            } catch (NoSuchAlgorithmException e) {
                HCLog.e(TAG, " NoSuchAlgorithmException use default");
            }
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = secureRandom.nextInt(str.length());
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

    public static Application getApplication() {
        return application;
    }

    public static void setApplication(Application application) {
        DemoUtil.application = application;
    }


    public static Context getResContext() {
        Activity cur = HCActivityManager.getInstance().getCurActivity();
        if (cur != null) {
            return cur;
        } else {
            HCLog.i(TAG, "getResContext get cur Activity null");
            return getApplication();
        }
    }

    public static DisabledMenuConfig getDisabledMenuConfig() {
        if (disabledMenuConfig == null) {
            disabledMenuConfig =  new DisabledMenuConfig();
        }
        return disabledMenuConfig;
    }

    public static void setDisabledMenuConfig(DisabledMenuConfig disabledMenuConfig) {
        DemoUtil.disabledMenuConfig = disabledMenuConfig;
    }

    public static void initDisabledMenuConfig(@NonNull Application application) {
        String data = PreferencesUtil.getStringPreference(application, KEY_DISABLE_MENU_CONFIG, "");
        if (!TextUtils.isEmpty(data)) {
            disabledMenuConfig = new Gson().fromJson(data, DisabledMenuConfig.class);
        } else {
            disabledMenuConfig = new DisabledMenuConfig();
        }
    }

    public static boolean disabled(String handleName, String groupTag, IConfMenu confMenu) {
        if (!disabledMenuConfig.getConfigMap().containsKey(handleName)) {
            return false;
        }
        if (disabledMenuConfig.getConfigMap().get(handleName).getDisabledMenuGroup() == null) {
            return false;
        }
        HashSet<String> groupMenuConfig = disabledMenuConfig.getConfigMap().get(handleName).getDisabledMenuGroup().get(groupTag);
        return groupMenuConfig != null && groupMenuConfig.contains(confMenu.getClass().getName());
    }

    public static List<HWMEnableFeatureType> queryCheckedCapabilities() {
        String savedConfig = PreferencesUtil.getStringPreference(DemoUtil.getApplication(), NeedCustomType.FEATURE_CONFIG, "");
        if (savedConfig.length() == 0) {
            return new ArrayList<>();
        }

        Gson gson = new Gson();
        return gson.fromJson(savedConfig,  new TypeToken<List<HWMEnableFeatureType>>(){}.getType());
    }

    public static String getAppName(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            return String.valueOf(packageManager.getApplicationLabel(packageInfo.applicationInfo));
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "getAppName exception");
        }
        return "";
    }

    public static LinkedList<String> getToastLogs() {
        return toastLogs;
    }

    public static void showToastDialog(String apiName, int retCode, String desc, Activity activity) {
        if (HWMBizSdk.getBizOpenApi() == null) {
            showToast(apiName + " : [" + retCode + "] " + desc);
            return;
        }
        String msg = HWMBizSdk.getBizOpenApi().getErrorMessage(retCode);
        if (TextUtils.isEmpty(msg)) {
            Log.i(TAG, "showToast msg == null!");
        }
        String errorMsg = msg + "\n" + "错误码: " + retCode + "\n" + "错误描述: " + desc;
        BaseDialogBuilder baseDialogBuilder = new BaseDialogBuilder(HCActivityManager.getInstance().isActivitySurviving(activity) ? activity : DemoActivity.getInstance());
        baseDialogBuilder
                .setMessage(errorMsg)
                .addAction("确定",
                        (dialog, button, index) -> {
                            dialog.dismiss();
                        })
                .show();
    }

    public static void showToastDialog(String apiName, int retCode, String desc) {
        Activity currentActivity = HCActivityManager.getInstance().getCurrentActivity();
        showToastDialog(apiName, retCode, desc, currentActivity);
    }

    public static String getAppId(Context context) {
        return PreferencesUtil.getStringPreference(context.getApplicationContext(), ConfigConstant.KEY_APP_ID, AppIdContants.APP_ID);
    }

    public static void restartApplication() {
        if (application == null) {
            HCLog.e(TAG, " restartApplication application is null ");
            return;
        }
        Intent intent = new Intent(application, DemoActivity.class);
        Intent restartIntent = Intent.makeRestartActivityTask(intent.getComponent());
        application.startActivity(restartIntent);
        System.exit(0);
    }
}
