
import { ResConst } from "../ConstDefine/ResConst"
import AppFacade from "../AppFacade"
import AssetMgr from "../Manager/AssetMgr"
import View from "../BaseView/View"
import GameUtil from "./GameUtil"


export default class UIUtil {

    public static optimizeViewNodes(view:View,nodes:string[],parent:cc.Node){
        if(!nodes||nodes.length<=0) return

        for (let i = 0; i < nodes.length; ++i) {
            let param = view[nodes[i]]
            let node = null
            if (param instanceof cc.Node) {
                node = param
            } else if (param instanceof cc.Component) {
                node = param.node
            }
            UIUtil.changeParentLast(node, view.node, parent)
        }
    }

    public static optimizeViewLabels(views:View[],propertys:string[],modes:cc.Label.CacheMode[],parent:cc.Node){
        for(let i=0;i<propertys.length;++i){
            views.forEach((view)=>{
                let label:cc.Label|cc.RichText=view[propertys[i]]
                if(label){
                    this.changeParentLast(label.node,view.node,parent)
                    label.cacheMode=modes[i]||cc.Label.CacheMode.NONE
                }
            })
        }
    }

    /**
     * 1.将组件中的label移动到底部，进而优化合批
     * 2.模式
     *      1.如果内容不长改变，修改成bit
     *      2.只有数字的常变内容，例如钱数额 修改成char
     * 2.【注意】移动后active等按钮状态影响不了label要
     */
    public static optimizeViewsLabel(views:View[],labelPropertyName:string,parent:cc.Node,mode:cc.Label.CacheMode){
        if(!views||views.length<=0) return
        for(let view of views){
            let label:cc.Label|cc.RichText=view[labelPropertyName]
            label.cacheMode=mode
            let pos=label.node.parent.convertToWorldSpaceAR(label.node.position)
            label.node.parent=parent
            label.node.position=parent.convertToNodeSpaceAR(pos)
            label.node.setSiblingIndex(parent.childrenCount)
        }
    }

    public static optimizeToggleLabel(toggles:cc.Toggle[],parent:cc.Node,mode:cc.Label.CacheMode){
        let labels:Array<cc.Label>=new Array()
        for(let t of toggles){
            labels.push(t.getComponentInChildren(cc.Label))
        }
        labels.forEach((label,i)=>{
            label.cacheMode=mode
            let pos=label.node.parent.convertToWorldSpaceAR(label.node.position)
            label.node.parent=parent
            label.node.position=parent.convertToNodeSpaceAR(pos)
            label.node.setSiblingIndex(parent.childrenCount)
        })
    }

    //设置按钮为沉默状态
    public static setSlience(node:cc.Node,isSlience:boolean)
    public static setSlience(btn: cc.Button, isSlience: boolean) 
    public static setSlience(val:any,isSlience: boolean) {
        if (!val) return
        if(val instanceof cc.Button){
            val.node.opacity = isSlience && 128 || 255
            val.interactable = !isSlience
        }else if(val instanceof cc.Node){
            val.opacity = isSlience && 128 || 255
        }
    }

    public static setGray(node: cc.Node, isGray: boolean) {
        if (node) {
            let sprites = node.getComponentsInChildren(cc.RenderComponent)
            let mat = isGray && cc.Material.getBuiltinMaterial("2d-gray-sprite") || cc.Material.getBuiltinMaterial("2d-sprite")
            for (let s of sprites) {
                s.setMaterial(0, mat)
            }
        }
    }

    /**
    * @param 自适应界面应该有的工具
    */
    public static autoFitCanvas(root: cc.Node,bangTopOffset:number=0,isOnce:boolean=false): cc.Widget {
        let res = GameUtil.addComp<cc.Widget>(root, cc.Widget)
        root.setContentSize(cc.view.getDesignResolutionSize())
        res.isAlignBottom = true
        res.isAlignTop = true
        res.isAlignLeft = true
        res.isAlignRight = true
        res.top += bangTopOffset
        res.updateAlignment()
        return res
    }

    public static autoFitLeft(root:cc.Node,isOnce:boolean=false):cc.Widget{
        let res = GameUtil.addComp<cc.Widget>(root, cc.Widget)
        root.setContentSize(cc.view.getDesignResolutionSize())
        res.isAlignLeft = true
        isOnce&&(res.alignMode=cc.Widget.AlignMode.ONCE)
        res.updateAlignment()
        return res
    }

    public static autoFitRight(root:cc.Node,isOnce:boolean=false):cc.Widget{
        let res = GameUtil.addComp<cc.Widget>(root, cc.Widget)
        root.setContentSize(cc.view.getDesignResolutionSize())
        res.isAlignRight = true
        isOnce&&(res.alignMode=cc.Widget.AlignMode.ONCE)
        res.updateAlignment()
        return res
    }

    public static autoFitTop(root:cc.Node,isOnce:boolean=false):cc.Widget{
        let res = GameUtil.addComp<cc.Widget>(root, cc.Widget)
        root.setContentSize(cc.view.getDesignResolutionSize())
        res.isAlignTop = true
        isOnce&&(res.alignMode=cc.Widget.AlignMode.ONCE)
        res.updateAlignment()
        return res
    }

    public static autoFitBottom(root:cc.Node,isOnce:boolean=false):cc.Widget{
        let res = GameUtil.addComp<cc.Widget>(root, cc.Widget)
        root.setContentSize(cc.view.getDesignResolutionSize())
        res.isAlignBottom = true
        isOnce&&(res.alignMode=cc.Widget.AlignMode.ONCE)
        res.updateAlignment()
        return res
    }

    //强制更新Label
    public static forceUpdatLabel(label:cc.Label){
        label&&label["_forceUpdateRenderData"](true)
        return label
    }


    /**
     * @param node 
     * @param newParent
     * @returns oldParent 
     */
    public static changeParent(node:cc.Node,newParent:cc.Node):cc.Node{
        if(!node||!cc.isValid(node)||!newParent||!cc.isValid(newParent)||node==newParent) return
        let oldParent=node.parent
        let pos=oldParent.convertToWorldSpaceAR(node.position)
        node.setParent(newParent)
        node.position=newParent.convertToNodeSpaceAR(pos)
        return oldParent
    }

    public static changeParentLast(node:cc.Node,preParent:cc.Node,parent:cc.Node){
        //还是不应该修改active
        // node.active=node.active&&preParent.activeInHierarchy
        let pos=node.parent.convertToWorldSpaceAR(node.position)
        node.parent=parent
        node.position=parent.convertToNodeSpaceAR(pos)
        node.setSiblingIndex(parent.childrenCount)
    }

    //从图集中提取精灵
    private static _altasWeek:WeakMap<object,cc.SpriteAtlas>=new WeakMap()
    public static async getSpriteAtlas(key:{abName:string,resName:string}):Promise<cc.SpriteFrame>{
        let altas=this._altasWeek.get(key)
        if(!altas||!cc.isValid(altas)){
            altas=await AppFacade.getMgr(AssetMgr).loadAssetAsync<cc.SpriteAtlas>(ResConst.emptyABName,key.abName,cc.SpriteAtlas)
            this._altasWeek.set(key,altas)
        }
        let sprite=altas?.getSpriteFrame(key.resName)
        key=null
        return sprite
    }
    
    //提取单图精灵
    public static async getSprite(key:{abName:string,resName:string}):Promise<cc.SpriteFrame>{
        let sprite:cc.SpriteFrame=await AppFacade.getMgr(AssetMgr).loadAssetAsync<cc.SpriteFrame>(key.abName,key.resName,cc.SpriteFrame)
        return sprite
    }

    //提取网络图片
    public static async getSpriteByUrl(key:{url:string}):Promise<cc.SpriteFrame>{
        return new Promise((resolve, reject) => {
            cc.loader.load(key, (err, img) => {
                if (err) {
                    cc.error("loadBundleByUrl error", key.url, err)
                    reject(err)
                }
                else {
                    const spriteFrame = new cc.SpriteFrame(img)
                    resolve(spriteFrame);
                }
            })
        });
    } 
}