import { FindPosition, MaxRectBinPack, Rect } from "./MaxRectsBinPack";
import { RGBA8888Texture } from "./RGBA8888Texture";



export class DynamicAtlas {

    private __texturePage: sp.spine.TextureAtlasPage;

    private __maxRectsBinPack: MaxRectBinPack;

    private __texture: RGBA8888Texture;
    private __temporaryTexture = new cc.RenderTexture();

    private __regions: Map<string, sp.spine.TextureRegion>;

    constructor(width: number, height: number) {
        this.__temporaryTexture = new cc.RenderTexture();
        this.__temporaryTexture.initWithSize(width, height);

        this.__regions = new Map<string, sp.spine.TextureRegion>();
        this.__maxRectsBinPack = new MaxRectBinPack(width, height, false);

        this.__texture = new RGBA8888Texture(width, height);

        this.__texturePage = new sp.spine.TextureAtlasPage();
        this.__texturePage.name = "page";
        this.__texturePage.width = width;
        this.__texturePage.height = height;
        this.__texturePage.minFilter = sp.spine.TextureFilter.Linear;
        this.__texturePage.magFilter = sp.spine.TextureFilter.Linear;
        this.__texturePage.uWrap = sp.spine.TextureWrap.ClampToEdge;
        this.__texturePage.vWrap = sp.spine.TextureWrap.ClampToEdge;

        //纹理
        let tex = new sp["SkeletonTexture"]({ width: width, height: height });
        tex.setRealTexture(this.__texture);
        this.__texturePage.texture = tex;

        this.__texturePage.texture.setFilters(this.__texturePage.minFilter, this.__texturePage.magFilter);
        this.__texturePage.texture.setWraps(this.__texturePage.uWrap, this.__texturePage.vWrap);
    }

    allocation(attachment: sp.spine.RegionAttachment) {
        let result: sp.spine.RegionAttachment = this.copyRegionAttachment(attachment);
        result.name = attachment.name;
        let region: sp.spine.TextureAtlasRegion = result["region"] as sp.spine.TextureAtlasRegion;
        let spTexture: sp.spine.Texture = region["texture"];
        let texture: cc.Texture2D = spTexture["_texture"];

        //将纹理绘制到临时纹理上
        this.__temporaryTexture["drawTextureAt"](texture, 0, 0);
        

        //从临时纹理中获取需要的纹理区块
        this.device.setFrameBuffer(this.__temporaryTexture["_framebuffer"]);
        let byte = this.__temporaryTexture.readPixels(null, region.x, region.y, region.width, region.height);

        //分配空间
        let rect: Rect = this.__maxRectsBinPack.insert(region.width, region.height, FindPosition.ShortSideFit);
        if (rect.isEmpty) {
            throw new Error("图集分配空间失败！");
        }
        //合并到共享图集
        this.__texture.setPixels(byte, region.width, rect.x, rect.y);
        this.__texture.update2Texture();

        let copy: sp.spine.TextureAtlasRegion = new sp.spine.TextureAtlasRegion();
        copy.name = region.name;
        copy.width = copy.originalWidth = region.width;
        copy.height = copy.originalHeight = region.height;
        copy.x = rect.x;
        copy.y = rect.y;
        copy.degrees = 0;
        copy.index = -1;
        copy.texture = this.__texturePage.texture;
        copy.u = rect.x / this.__texturePage.width;
        copy.v = rect.y / this.__texturePage.height;
        copy.u2 = (rect.x + rect.width) / this.__texturePage.width;
        copy.v2 = (rect.y + rect.height) / this.__texturePage.height;
        copy.offsetX = copy.offsetY = 0;
        copy.page = this.__texturePage;
        copy.renderObject = copy;

        this.__regions.set(copy.name, copy);

        result.setRegion(copy);
        return result;
    }

    copyRegionAttachment(data:sp.spine.RegionAttachment): sp.spine.RegionAttachment {
        var copy = new sp.spine.RegionAttachment(data.name);
        copy.region = data.region;
        copy.rendererObject = data.rendererObject;
        copy.path = data.path;
        copy.x = data.x;
        copy.y = data.y;
        copy.scaleX = data.scaleX;
        copy.scaleY = data.scaleY;
        copy.rotation = data.rotation;
        copy.width = data.width;
        copy.height = data.height;
        sp.spine.Utils.arrayCopy(data.uvs, 0, copy.uvs, 0, 8);
        sp.spine.Utils.arrayCopy(data.offset, 0, copy.offset, 0, 8);
        copy.color.setFromColor(data.color);
        return copy;
    }

    private get device(): any {
        return cc.renderer["device"];
    }

    get texture(): cc.Texture2D {
        return this.__texture;
    }
}