
/**
 * 由于RenderEntity未暴露，所以修改就只有另辟蹊径
 */

import { Graphics } from "cc";
import { UIRenderer } from "cc";
import { TiledLayer } from "cc";
import { UIMeshRenderer } from "cc";
import { __private,dragonBones,sp } from "cc";
import { JSB } from "cc/env";
import { DEFAULT_SORTING_PRIORITY } from "../sorting-define";

export enum RenderEntityFloatSharedBufferView {
    localOpacity,
    sortingPriority,
    count,
}

export enum RenderEntityUInt8SharedBufferView {
    colorR,
    colorG,
    colorB,
    colorA,
    maskMode,
    count,
}

export enum RenderEntityBoolSharedBufferView {
    colorDirty,
    enabled,
    useLocal,
    count,
}

/**
 * RenderEntity类
 */
let RenderEntityClass:typeof __private._cocos_2d_renderer_render_entity__RenderEntity = null;

/**
 * 更新RenderEntity实体
 */
export function UpdateRenderEntity(renderEntity:__private._cocos_2d_renderer_render_entity__RenderEntity){
    if(renderEntity && !RenderEntityClass){
        RenderEntityClass = renderEntity.constructor as typeof __private._cocos_2d_renderer_render_entity__RenderEntity;

        // @ts-ignore
        RenderEntityClass.prototype.initSharedBuffer = function(){
            this._sortingPriority = DEFAULT_SORTING_PRIORITY;
            if (JSB) {
                //this._sharedBuffer = new Float32Array(RenderEntitySharedBufferView.count);
                const buffer = this._nativeObj.getEntitySharedBufferForJS();
                let offset = 0;
                this._floatSharedBuffer = new Float32Array(buffer, offset, RenderEntityFloatSharedBufferView.count);
                offset += RenderEntityFloatSharedBufferView.count * 4;
                this._uint8SharedBuffer = new Uint8Array(buffer, offset, RenderEntityUInt8SharedBufferView.count);
                offset += RenderEntityUInt8SharedBufferView.count * 1;
                this._boolSharedBuffer = new Uint8Array(buffer, offset, RenderEntityBoolSharedBufferView.count);
            }
        };

        if(!('sortingPriority' in RenderEntityClass.prototype)){
            Object.defineProperty(RenderEntityClass.prototype, 'sortingPriority', {
                get: function() { 
                    return this._sortingPriority; 
                },
                set: function(value) { 
                    this._sortingPriority = value;
                    // console.log(`JSB sortingPriority ${value}`);
                    if (JSB) {
                        this._floatSharedBuffer[RenderEntityFloatSharedBufferView.sortingPriority] = value;
                    }
                },
                enumerable: true
            });
        }
        
        // @ts-ignore
        renderEntity.initSharedBuffer();

        console.log('Update RenderEntity Class');
    }
}

// @ts-ignore
const Graphics_createRenderEntity = Graphics.prototype.createRenderEntity;
// @ts-ignore
Graphics.prototype.createRenderEntity = function(){
    let entity = Graphics_createRenderEntity.call(this);
    UpdateRenderEntity(entity);
    return entity;
}

const UIMeshRenderer_onLoad = UIMeshRenderer.prototype.onLoad;
UIMeshRenderer.prototype.onLoad = function(){
    UpdateRenderEntity(this._renderEntity);
    return UIMeshRenderer_onLoad.call(this);
}

// @ts-ignore
const UIRenderer_createRenderEntity = UIRenderer.prototype.createRenderEntity;
// @ts-ignore
UIRenderer.prototype.createRenderEntity = function(){
    let entity = UIRenderer_createRenderEntity.call(this);
    UpdateRenderEntity(entity);
    return entity;
}

if(dragonBones){
    // @ts-ignore
    const ArmatureDisplay_createRenderEntity = dragonBones.ArmatureDisplay.prototype.createRenderEntity;
    // @ts-ignore
    dragonBones.ArmatureDisplay.prototype.createRenderEntity = function(){
        let entity = ArmatureDisplay_createRenderEntity.call(this);
        UpdateRenderEntity(entity);
        return entity;
    }
}

if(sp){
    // @ts-ignore
    const Skeleton_createRenderEntity = sp.Skeleton.prototype.createRenderEntity;
    // @ts-ignore
    sp.Skeleton.prototype.createRenderEntity = function(){
        let entity = Skeleton_createRenderEntity.call(this);
        UpdateRenderEntity(entity);
        return entity;
    }
}

if(TiledLayer){
    // @ts-ignore
    const TiledLayer_createRenderEntity = TiledLayer.prototype.createRenderEntity;
    // @ts-ignore
    TiledLayer.prototype.createRenderEntity = function(){
        let entity = TiledLayer_createRenderEntity.call(this);
        UpdateRenderEntity(entity);
        return entity;
    }
}
