
const { ccclass, property } = cc._decorator;
/**
 * 飞item组件
 * - item使用容器存储，可复用，组件的节点被销毁时，销毁所有item
 * - 流程：
 * - 把节点在范围内随机展开，移动到指定位置
 * - 数值优先使用通过事件传递的值，没有则使用装饰器上的默认值
 * @author 薛鸿潇
 */
@ccclass
export default class FlyNode extends cc.Component {

    @property({ displayName: '起始阶段消耗时间' })
    private start_move_time: number = 0.1;
    @property({ displayName: '结束阶段消耗时间' })
    private end_move_time: number = 0.3;
    // @property({ displayName: 'item缩放比率' })
    // private item_scale: number = 0.2;
    @property({ displayName: 'item默认数量' })
    private item_count: number = 10;
    /** 组件数据 */
    private fly_data = {
        /** 节点的父节点 */
        node_p: null,
        /** 节点数量 */
        item_count: this.item_count,
        /** 节点大小 */
        item_scale: [0.3, 1],
        /** 节点纹理 */
        item_sf: null,
        /** 起始位置 */
        start_pos: cc.Vec2.ZERO,
        /** 结束位置 */
        end_pos: cc.Vec2.ZERO,
        /** 完成回调 */
        complete_call: null,
    }
    /** item父节点 */
    private node_fly: cc.Node = null;
    /** item容器 */
    private arr_item: Array<cc.Node> = [];

    onLoad() {
        this.node.on('ui-fly-node', this.getNodeProgress, this);
    }

    /**
     * 加载 小号图标组 
     * @param _fly_data 数据内容
     */
    private getNodeProgress(_fly_data: any) {
        // 数据整理node_p, item_sf: cc.SpriteFrame, item_count: number, start_pos: cc.Vec2 = cc.Vec2.ZERO, item_scale: number = 1
        // this.fly_data = _fly_data;
        if (_fly_data.node_p) this.fly_data.node_p = _fly_data.node_p;
        if (_fly_data.item_count) this.fly_data.item_count = _fly_data.item_count;
        if (_fly_data.item_scale) this.fly_data.item_scale = _fly_data.item_scale;
        if (_fly_data.item_sf) this.fly_data.item_sf = _fly_data.item_sf;
        if (_fly_data.start_pos) this.fly_data.start_pos = _fly_data.start_pos;
        if (_fly_data.end_pos) this.fly_data.end_pos = _fly_data.end_pos;
        if (_fly_data.complete_call) this.fly_data.complete_call = _fly_data.complete_call;
        let node_p = this.fly_data.node_p;
        const item_count = this.fly_data.item_count;
        const item_scale = this.fly_data.item_scale;
        let item_sf = this.fly_data.item_sf;
        let start_pos = this.fly_data.start_pos;
        // 创建节点
        if (!this.node_fly) {
            this.node_fly = new cc.Node('node_fly');
            this.node_fly.parent = node_p;
        }
        for (let i = 0; i < item_count; i++) {
            let node_item = this.arr_item.shift();
            if (!node_item || (node_item && node_item.parent)) {
                // 无item 或者item存在，但有父节点【表示正在运行中】
                node_item = new cc.Node('node_item');
                this.arr_item.push(node_item);
            }
            node_item.stopAllActions();
            node_item.parent = this.node_fly;
            node_item.setPosition(start_pos);
            // // 创建位置
            node_item.angle = this.range(-45, 45, true);
            let new_scale = this.range(item_scale[0], item_scale[1], false);
            node_item.scale = new_scale;
            // 偏移位置计算-新
            let dir = cc.v2(this.range(-1, 1, false), this.range(-1, 1, false));
            dir = dir.normalize();
            let deltaInit = cc.v2(this.range(10, 80, false) * dir.x, this.range(10, 80, false) * dir.y);
            let initPos = start_pos.add(deltaInit);
            // node_item.setPosition(initPos);

            // 纹理
            let spr_item = node_item.getComponent(cc.Sprite) || node_item.addComponent(cc.Sprite);
            spr_item.spriteFrame = item_sf;
            // 执行动画
            this.movePos(node_item, initPos);
        }
    }

    /**
     * 移动到起始位置
     * @param node_item 
     * @param initPos 
     */
    private movePos(node_item, initPos) {
        let new_start_move_time = this.range(0.3, 1, false);
        //this.start_move_time
        let start_pos = cc.tween().to(new_start_move_time, { position: new cc.Vec2(initPos) }, { easing: 'sineOut' });
        let dt1 = cc.tween().delay(this.start_move_time * 1.5);
        // this.end_move_time
        // 结束阶段效果
        let end_pos = cc.tween().to(this.end_move_time, { position: this.fly_data.end_pos }, { easing: 'sineOut' })
        let end_scale = cc.tween().to(this.end_move_time, { scale: 1 });
        let end_angle = cc.tween().to(this.end_move_time, { angle: 0 });
        let parallel1 = cc.tween().parallel(end_pos, end_scale, end_angle);
        let call1 = cc.tween().call(() => {
            this.fly_data.complete_call && this.fly_data.complete_call();
            this.fly_data.complete_call = null;
            this.arr_item.push(node_item);
            node_item.removeFromParent();
        });
        cc.tween(node_item).then(start_pos).then(dt1).then(parallel1).then(call1).start();
    }

    /**
     * 
     * @param min 
     * @param max 
     * @param isInt 
     * @returns 
     */
    private range(min: number, max: number, isInt: boolean = true): number {
        //return min + Math.ceil(Math.random() * 1000) % (max - min);         //不包含最大值
        let del: number = max - min;
        if (del > 0) {
            let val: number = min + Math.random() * 0xffffff % del
            if (isInt) {
                return Math.floor(val);
            }
            return val
        }
        return min;
    }

    onDestroy() {
        const item_count = this.arr_item.length
        for (let i = 0; i < item_count; i++) {
            if (cc.isValid(this.arr_item[0])) {
                this.arr_item[0].destroy();
                this.arr_item.shift();
            }
        }
    }
    // update (dt) {}
}
