import * as fflate from 'fflate';

export class SkinManager {
    constructor() {
        /**
         * @type {Map<string, SkinResource>}
         */
        this.resources = new Map();
    }

    /**
     * @description 载入加密 zip 字节
     * @param {ArrayBuffer} binary 
     */
    load(binary) {
        const buffer = new Uint8Array(binary);
        const resources = fflate.unzipSync(buffer);
        const decoder = new TextDecoder('utf-8');
        for (const [path, buffer] of Object.entries(resources)) {
            if (path.endsWith('.svg')) {
                const filename = path.split('/').at(-1);
                const name = filename.slice(0, -4);
                const text = decoder.decode(buffer);
                const meta = new SkinMeta(text, path);

                this.resources.set(name, {
                    path,
                    filename,
                    text,
                    name,
                    meta
                });
            }
        }
    }

    /**
     * @description 查询 skin
     * @param {string} name 
     * @returns {SkinResource | undefined}
     */
    querySkin(name) {
        const resource = this.resources.get(name);
        return resource;
    }
}


/**
 * @typedef SkinResource
 * @property {string} path 压缩包中的相对定义路径，比如：src/static/Gate/Combinatorial cells (simple)/$_NOR_.svg
 * @property {string} filename 器件文件名，比如 $_OR_.svg
 * @property {string} name  器件名，比 $_OR_
 * @property {string} text svg 原文本
 * @property {SkinMeta} meta 后续生成的更加格式化的器件
 */


export const levelName2CssName = {
    'Combinatorial cells (combined)': 'combined',
    'Combinatorial cells (simple)': 'simple',
    'Flip-flop cells': 'flip',
    'Binary operators': 'binary',
    'Coarse arithmetics': 'coarse',
    'Finite state machines': 'finite',
    'Memories': 'memories',
    'Multiplexers': 'multiplexers',
    'Registers': 'registers',
    'Unary operators': 'unary'
}

class SkinMeta {
    /**
     * @param {string} svgString 
     * @param {string} path
     */
    constructor(svgString, path) {
        if (path.startsWith('dide')) {
            path = path.slice(5);
        }
        const levelName = path.split('/')[1];
        const cssName = levelName2CssName[levelName];
        
        const color = `var(--${cssName}-color)`;
        const fillColor = `var(--${cssName}-fill-color)`;
        
        // 解析 svg string 获取关键信息
        const parser = new DOMParser();

        // 颜色替换
        // 填充颜色
        svgString = svgString.replace(/#279BB0/g, color);

        // 边缘颜色
        svgString = svgString.replace(/#000000/g, fillColor);

        // 字体颜色
        svgString = svgString.replace(/#010101/g, 'var(--foreground)');
        
        const svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
        const element = svgDoc.documentElement;
        this.width = parseFloat(element.getAttribute('width'));
        this.height = parseFloat(element.getAttribute('height'));
        this.svgDoc = svgDoc;

        /**
         * @type {Map<string, number>}
         */
        this.portToYOffset = new Map();
    }

    /**
     * @description 获取指定 port 在所在 svg 中 Y 轴的相对偏移量
     * @param {string} portName 
     */
    getPortYOffset(portName) {
        if (this.portToYOffset.has(portName)) {
            return this.portToYOffset.get(portName);
        }
        // 没有 hit，尝试获取        
        const pathElement = this.svgDoc.getElementById(portName);
        if (pathElement === null) {
            return 0;
        }
        const transform = pathElement.getAttribute('transform');
        const yOffset = parseFloat(transform.split(' ').at(-1));
        this.portToYOffset.set(portName, yOffset);
        return yOffset;
    }
}