package com.key.vibekeyboard.Utils;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import android.util.TypedValue;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.key.vibekeyboard.AppApplication;
import com.key.vibekeyboard.Keyboard.MyKeyboard;
import com.key.vibekeyboard.R;
import com.key.vibekeyboard.Room.Category;
import com.key.vibekeyboard.Room.WallpaperInfo;
import com.key.vibekeyboard.callback.DownloadCallback;
import com.key.vibekeyboard.callback.UnzipCallback;

import net.sf.sevenzipjbinding.ArchiveFormat;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.impl.RandomAccessFileOutStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Mytool {

    // 获取输入法管理服务的实例
    private static final InputMethodManager methodManager = (InputMethodManager) AppApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
    // 用于执行异步任务的线程池
    private static ExecutorService executorService;

    public static void onDrawKeyIcon(Keyboard.Key currentKey,
                                     Drawable drawKeyIcon,
                                     Canvas myCanvas,
                                     MyKeyboard myKeyboardView) {
        currentKey.icon = drawKeyIcon;
        currentKey.icon.setBounds(calculateIconBounds(currentKey, drawKeyIcon, myKeyboardView));
        currentKey.icon.draw(myCanvas);
    }

    private static Rect calculateIconBounds(Keyboard.Key currentKey,
                                            Drawable drawKeyIcon,
                                            MyKeyboard myKeyboardView) {
        float icon_w = drawKeyIcon.getIntrinsicWidth();
        float icon_h = drawKeyIcon.getIntrinsicHeight();
        float icon_wr = icon_w / currentKey.width;
        float icon_hr = icon_h / currentKey.height;

        float tep1, tep2;
        if (icon_wr > icon_hr) {
            tep2 = icon_wr;
            tep1 = Math.max(icon_wr, 0.5f);
        } else {
            tep2 = icon_hr;
            tep1 = Math.max(icon_hr, 0.5f);
        }

        icon_h = (icon_h / tep2) * tep1;
        icon_w = (icon_w / tep2) * tep1;

        int top = (int) (currentKey.y + myKeyboardView.getPaddingTop() + (currentKey.height - icon_h) / 2);
        int left = (int) (currentKey.x + myKeyboardView.getPaddingLeft() + (currentKey.width - icon_w) / 2);
        int bottom = top + (int) icon_h;
        int right = left + (int) icon_w;

        return new Rect(left, top, right, bottom);
    }

    // 从资源文件加载JSON数据
    public static JSONArray loadJSONFromAsset(String filename) {
        String json;
        try {
            AssetManager assetManager = AppApplication.getContext().getAssets();
            InputStream inputStream = assetManager.open(filename);
            int size = inputStream.available();
            byte[] buffer = new byte[size];
            inputStream.read(buffer);
            inputStream.close();
            json = new String(buffer, StandardCharsets.UTF_8);
            return new JSONArray(json);  // 转换为JSONArray
        } catch (IOException | JSONException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 解析JSON数据为列表
    public static List<Category> parseJsonToList(String filename) {
        List<Category> dataList = new ArrayList<>();
        try {
            JSONArray jsonObject = loadJSONFromAsset(filename);
            for (int a = 0; a < Objects.requireNonNull(jsonObject).length(); a++) {
                JSONObject list = jsonObject.getJSONObject(a);
                Category myData = new Category();
                List<WallpaperInfo> otherdataList = new ArrayList<>();
                myData.setClassName(list.getString("className"));
                JSONArray classArray = list.getJSONArray("list");
                for (int i = 0; i < classArray.length(); i++) {
                    JSONObject item = classArray.getJSONObject(i);
                    WallpaperInfo otherdata = new WallpaperInfo();
                    otherdata.setDownloaded(false);
                    otherdata.setIslike(false);
                    otherdata.setClassName(myData.getClassName());
                    otherdata.setPreview(item.getString("preview"));
                    otherdata.setThumb(item.getString("thumb"));
                    otherdata.setTitle(item.getString("title"));
                    otherdata.setZipUrl(item.getString("zipUrl"));
                    otherdataList.add(otherdata);
                }
                myData.setList(otherdataList);
                dataList.add(myData);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return dataList;
    }

    // 检查输入法步骤2（确认输入法是否为当前应用）
    public static boolean isStep2() {
        String string = Settings.Secure.getString(AppApplication.instance.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
        return string.startsWith(AppApplication.instance.getPackageName());
    }

    // 检查输入法步骤1（确认当前输入法是否被启用）
    public static boolean isStep1() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return methodManager.getEnabledInputMethodList().stream()
                    .anyMatch(inputMethodInfo -> inputMethodInfo.getId().startsWith(AppApplication.instance.getPackageName()));
        } else {
            InputMethodManager inputMethodManager = (InputMethodManager) AppApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
            List<InputMethodInfo> inputMethodList = inputMethodManager.getEnabledInputMethodList();
            for (InputMethodInfo inputMethodInfo : inputMethodList) {
                if (inputMethodInfo.getId().startsWith(AppApplication.instance.getPackageName())) {
                    return true;
                }
            }
            return false;
        }
    }

    // 解压文件的操作
    public static void unZip(Context context, String urlpath, File resource, UnzipCallback callback) throws IOException {
        if (!resource.exists()) {  // 如果资源文件不存在，显示下载失败的提示
            Toast.makeText(context, context.getString(R.string.app_name), Toast.LENGTH_SHORT).show();
        } else {
            String itemFilePath = "";

            // 使用应用的外部文件目录来存储解压后的文件
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir == null) {
                externalDir = context.getFilesDir();  // 如果外部存储不可用，则回退到内部存储
            }

            String extractPath = new File(externalDir, "ExtractedFiles").getAbsolutePath();  // 定义一个专门的文件夹存储解压文件

            RandomAccessFile accessFile = new RandomAccessFile(resource, "r");
            RandomAccessFileInStream inStream = new RandomAccessFileInStream(accessFile);
            IInArchive iInArchive = SevenZip.openInArchive(ArchiveFormat.SEVEN_ZIP, inStream);
            ISimpleInArchiveItem[] archiveItems = iInArchive.getSimpleInterface().getArchiveItems();

            // 解压每一个文件
            for (int d = 0; d < archiveItems.length; d++) {
                ISimpleInArchiveItem simple = archiveItems[d];
                File file = new File(extractPath, simple.getPath());  // 将解压路径设置为外部存储目录
                if (!simple.isFolder()) {  // 如果不是文件夹，解压文件
                    RandomAccessFileOutStream outStream = new RandomAccessFileOutStream(new RandomAccessFile(file, "rw"));
                    simple.extractSlow(outStream);
                    itemFilePath = file.getPath();  // 记录解压后的文件路径
                    Log.d("--------", "path:  " + itemFilePath);
                } else {
                    boolean mkdirs = file.mkdirs();  // 创建文件夹
                }
            }

            inStream.close();
            iInArchive.close();

            // 截取资源路径
            int res = itemFilePath.indexOf("res");
            String substring = itemFilePath.substring(0, res + 3);  // 截取资源路径
            Log.d("--------", "substring:  " + substring);

            callback.onUnzipCall(true, substring);  // 调用回调函数
        }
    }

    // 下载压缩文件操作
    public static void donwnZip(Context context, String url, DownloadCallback callback) {
        // 使用Glide库来下载文件
        Glide.with(context)
                .asFile() // 指定下载的资源类型为File
                .load(url) // 设置下载的URL
                .listener(new RequestListener<File>() {
                    // 添加监听器来处理下载结果
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<File> target, boolean isFirstResource) {
                        // 下载失败时的回调
                        try {
                            callback.onDownloadCall(false, null);  // 调用回调方法，传递失败状态
                        } catch (FileNotFoundException ex) {
                            throw new RuntimeException(ex);  // 如果捕获到FileNotFoundException异常，抛出运行时异常
                        } catch (IOException ex) {
                            throw new RuntimeException(ex);  // 如果捕获到IOException异常，抛出运行时异常
                        }
                        return false; // 表示处理了这个事件
                    }

                    @Override
                    public boolean onResourceReady(@NonNull File resource, @NonNull Object model, Target<File> target, @NonNull DataSource dataSource, boolean isFirstResource) {
                        // 下载成功时的回调
                        try {
                            // 使用外部存储目录或内部存储目录
                            File externalDir = context.getExternalFilesDir(null);
                            if (externalDir == null) {
                                externalDir = context.getFilesDir();  // 如果外部存储不可用，则回退到内部存储
                            }

                            // 将下载文件保存到外部存储的特定文件夹
                            File downloadDir = new File(externalDir, "DownloadedFiles");
                            if (!downloadDir.exists()) {
                                downloadDir.mkdirs();  // 创建目录
                            }

                            File destinationFile = new File(downloadDir, resource.getName());
                            copyFile(resource, destinationFile);  // 使用FileUtils来复制文件

                            callback.onDownloadCall(true, destinationFile);  // 调用回调方法，传递成功状态和保存后的文件路径
                            Log.d("--------", "resource:  " + destinationFile);
                        } catch (FileNotFoundException e) {
                            throw new RuntimeException(e);  // 如果捕获到FileNotFoundException异常，抛出运行时异常
                        } catch (IOException e) {
                            throw new RuntimeException(e);  // 如果捕获到IOException异常，抛出运行时异常
                        }
                        return false; // 表示处理了这个事件
                    }
                }).preload();  // 预加载文件
    }

    public static void copyFile(File sourceFile, File destinationFile) throws IOException {
        try (InputStream in = new FileInputStream(sourceFile);
             OutputStream out = new FileOutputStream(destinationFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
    }

    // 将文件内容转换为字符串
    public static String fileToString(File file) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(file);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String lin = "";
        // 逐行读取文件内容
        while ((lin = bufferedReader.readLine()) != null) {
            stringBuilder.append(lin);
        }
        bufferedReader.close();
        String con = stringBuilder.toString(); // 转换为字符串
        return con;
    }

    // 将SP单位转换为像素单位
    public static float spToPpx(Float values, Context context) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, values, context.getResources().getDisplayMetrics());
    }

    // 运行IO操作的任务
    public static void runIO(Runnable task) {
        getExecutorService().execute(task);
    }

    // 获取线程池的实例，如果不存在则创建一个单线程池
    private static ExecutorService getExecutorService() {
        if (executorService == null) {
            executorService = Executors.newSingleThreadExecutor();
        }
        return executorService;
    }
}
