package net.northking.cctp.scriptcase.tools.hapUtil;

import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import net.northking.cctp.scriptcase.tools.hapUtil.module.Ability;
import net.northking.cctp.scriptcase.tools.hapUtil.module.HapModule;
import net.northking.cctp.scriptcase.tools.hapUtil.pack.HapPackInfo;
import net.northking.cctp.scriptcase.tools.hapUtil.resources.RecordItem;
import net.northking.cctp.scriptcase.tools.hapUtil.resources.ResType;
import net.northking.cctp.scriptcase.tools.hapUtil.resources.ResourcesIndex;


import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@Slf4j
public class Hap implements Closeable {
    /**
     * 模块信息文件名
     */
    private static final String MODULE_INFO_FILE_NAME = "module.json";

    /**
     * 打包信息文件名
     */
    private static final String PACK_INFO_FILE_NAME = "pack.info";

    private static final String RESOURCE_INDEX_FILE_NAME = "resources.index";

    private static final Gson gson = new Gson();

    private HapModule hapModule;
    private HapPackInfo hapPackInfo;
    private ResourcesIndex resourcesIndex;

    private final ZipFile zipFile;

    public Hap(File file) throws IOException {
        zipFile = new ZipFile(file);
        ZipEntry entry = zipFile.getEntry(MODULE_INFO_FILE_NAME);
        InputStream inputStream = zipFile.getInputStream(entry);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = null;
        StringBuilder builder = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
        hapModule = gson.fromJson(builder.toString(), HapModule.class);
        inputStream = zipFile.getInputStream(zipFile.getEntry(PACK_INFO_FILE_NAME));
        reader = new BufferedReader(new InputStreamReader(inputStream));
        builder = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
        hapPackInfo = gson.fromJson(builder.toString(), HapPackInfo.class);
        ZipEntry resIndexEntry = zipFile.getEntry(RESOURCE_INDEX_FILE_NAME);
        resourcesIndex = new ResourcesIndex(zipFile.getInputStream(resIndexEntry), resIndexEntry.getSize());
    }


    public HapModule getHapModule() {
        return hapModule;
    }

    public HapPackInfo getHapPackInfo() {
        return hapPackInfo;
    }

    public ResourcesIndex getResourcesIndex() {
        return resourcesIndex;
    }

    public String getVersionName() {
        return hapModule.getApp().getVersionName();
    }

    public long getVersionCode() {
        return hapModule.getApp().getVersionCode();
    }

    public String getAppName() {

        int labelId = hapModule.getApp().getLabelId();

        Ability homeAbility = hapModule.getModule().getDefaultHomeAbility();
        if (homeAbility != null) {
            labelId = homeAbility.getLabelId();
        }
        String name = null;
        RecordItem recordItem = resourcesIndex.getRecordItemById(labelId);
        while (name == null) {
            if (recordItem == null) {
                log.warn("获取Hap应用名称时找不到资源索引");
                return null;
            }
            if (recordItem.getResType() != ResType.STRING) {
                log.warn("获取Hap应用名称时索引资源类型不为字符串，实际为：{}", recordItem.getResType());
                return null;
            }
            if (recordItem.getValue().startsWith("$string:")) {
                try {
                    labelId = Integer.parseInt(recordItem.getValue().split(":")[1]);
                } catch (NumberFormatException e) {
                    log.error("无法从字符串[{}]获取次级资源id", recordItem.getValue());
                    return recordItem.getValue();
                }

                recordItem = resourcesIndex.getRecordItemById(labelId);
            } else {
                name = recordItem.getValue();
            }
        }
        return name;
    }

    /**
     * 获取应用图标
     * <br>
     * 记得使用完毕后关闭流
     *
     * @return 应用图标数据流
     */
    public InputStream getAppIcon() {
        int iconId = hapModule.getApp().getIconId();
        Ability homeAbility = hapModule.getModule().getDefaultHomeAbility();
        if (homeAbility != null) {
            iconId = homeAbility.getStartWindowIconId();//不使用IconId是因为指向的是分层图标json
        }
        RecordItem recordItem = resourcesIndex.getRecordItemById(iconId);
        if (recordItem == null) {
            log.warn("获取Hap应用图标时找不到资源索引");
            return null;
        }
        if (recordItem.getResType() != ResType.MEDIA) {
            log.warn("获取Hap应用图标时索引资源类型不为媒体，实际为：{}", recordItem.getResType());
            return null;
        }
        ZipEntry entry = zipFile.getEntry(recordItem.getValue().replace(hapModule.getModule().getName() + "/", ""));
        if (entry == null) {
            log.error("获取Hap应用图标时，包内未找到图标文件：{}", recordItem.getValue());
            return null;
        }
        InputStream inputStream = null;
        try {
            inputStream = zipFile.getInputStream(entry);
        } catch (IOException e) {
            log.error("获取Hap应用图标时，获取包内图片文件读取流时发生IO错误", e);
        }
        return inputStream;
    }

    @Override
    public void close() {
        try {
            zipFile.close();
        } catch (IOException e) {
            log.error("关闭Hap资源时发生IO错误", e);
        }
    }
}
