package com.xplora.xpsettings.Data;

import android.app.Application;
import android.app.NotificationManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.LocaleList;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.android.internal.app.LocalePicker;
import com.android.internal.telephony.ITelephony;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.xplora.xpsettings.Model.ApnModel;
import com.xplora.xpsettings.Model.RingtoneModel;
import com.xplora.xpsettings.Utils.Constant;
import com.xplora.xpsettings.Utils.Macros;
import com.xplora.xpsettings.Utils.MetaData;
import com.xplora.xpsettings.Utils.ResUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class DataManager extends Application {
    public static String TAG = "losion / xpsettings :" + "DataManager";
    private static Context sContext = null;

    public static int mDataRoamingType = 0;
    public static int mBrightness = 50;
    public static int mScreenTime = 60;
    public static int mRingTone = 1;
    public static int mRingerMode = 2;
    public static int mSystemVolume = 10;
    public static int mMediaVolume = 50;
    public static int mCallVolume = 80;
    public static int mIsVibrate = 1;
    public static int mAppNameType = 0;
    public static int mVoLET = 1;
    public static String mTimeFormat = Constant.TIMEFORMAT_12;
    public static String mPhotoResolution = null;
    public static String mVideoResolution = null;

    @Override
    public void onCreate() {
        super.onCreate();
        sContext = getApplicationContext();
    }

    public static int getBrightness() {
        int value = Settings.System.getInt(sContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 125);
        Log.d(TAG, "getBrightness: " + value);
        return value * 100 / 255;
    }

    public static void setBrightness(int value) {
        Log.d(TAG, "setBrightness: " + value);
        if (Macros.DEBUG)
            return;
        Settings.System.putInt(sContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, value * 255 / 100);
    }

    public static int getScreenTime() {
        AtomicInteger time = new AtomicInteger(10 * 1000);
        return Settings.System.getInt(sContext.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, time.intValue());
    }

    public static void setScreenTime(int value) {
        Settings.System.putInt(sContext.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, value);
    }

    public static ArrayList<RingtoneModel> getRingToneList() {
        ArrayList<RingtoneModel> ringToneList = new ArrayList<>();
        RingtoneManager ringtoneManager= new RingtoneManager(sContext); // 铃声管理器
        Cursor cursor = ringtoneManager.getCursor(); //获取铃声表,根据表名取值
        int count = cursor.getCount(); //获取铃声列表数量
        for(int i = 0 ; i < count ; i ++){
            RingtoneModel model = new RingtoneModel();
            model.ringtone = ringtoneManager.getRingtone(i);
            model.uri = ringtoneManager.getRingtoneUri(i);
            ringToneList.add(model);
        }
        return reverseData(ringToneList);
    }

    public static ArrayList<RingtoneModel> getRingToneListTest() {
        ArrayList<RingtoneModel> ringToneList = new ArrayList<>();
        RingtoneManager ringtoneManager= new RingtoneManager(sContext); // 铃声管理器
        Cursor cursor = ringtoneManager.getCursor(); //获取铃声表,根据表名取值
        int count = cursor.getCount(); //获取铃声列表数量
        for(int i = 0 ; i < count ; i ++){
            RingtoneModel model = new RingtoneModel();
            model.ringtone = ringtoneManager.getRingtone(i);
            model.uri = ringtoneManager.getRingtoneUri(i);
            ringToneList.add(model);
        }
        return reverseData(ringToneList);
    }

    public static ArrayList reverseData(ArrayList arrayList) {
        ArrayList messageBeens = new ArrayList<>();
        for (int i = arrayList.size()-1; i >= 0; i--) {
            messageBeens.add(arrayList.get(i));
        }
        return messageBeens;
    }

    public static Uri getDefaultRingToneUri() {
        return RingtoneManager.getActualDefaultRingtoneUri(sContext, RingtoneManager.TYPE_RINGTONE);
    }

    public static Ringtone getDefaultRingTone() {
        if (Macros.DEBUG)
            return null;
        Uri uri = RingtoneManager.getActualDefaultRingtoneUri(sContext, RingtoneManager.TYPE_RINGTONE);
        return RingtoneManager.getRingtone(sContext, uri);
    }

    public static void setRingTone(int value, Uri uri) {
        if (Macros.DEBUG) {
            mRingTone = value;
        } else {
            if (uri != null) {
                RingtoneManager.setActualDefaultRingtoneUri(sContext, RingtoneManager.TYPE_RINGTONE, uri);
            }
        }
    }

    public static int getRingerMode() {
//        public static final int RINGER_MODE_SILENT = 0;
//        public static final int RINGER_MODE_VIBRATE = 1;
//        public static final int RINGER_MODE_NORMAL = 2;
        if (Macros.DEBUG) {
            return mRingerMode;
        } else {
            AudioManager audioManager = (AudioManager)sContext.getSystemService(Context.AUDIO_SERVICE);
            return audioManager.getRingerMode();
        }
    }

    public static void setRingerMode(int value) {
//        public static final int RINGER_MODE_SILENT = 0; //无声音、强制不振动
//        public static final int RINGER_MODE_VIBRATE = 1; //无声音、强制振动
//        public static final int RINGER_MODE_NORMAL = 2; //有声音、振动可以独立开关
        if (Macros.DEBUG) {
            mRingerMode = value;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setRingerMode(value);

            //carlos 处理禁用逻辑时，会使用这个字段
            Settings.Global.putInt(sContext.getContentResolver(), "soundMode_f", value);
        }
    }

    //获取是否允许静音
    public static boolean hasSilentPermission() {
        NotificationManager notificationManager = (NotificationManager) sContext.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !notificationManager.isNotificationPolicyAccessGranted()) {
            return false;
        }
        return true;
    }

    public static Map getSystemVolume() {
        Map map = new HashMap();
        if (Macros.DEBUG) {
            map.put("max", 100);
            map.put("min", 0);
            map.put("cur", 50);
            return map;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            int max = audioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
            int min = audioManager.getStreamMinVolume(AudioManager.STREAM_SYSTEM);
            int cur = audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
            map.put("max", max);
            map.put("min", min);
            map.put("cur", cur);
            return map;
        }
    }

    public static void setSystemVolume(int value) {
        if (Macros.DEBUG) {
            mSystemVolume = value;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, value, AudioManager.FLAG_PLAY_SOUND);

            if (value <= 0) {
                if (getIsVibrate() == 1) {
                    setRingerMode(1);
                } else {
                    setRingerMode(0);
                }
            } else {
                setRingerMode(2);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    public static Map getMediaVolume() {
        Map map = new HashMap();
        if (Macros.DEBUG) {
            map.put("max", 100);
            map.put("min", 0);
            map.put("cur", 50);
            return map;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            int max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            int min = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
            int cur = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            map.put("max", max);
            map.put("min", min);
            map.put("cur", cur);
            return map;
        }
    }

    public static void setMediaVolume(int value) {
        if (Macros.DEBUG) {
            mMediaVolume = value;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value, AudioManager.FLAG_PLAY_SOUND);
        }
    }

    public static Map getCallVolume() {
        Map map = new HashMap();
        if (Macros.DEBUG) {
            map.put("max", 100);
            map.put("min", 0);
            map.put("cur", 50);
            return map;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            int max = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
            int min = audioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL);
            int cur = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            map.put("max", max);
            map.put("min", min);
            map.put("cur", cur);
            return map;
        }
    }

    public static void setCallVolume(int value) {
        if (Macros.DEBUG) {
            mCallVolume = value;
        } else {
            AudioManager audioManager = (AudioManager) sContext.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, value, AudioManager.FLAG_PLAY_SOUND);
            //蓝牙连接时，通话的音量
            audioManager.setStreamVolume(6, value*3, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
        }
    }

    public static int getIsVibrate() {
        return Settings.System.getInt(sContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0);
    }

    public static void setIsVibrate(int mIsVibrate) {
        Settings.System.putInt(sContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, mIsVibrate);

        Map volume = getSystemVolume();
        int cur =  (int) volume.get("cur");
        if (mIsVibrate == 1) {
            if ( cur <= 0) {
                //无声音、强制振动
                setRingerMode(1);
            } else {
                setRingerMode(2);
            }
        } else {
            if ( cur <= 0) {
                setRingerMode(0);
            } else {
                setRingerMode(2);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    public static Map getVolume(int type) {
        if (type == 1) {
            return DataManager.getMediaVolume();
        } else if (type == 2) {
            return DataManager.getCallVolume();
        } else {
            return DataManager.getSystemVolume();
        }
    }

    public static void setVolume(int type, int value) {
        if (type == 1) {
            DataManager.setMediaVolume(value);
        } else if (type == 2) {
            DataManager.setCallVolume(value);
        } else {
            DataManager.setSystemVolume(value);
        }
    }

    public static String getCurrentLanguage() {
        LocaleList list = LocalePicker.getLocales();
        if (list.size() <= 0)
            return "";
        String s = list.get(0).toString();
        if (s.isEmpty())
            return "";
        if (s.contains("-")) {
            s = s.split("-")[0];
        } else if (s.contains("_")) {
            s = s.split("_")[0];
        }
        Log.d(TAG, "getCurrentLanguage: " + s);
        return s;
    }

    public static ArrayList<String> getLanguageList() {
        String[] languages = LocalePicker.getSystemAssetLocales();
        Log.d(TAG, "getLanguageList1: " + Arrays.toString(languages));

        ArrayList<String> list = new ArrayList<>();
        for (String s:languages) {
            if (s == null || s.isEmpty())
                continue;
            if (s.contains("-")) {
                s = s.split("-")[0];
            } else if (s.contains("_")) {
                s = s.split("_")[0];
            }
            boolean isExist = list.contains(s);
            if (isExist)
                continue;
            list.add(s);
        }
        Log.d(TAG, "getLanguageList2: " + list.toString());
        return list;
    }

    public static List<Locale> getSupportLocale(Context context) {
        List<LocalePicker.LocaleInfo> locales = LocalePicker.getAllAssetLocales(context, false);
        List<Locale> localeStrings = new ArrayList<Locale>();
        for (int i = 0; i < locales.size(); i++) {
            LocalePicker.LocaleInfo localeInfo = locales.get(i);
            if (localeInfo != null) {
                Locale locale = localeInfo.getLocale();

                if (locale != null) {
                    localeStrings.add(locale);
                    Log.d(TAG, "support locale DisplayLanguage = " + locale.getDisplayLanguage(locale));
                }
            }
        }
        return localeStrings;
    }

    public static int getDataRoamingType() {
        if (Macros.DEBUG) {
            return mDataRoamingType;
        } else {
            return Settings.Global.getInt(sContext.getContentResolver(), Settings.Global.DATA_ROAMING, 0);
        }
    }

    public static void setDataRoamingType(int value) {
        if (Macros.DEBUG) {
            mDataRoamingType = value;
        } else {
            Settings.Global.putInt(sContext.getContentResolver(), Settings.Global.DATA_ROAMING, value);
        }
    }

    public static void setNewMessageStatus() {
        if (!Macros.DEBUG) {
            Settings.Global.putString(sContext.getContentResolver(), MetaData.KEY_NEW_MESSAGE, "");
        }
    }

    //是否 watch 激活
    public static int isWatchActivated() {
        int isActivated = Settings.Global.getInt(sContext.getContentResolver(), MetaData.KEY_WATCH_ACTIVATED, 0);
        Log.d(TAG, "isWatchActivated: " + isActivated);
        return isActivated;
    }

    public static String getTimeFormat() {
        if (Macros.DEBUG) {
            return mTimeFormat;
        }
        String format = Settings.System.getString(sContext.getContentResolver(), Settings.System.TIME_12_24);
        if (format == null || format.equals("")) {
            format = Constant.TIMEFORMAT_12;
            setTimeFormat(format);
        }
        return format;
    }

    public static void setTimeFormat(String format) {
        if (Macros.DEBUG) {
            mTimeFormat = format;
            return;
        }
        Settings.System.putString(sContext.getContentResolver(), Settings.System.TIME_12_24, format);
    }

    public static int getVoLTE() {
        if (Macros.DEBUG) {
            return mVoLET;
        }

        try {
            TelephonyManager localTelephonyManager = (TelephonyManager)sContext.getSystemService(Context.TELEPHONY_SERVICE);
            Class clazz = Class.forName(localTelephonyManager.getClass().getName());
            Method m = clazz.getDeclaredMethod("getITelephony");
            m.setAccessible(true);
            ITelephony it = (ITelephony) m.invoke(localTelephonyManager);
            return it.isVolteAvailable() ? 1 : 0;
        } catch (RemoteException ex) {
            return 0;
        } catch (NullPointerException ex) {
            return 0;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        int value = Settings.Global.getInt(sContext.getContentResolver(), "volte_vt_enabled", 0);
        Log.d(TAG, "getVoLTE:" + value);
        return value;
    }

    public static void setVoLET(int value) {
        Log.d(TAG, "setVoLET: " + value);
        SetVolteEnable(value == 1);
        Settings.Global.putInt(sContext.getContentResolver(), "volte_vt_enabled", value);
    }

    public static int getAppNameType() {
        if (Macros.DEBUG) {
            return mAppNameType;
        } else {
            return Settings.Global.getInt(sContext.getContentResolver(), MetaData.KEY_APP_NAME, 0);
        }
    }

    public static void setAppNameType(int value) {
        if (Macros.DEBUG) {
            mAppNameType = value;
        } else {
            Settings.Global.putInt(sContext.getContentResolver(), MetaData.KEY_APP_NAME, value);
        }
    }

    public static void setChangeLanguageStatus(int value) {
        Settings.Global.putInt(sContext.getContentResolver(), "change_language", value);
    }

    public static int getCloseDisableStatus() {
        return Settings.Global.getInt(sContext.getContentResolver(), MetaData.KEY_CLOSE_DISABLE, 0);
    }

    public static void setCloseDisableStatus(int value) {
        Settings.Global.putInt(sContext.getContentResolver(), MetaData.KEY_CLOSE_DISABLE, value);
    }

    public static int getChargingStatus() {
        return Settings.Global.getInt(sContext.getContentResolver(), "sk_charging_status", 1);
    }

    public static void setChargingStatus(int value) {
        Settings.Global.putInt(sContext.getContentResolver(), "sk_charging_status", value);
    }

    public static int getLockShutDown() {
        return Settings.Global.getInt(sContext.getContentResolver(), MetaData.KEY_LOCK_SHUTDOWN, 0);
    }

    public static void setLockShutDown(int value) {
        Settings.Global.putInt(sContext.getContentResolver(), MetaData.KEY_LOCK_SHUTDOWN, value);
    }

    public static String getPhotoResolution() {
        if (Macros.DEBUG) {
            if (mPhotoResolution == null)
                return "1280 x 720";
            return mPhotoResolution;
        } else {
            String resolution = Settings.Global.getString(sContext.getContentResolver(), MetaData.KEY_RESOLUTION_PHOTO);
            if (resolution == null || resolution.isEmpty()) {
                resolution = "1280 x 720";
                setPhotoResolution(resolution);
            }
            return resolution;
        }
    }

    public static void setPhotoResolution(String value) {
        if (Macros.DEBUG) {
            mPhotoResolution = value;
        } else {
            Settings.Global.putString(sContext.getContentResolver(), MetaData.KEY_RESOLUTION_PHOTO, value);
        }
    }

    public static String getVideoResolution() {
        if (Macros.DEBUG) {
            if (mVideoResolution == null)
                return "480p";
            return mVideoResolution;
        } else {
            String resolution = Settings.Global.getString(sContext.getContentResolver(), MetaData.KEY_RESOLUTION_VIDEO);
            if (resolution == null || resolution.isEmpty()) {
                resolution = "480p";
                setVideoResolution(resolution);
            }
            return resolution;
        }
    }

    public static void setVideoResolution(String value) {
        if (Macros.DEBUG) {
            mVideoResolution = value;
        } else {
            Settings.Global.putString(sContext.getContentResolver(), MetaData.KEY_RESOLUTION_VIDEO, value);
        }
    }

    //true:ESIM false: nano sim
    public static boolean getIsSupportESIM() {
        return SystemProperties.getBoolean("ro.product.support.esim", false);
    }

    public static String getEsimEid() {
        return Settings.Global.getString(sContext.getContentResolver(), "lpa_eid");
    }

    public static String getIMEI() {
        if (Macros.DEBUG) {
            return "867909043812052";
        } else {
            return SystemProperties.get("persist.zs.imei.number", "");
        }
    }

    public static String getSN() {
        if (Macros.DEBUG) {
            return "";
        } else {
            return SystemProperties.get("persist.zs.sn.number", "");
        }
    }

    public static String getBTMac() {
        if (Macros.DEBUG) {
            return "11:22:33:44:55";
        } else {
            return SystemProperties.get("persist.zs.bt.address", "");
        }
    }

    public static String getWifiMac() {
        if (Macros.DEBUG) {
            return "11:22:33:44:55";
        } else {
            return SystemProperties.get("persist.zs.wifi.address", "");
        }
    }

    public static boolean getIsDisableWifi() {
        return SystemProperties.getBoolean("persist.operator.disable.wifi", false);
    }

    public static boolean getIsDisableRoming() {
        return SystemProperties.getBoolean("persist.operator.disable.wifi", false);
    }

    public static List<ApnModel> getApnListFromSP() {
        List<ApnModel> apnModelList = new ArrayList<>();
        if (Macros.DEBUG) {
            for (int i = 0; i < 5; i++) {
                ApnModel a = new ApnModel();
                a.name = "test" + i;
                a.apn_name = "test" + i;
                a.user_name = "test" + i;
                a.password = "test" + i;
                a.mcc = "test" + i;
                a.mnc = "test" + i;
                apnModelList.add(a);
            }

            ApnModel model = apnModelList.get(0);
            String[] specifiedValues = ResUtils.getStringArray("apn_value_array_", 9);
            model.name = specifiedValues[0];
            model.mcc = specifiedValues[1];
            model.mnc = specifiedValues[2];
        } else {
            SharedPreferences xpsp = sContext.getSharedPreferences("xpsp", 0);
            String apnlist = xpsp.getString("apnlist", "");
            Log.d(TAG, "getApnListFromSP: " + apnlist);
            if (apnlist.isEmpty())
                return apnModelList;

            Type listType = new TypeToken<List<ApnModel>>() {
            }.getType();
            Gson gson = new Gson();
            apnModelList = gson.fromJson(apnlist, listType);
        }
        return apnModelList;
    }

    public static void setApnListToSP(List<ApnModel> apnModelList) {
        Type listType = new TypeToken<List<ApnModel>>() {}.getType();
        String content = new Gson().toJson(apnModelList, listType);

        SharedPreferences xpsp = sContext.getSharedPreferences("xpsp", 0);
        SharedPreferences.Editor editor = xpsp.edit();
        editor.putString("apnlist", content);
        editor.apply();
    }

    public static boolean isCustomApn(ApnModel apnModel) {
        List<ApnModel> apnModelList = DatabaseHelper.getCustomApnList(sContext);
        for (int i = 0; i < apnModelList.size(); i++) {
            ApnModel model = apnModelList.get(i);
            if (model._id.equals(apnModel._id)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Whether the Volte/VT is enabled
     * <p>
     * Type: int (0 for false, 1 for true)
     * "volte_vt_enabled"
     */

    public static void SetVolteEnable(boolean enable){
        int value = enable ? 1 : 0;
        String volteStr = null ;
        Settings.Global Global = new Settings.Global();
        Class<?> GlobalClass = Global.getClass();
        try {
            Field field = GlobalClass.getDeclaredField("ENHANCED_4G_MODE_ENABLED");
            field.setAccessible(true);
            volteStr = (String) field.get(Global);
        } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
            e.printStackTrace();
        }
        //如果是你的App是预制为系统App的，那么直接改变即可
        android.provider.Settings.Global.putInt(sContext.getContentResolver(),volteStr, value);

        try {
            SubscriptionManager subManager = (SubscriptionManager)sContext
                    .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);

            Class<? extends SubscriptionManager> sunClass = subManager.getClass();
            Method method1 = sunClass.getDeclaredMethod("getDefaultVoicePhoneId");
            method1.setAccessible(true);
            int phoneid = (Integer) method1.invoke(subManager);

            Class<?> clazz = (Class<?>)Class.forName("com.android.ims.ImsManager");
            Constructor ct = clazz.getDeclaredConstructor(new Class[]{Context.class,int.class});
            ct.setAccessible(true);
            Object obj = ct.newInstance(new Object[]{sContext,phoneid});
            //setAdvanced4GMode
            Method method = clazz.getDeclaredMethod("setAdvanced4GMode", new Class[]{boolean.class});
            method.setAccessible(true);
            method.invoke(obj, enable);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
}
