import { _decorator, Asset, assetManager, BufferAsset, Component, error, Node, resources, TextAsset, Texture2D } from 'cc';
import { ReadStream } from '../Tool/ReadStream';
import * as pako from 'pako';
import { Img, ImgInfo, NpkInfo } from '../GlobalInterface/GlobalInterface';


const { ccclass, property } = _decorator;


type NewType = Img;

@ccclass('ImagePack')
export class ImagePack extends Component {

    //全局单例类
    private static instance: ImagePack;

    private constructor() {
        super();
    }

    public static getInstance(): ImagePack {
        if (!ImagePack.instance) {
            ImagePack.instance = new ImagePack();
        }
        return ImagePack.instance;
    }



    Key: Array<number> = [112, 117, 99, 104, 105, 107, 111, 110, 64, 110, 101, 111, 112, 108, 101, 32, 100, 117, 110, 103, 101, 111, 110, 32, 97, 110, 100, 32, 102, 105, 103, 104, 116, 101, 114, 32, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 0];


    //NPK加载完成后的回调函数
    LoadCallBack = undefined;
    //NPK文件数量
    private NpkCount = 0;
    //已加载NPK文件数量
    private LoadNpkCount = 0;
    //Img的map Key:img路径  Value:Img结构体
    private Map_Img: Map<string, NewType> = new Map<string, Img>();
    //NPK的本地路径 对应的 NPK名字
    private Npk_URL_Table: Map<string, string> = new Map<string, string>();



    start() {

    }

    update(deltaTime: number) {

    }


    initSuccess(): void {
        if (this.LoadCallBack) this.LoadCallBack();
    }

    BundleObject;
    init(Func: Function): void {
        //储存回调
        this.LoadCallBack = Func;

        assetManager.loadBundle('ImagePacks', (err, bundle) => {
            this.BundleObject = bundle;
            this.LoadNpk();
        });
    }


    LoadNpk(): void {
        this.BundleObject.loadDir("", BufferAsset, (err, contents: Array<BufferAsset>) => {
            //记录NPK文件数量
            this.NpkCount = contents.length;
            console.log(this.NpkCount);

            contents.forEach(content => {
                const Buf = new Uint8Array(content.buffer());
                const Ro = new ReadStream(Buf);
                //文件头
                const Header = Ro.GetString();
                if (Header == "NeoplePack_Bill") {
                    //读取img数量
                    const ImageCount = Ro.GetInt();
                    let ImgList: NpkInfo[] = new Array<NpkInfo>(ImageCount);
                    for (let i = 0; i < ImageCount; i++) {
                        ImgList[i] = {
                            Offset: Ro.GetInt(),
                            Length: Ro.GetInt(),
                            Path: Ro.ReadInfo(this.Key),
                        }
                    }
                    for (let i = 0; i < ImageCount; i++) {
                        let Buf: Img = {
                            ImgOffset: ImgList[i].Offset,
                            ImgSize: ImgList[i].Length,
                            Img_Index: i,
                            BelongsFile: content.nativeUrl,
                            ImgName: ImgList[i].Path,
                            Png_List: null,
                            Png_Count: 0
                        }
                        this.Map_Img.set(ImgList[i].Path, Buf);
                    }
                }

                //完成一个加载
                this.LoadNpkCount = this.LoadNpkCount + 1;
                //加载完成
                if (this.LoadNpkCount == this.NpkCount) {
                    this.initSuccess();
                }
                //把本地路径和NPK名称挂钩一下
                this.Npk_URL_Table.set(content.nativeUrl, content.name);
                //载入完成以后需要释放
                assetManager.releaseAsset(content);
            });
        });
    }

    LoadImgToMem(ImgObj: Img, func: Function) {

        //获取路径 如果不存在直接返回
        const Path = this.Npk_URL_Table.get(ImgObj.BelongsFile);
        if (!Path) return;
        this.BundleObject.load(Path, BufferAsset, (err, content) => {
            const Buf = new Uint8Array(content.buffer());
            const Ro = new ReadStream(Buf);

            Ro.Seekg(ImgObj.ImgOffset);
            //Img头
            const Header = Ro.GetString();
            //开始读图片
            if (Header == "Neople Img File") {
                //索引表大小
                const TableLength = Ro.GetLongInt();

                //img 版本 4字节
                const ver = Ro.GetInt();
                //img 帧数
                const IndexCount = Ro.GetInt();

                ImgObj.Png_Count = IndexCount;

                let PngArr: ImgInfo[] = [];
                for (let index = 0; index < IndexCount; index++) {

                    let ImgBuf: ImgInfo = {};

                    //图片格式
                    ImgBuf.Type = Ro.GetInt();
                    if (ImgBuf.Type == 17) {
                        //引用贴图
                        const IndexBuf = Ro.GetInt();
                        ImgBuf.Offset = PngArr[index - 1].Offset;
                        ImgBuf.Type = 17;
                        ImgBuf.QuoteIndex = IndexBuf;
                        ImgBuf.Size = PngArr[index - 1].Size;
                        PngArr.push(ImgBuf);
                        continue;
                    }
                    //压缩类型
                    ImgBuf.CmpType = Ro.GetInt();
                    //宽度
                    ImgBuf.Width = Ro.GetInt();
                    //高度
                    ImgBuf.Height = Ro.GetInt();
                    //大小
                    ImgBuf.Size = Ro.GetInt();
                    //Xpos
                    ImgBuf.Xpos = Ro.GetInt();
                    //Ypos
                    ImgBuf.Ypos = Ro.GetInt();
                    //帧域X
                    ImgBuf.FrameXpos = Ro.GetInt();
                    //帧域Y
                    ImgBuf.FrameYpos = Ro.GetInt();

                    if (index == 0) {
                        ImgBuf.Offset = 0 + ImgObj.ImgOffset + Number(TableLength) + 32;
                    } else {
                        ImgBuf.Offset = PngArr[index - 1].Offset + PngArr[index - 1].Size;
                    }
                    PngArr.push(ImgBuf);
                }

                for (let index = 0; index < IndexCount; index++) {
                    let PngObj = PngArr[index];
                    //引用贴图
                    if (PngObj.Type == 17) {
                        const QuoteIndexBuf = PngObj.QuoteIndex;
                        PngArr[index] = PngArr[QuoteIndexBuf];
                    }
                }

                for (let index = 0; index < IndexCount; index++) {
                    let PngObj = PngArr[index];


                    Ro.Seekg(PngObj.Offset);
                    //PNG压缩原始数据
                    let DataBuf = Ro.GetBufferByLength(PngObj.Size);

                    //图片数据应有大小
                    let PngBufSize = PngObj.Width * PngObj.Height * 4;
                    // 使用pako 解压 zlib的inflate函数解压缩数据
                    let Bsf;
                    try {
                        Bsf = pako.inflate(DataBuf);
                    }
                    catch (error) {
                        Bsf = DataBuf;
                    }

                    if (PngObj.Type != 16) {
                        let PngByteSize = Bsf.length * 2;
                        PngObj.PNGdata = new Uint8Array(PngByteSize);
                        for (let e = 0; e < PngByteSize; e += 4) {
                            let BarBuf = new Uint8Array(2);

                            let Pos = (e / 4) * 2;
                            BarBuf[0] = Bsf[Pos];
                            BarBuf[1] = Bsf[Pos + 1];
                            this.ReadColor(BarBuf, PngObj, e);
                        }
                    }
                    else {
                        PngObj.PNGdata = new Uint8Array(Bsf.length);
                        for (let index = 0; index < Bsf.length; index += 4) {
                            PngObj.PNGdata[index] = Bsf[index + 2];
                            PngObj.PNGdata[index + 1] = Bsf[index + 1];
                            PngObj.PNGdata[index + 2] = Bsf[index];
                            PngObj.PNGdata[index + 3] = Bsf[index + 3];
                        }
                    }
                }
                ImgObj.Png_List = PngArr;
                func(ImgObj);
            }

            //载入完成以后需要释放
            assetManager.releaseAsset(content);
        });
    }

    ReadColor(Bar: Uint8Array, PngObj: ImgInfo, Offset: number) {
        let a: number = 0;
        let r: number = 0;
        let g: number = 0;
        let b: number = 0;
        switch (PngObj.Type) {
            case 0x0e:
                a = Bar[1] >> 7;
                r = (Bar[1] >> 2) & 0x1f;
                g = (Bar[0] >> 5) | ((Bar[1] & 3) << 3);
                b = Bar[0] & 0x1f;
                a = a * 0xff;
                r = (r << 3) | (r >> 2);
                g = (g << 3) | (g >> 2);
                b = (b << 3) | (b >> 2);
                break;
            case 0x0f:
                a = Bar[1] & 0xf0;
                r = (Bar[1] & 0xf) << 4;
                g = Bar[0] & 0xf0;
                b = (Bar[0] & 0xf) << 4;
                break;
            default:
                console.log(PngObj.Type);
                break;
        }
        PngObj.PNGdata[Offset + 0] = r;
        PngObj.PNGdata[Offset + 1] = g;
        PngObj.PNGdata[Offset + 2] = b;
        PngObj.PNGdata[Offset + 3] = a;
    }


    //读取Img数据
    ReadNpkTable(imgname: string, func: Function): boolean {
        let ImgObj: Img = this.Map_Img.get(imgname);
        if (ImgObj) {
            //没有图片数据 需要加载
            if (ImgObj.Png_List == null) {
                //加载Img进内存
                this.LoadImgToMem(ImgObj, func);
                return true;
            }
            else {
                func(ImgObj);
                return true;
            }
        }
        return false;
    }

    ReleaseNpkTable(p: Img): void {
        // implementation
    }
}


