import { _decorator, absMax, assetManager, Component, ImageAsset, instantiate, Node, Prefab, resources, SpriteFrame, Texture2D } from 'cc';
import { gameManager } from './gameManager';
import { config } from './config';
import { toast } from './toast';
import { dialog } from './dialog/dialog';
const { ccclass, property } = _decorator;

export class tools  {
    public static showToast(text:string){
        if(gameManager.getTopLayer()==null){
            console.log("gameManager.topLayer -- null!");
            return;
        }
        resources.load(config.PREFAB_PATH.toast, Prefab, (err, prefab) => {
            if(err){
                console.log("addTopView -- err::",err);
                return;
            }

            let newNode:Node = instantiate(prefab);
            newNode.parent = gameManager.getTopLayer();
            newNode.getComponent(toast).showView(text);
        });
    }

    public static showDialog(text:string,call_yes=null,call_not=null){
        if(gameManager.getTopLayer()==null){
            console.log("gameManager.topLayer -- null!");
            return;
        }
        resources.load(config.PREFAB_PATH.dialog, Prefab, (err, prefab) => {
            if(err){
                console.log("addTopView -- err::",err);
                return;
            }

            let newNode:Node = instantiate(prefab);
            newNode.parent = gameManager.getTopLayer();
            newNode.getComponent(dialog).show(text,call_yes,call_not);
        });
    }


    public static showDialogOne(text:string,call_yes=null){
        if(gameManager.getTopLayer()==null){
            console.log("gameManager.topLayer -- null!");
            return;
        }
        resources.load(config.PREFAB_PATH.dialog, Prefab, (err, prefab) => {
            if(err){
                console.log("addTopView -- err::",err);
                return;
            }

            let newNode:Node = instantiate(prefab);
            newNode.parent = gameManager.getTopLayer();
            newNode.getComponent(dialog).showOne(text,call_yes);
        });
    }

    public static loadRemoteImg(url,call_back,id=null){
        assetManager.loadRemote<ImageAsset>(url, (err, imageAsset2)=>{
            if (!err && imageAsset2) {        
                const texture = new Texture2D();
                texture.image = imageAsset2;
                let spFrame2 = new SpriteFrame();     
                spFrame2.texture = texture;
                if(id!=null){
                    call_back(spFrame2,id);
                }else{
                    call_back(spFrame2);
                }
                
            }
        
        });
    }
    public static loadRemoteImgByCategoryid(categoryid:number,level:number,url,call_back,id=null){
        let map = gameManager.cache.get(`${level}_${categoryid}`)
        let isCache = false;
        if(map!=null&&map.size>0){
            if(map.get(url)){
                isCache =true;
                if(id!=null){
                    call_back(map.get(url),id);
                }else{
                    call_back(map.get(url));
                }
            }
        }
        if(!isCache){
            assetManager.loadRemote<ImageAsset>(url, (err, imageAsset2)=>{
                if (!err && imageAsset2) {        
                    const texture = new Texture2D();
                    texture.image = imageAsset2;
                    let spFrame2 = new SpriteFrame();     
                    spFrame2.texture = texture;
                    if(id!=null){
                        call_back(spFrame2,id);
                    }else{
                        call_back(spFrame2);
                    }
                    
                }
            
            });
        }
 
    }

    public static sortDoudizhuCards(cards, ascending = true) {
        const cardsCopy = cards.slice();
        return cardsCopy.sort((a, b) => {
            return ascending
                ? parseInt(a) - parseInt(b)
                : parseInt(b) - parseInt(a);
        });
    }




   // # check if move is a continuous sequence  //是连续序列
    public static is_continuous_seq(move){
        var i = 0;
        while (i < move.length - 1) {
            if (parseInt(move[i+1]) - parseInt( move[i]) !== 1) {
                return false;
            }
            i++;
        }
        return true;
    }
    public static get_move_type(move){
        var moveSize = move.length;
        var moveDict = {};
    
        for (var i = 0; i < moveSize; i++) {
            moveDict[move[i]] = (moveDict[move[i]] || 0) + 1;
        }
    
        if (moveSize === 0) {
            return {'type': config.TYPE_0_PASS};
        }
    
        if (moveSize === 1) {
            return {'type': config.TYPE_1_SINGLE, 'rank': move[0]};
        }
    
        if (moveSize === 2) {
            if (move[0] === move[1]) {
                return {'type': config.TYPE_2_PAIR, 'rank': move[0]};
            } else if (move.toString() === [20, 30].toString()) {  // Kings
                return {'type': config.TYPE_5_KING_BOMB};
            } else {
                return {'type': config.TYPE_15_WRONG};
            }
        }
    
        if (moveSize === 3) {
            if (Object.keys(moveDict).length === 1) {
                return {'type': config.TYPE_3_TRIPLE, 'rank': move[0]};
            } else {
                return {'type': config.TYPE_15_WRONG};
            }
        }
    
        if (moveSize === 4) {
            if (Object.keys(moveDict).length === 1) {
                return {'type': config.TYPE_4_BOMB, 'rank': move[0]};
            } else if (Object.keys(moveDict).length === 2) {
                if (move[0] === move[1] && move[1] === move[2] || move[1] === move[2] && move[2] === move[3]) {
                    return {'type': config.TYPE_6_3_1, 'rank': move[1]};
                } else {
                    return {'type': config.TYPE_15_WRONG};
                }
            } else {
                return {'type': config.TYPE_15_WRONG};
            }
        }
    
        if (tools.is_continuous_seq(move)) {
            return {'type': config.TYPE_8_SERIAL_SINGLE, 'rank': move[0], 'len': move.length};
        }
    
        if (moveSize === 5) {
            if (Object.keys(moveDict).length === 2) {
                return {'type': config.TYPE_7_3_2, 'rank': move[2]};
            } else {
                return {'type': config.TYPE_15_WRONG};
            }
        }
    
        var countDict = {};
    
        for (var key in moveDict) {
            if (countDict[moveDict[key]]) {
                countDict[moveDict[key]] += 1;
            } else {
                countDict[moveDict[key]] = 1;
            }
        }
    
        if (moveSize === 6) {
            if ((Object.keys(moveDict).length === 2 || Object.keys(moveDict).length === 3) && countDict[4] === 1 && (countDict[2] === 1 || countDict[1] === 2)) {
                return {'type': config.TYPE_13_4_2, 'rank': move[2]};
            }
        }
    
        if (moveSize === 8 && (((Object.keys(moveDict).length === 3 || Object.keys(moveDict).length === 2) && (countDict[4] === 1 && countDict[2] === 2)) || countDict[4] === 2)) {
            return {'type': config.TYPE_14_4_22, 'rank': Math.max.apply(null, Object.keys(moveDict).filter(function(key) { return moveDict[key] === 4; }))};
        }
    
        var mdKeys = Object.keys(moveDict).sort();
    
        if (Object.keys(moveDict).length === countDict[2] && tools.is_continuous_seq(mdKeys)) {
            return {'type': config.TYPE_9_SERIAL_PAIR, 'rank': parseInt(mdKeys[0]), 'len': mdKeys.length};
        }
        
        if (Object.keys(moveDict).length === countDict[3] && tools.is_continuous_seq(mdKeys) ) {
            return {'type': config.TYPE_10_SERIAL_TRIPLE, 'rank': parseInt(mdKeys[0]), 'len': mdKeys.length};
        }
    
        if (countDict[3] >= config.MIN_TRIPLES) {
            var serial3 = [];
            var single = [];
            var pair = [];
    
            for (var key in moveDict) {
                if (moveDict[key] === 3) {
                    serial3.push(parseInt(key));
                } else if (moveDict[key] === 1) {
                    single.push(parseInt(key));
                } else if (moveDict[key] === 2) {
                    pair.push(parseInt(key));
                } else {
                    return {'type': config.TYPE_15_WRONG};
                }
            }
    
            serial3.sort((a,b)=>{return a - b});
            let is_continuous_seq = tools.is_continuous_seq(serial3)
            if (is_continuous_seq) {
                if (serial3.length === single.length + pair.length * 2) {
                    return {'type': config.TYPE_11_SERIAL_3_1, 'rank': serial3[0], 'len': serial3.length};
                }
                if (serial3.length === pair.length && Object.keys(moveDict).length === serial3.length * 2) {
                    return {'type': config.TYPE_12_SERIAL_3_2, 'rank': serial3[0], 'len': serial3.length};
                }
            }
    
            if (serial3.length === 4) {
                if (tools.is_continuous_seq(serial3.slice(1))) {
                    return {'type': config.TYPE_11_SERIAL_3_1, 'rank': serial3[1], 'len': serial3.length - 1};
                }
                if (tools.is_continuous_seq(serial3.slice(0, -1))) {
                    return {'type': config.TYPE_11_SERIAL_3_1, 'rank': serial3[0], 'len': serial3.length - 1};
                }
            }
        }
    
        return {'type': config.TYPE_15_WRONG};
    }

//# return the type of the move
    // public static  get_move_type(move){
    //     var move_size = move.length;
    //     var move_dict = {};
    
    //     for (var i = 0; i < move.length; i++) {
    //         var item = move[i];
    //         move_dict[item] = (move_dict[item] || 0) + 1;
    //     }
    
    //     if (move_size === 0) {
    //         return { 'type': config.TYPE_0_PASS };
    //     }
    
    //     if (move_size === 1) {
    //         return { 'type':  config.TYPE_1_SINGLE, 'rank': move[0] };
    //     }
    
    //     if (move_size === 2) {
    //         if (move[0] === move[1]) {
    //             return { 'type':  config.TYPE_2_PAIR, 'rank': move[0] };
    //         } else if (move.toString() === [20, 30].toString()) {  // Kings
    //             return { 'type':  config.TYPE_5_KING_BOMB };
    //         } else {
    //             return { 'type':  config.TYPE_15_WRONG };
    //         }
    //     }
    
    //     if (move_size === 3) {
    //         if (Object.keys(move_dict).length === 1) {
    //             return { 'type':  config.TYPE_3_TRIPLE, 'rank': move[0] };
    //         } else {
    //             return { 'type':  config.TYPE_15_WRONG };
    //         }
    //     }
    
    //     if (move_size === 4) {
    //         if (Object.keys(move_dict).length === 1) {
    //             return { 'type':  config.TYPE_4_BOMB, 'rank': move[0] };
    //         } else if (Object.keys(move_dict).length === 2) {
    //             if (move[0] === move[1] && move[1] === move[2] || move[1] === move[2] && move[2] === move[3]) {
    //                 return { 'type':  config.TYPE_6_3_1, 'rank': move[1] };
    //             } else {
    //                 return { 'type':  config.TYPE_15_WRONG };
    //             }
    //         } else {
    //             return { 'type': config.TYPE_15_WRONG };
    //         }
    //     }
    
    //     if (tools.is_continuous_seq(move)) {
    //         return { 'type':  config.TYPE_8_SERIAL_SINGLE, 'rank': move[0], 'len': move.length };
    //     }
    
    //     if (move_size === 5) {
    //         if (Object.keys(move_dict).length === 2) {
    //             return { 'type':  config.TYPE_7_3_2, 'rank': move[2] };
    //         } else {
    //             return { 'type':  config.TYPE_15_WRONG };
    //         }
    //     }
    
    //     var count_dict = {};
    //     for (var c in move_dict) {
    //         var n = move_dict[c];
    //         count_dict[n] = (count_dict[n] || 0) + 1;
    //     }
    
    //     if (move_size === 6) {
    //         if ((Object.keys(move_dict).length === 2 || Object.keys(move_dict).length === 3) && count_dict[4] === 1 && (count_dict[2] === 1 || count_dict[1] === 2)) {
    //             return { 'type':  config.TYPE_13_4_2, 'rank': move[2] };
    //         }
    //     }
        
    //     if (move_size === 8 && ((Object.keys(move_dict).length === 3 || Object.keys(move_dict).length === 2) && (count_dict[4] === 1 && count_dict[2] === 2) || count_dict[4] === 2)) {
    //         return { 'type':  config.TYPE_14_4_22, 'rank': Math.max.apply(null, Object.keys(move_dict).filter(function (c) { return move_dict[c] === 4; })) };
    //     }
    //     var mdkeys = Object.keys(move_dict).sort();
    //     if (Object.keys(move_dict).length === count_dict[2] && tools.is_continuous_seq(mdkeys)) {
    //         return { 'type':  config.TYPE_9_SERIAL_PAIR, 'rank': mdkeys[0], 'len': mdkeys.length };
    //     }
    //     if (Object.keys(move_dict).length === count_dict[3] && tools.is_continuous_seq(mdkeys)) {
    //         return { 'type':  config.TYPE_10_SERIAL_TRIPLE, 'rank': mdkeys[0], 'len': mdkeys.length };
    //     }
    //     if (count_dict[3] >=  config.MIN_TRIPLES) {
    //         var serial_3 = [];
    //         var single = [];
    //         var pair = [];
    
    //         for (var k in move_dict) {
    //             var v = move_dict[k];
    //             if (v === 3) {
    //                 serial_3.push(k);
    //             } else if (v === 1) {
    //                 single.push(k);
    //             } else if (v === 2) {
    //                 pair.push(k);
    //             } else {
    //                 return { 'type':  config.TYPE_15_WRONG };
    //             }
    //         }
    
    //         serial_3.sort();
    
    //         if (tools.is_continuous_seq(serial_3)) {
    //             if (serial_3.length === single.length + pair.length * 2) {
    //                 return { 'type':  config.TYPE_11_SERIAL_3_1, 'rank': serial_3[0], 'len': serial_3.length };
    //             }
    //             if (serial_3.length === pair.length && Object.keys(move_dict).length === serial_3.length * 2) {
    //                 return { 'type':  config.TYPE_12_SERIAL_3_2, 'rank': serial_3[0], 'len': serial_3.length };
    //             }
    //         }
    
    //         if (serial_3.length === 4) {
    //             if (tools.is_continuous_seq(serial_3.slice(1))) {
    //                 return { 'type':  config.TYPE_11_SERIAL_3_1, 'rank': serial_3[1], 'len': serial_3.length - 1 };
    //             }
    //             if (tools.is_continuous_seq(serial_3.slice(0, -1))) {
    //                 return { 'type':  config.TYPE_11_SERIAL_3_1, 'rank': serial_3[0], 'len': serial_3.length - 1 };
    //             }
    //         }
    //     }
    //     return { 'type': config. TYPE_15_WRONG };
    // }


    public static common_handle(moves, rival_move){
        var new_moves = [];
        for (let index = 0; index < moves.length; index++) {
            const move = moves[index];
            if (parseInt(move[0]) > parseInt(rival_move[0])) {
                new_moves.push(move);
            }
        }
        
        return [new_moves];
    }

    

    public static filter_type_1_single(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
    


    public static filter_type_2_pair(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
    


    public static filter_type_3_triple(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
    


    public static filter_type_4_bomb(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
    



    //# No need to filter for type_5_king_bomb

    public static filter_type_6_3_1(moves, rival_move){
        rival_move.sort();
        var rival_rank = rival_move[1];
        var new_moves = [];
        
        moves.forEach(function(move) {
        move.sort();
        var my_rank = move[1];
        if (parseInt(my_rank) > parseInt(rival_rank) ) {
        new_moves.push(move);
        }
        });
        return new_moves;
    }



    public static filter_type_7_3_2(moves, rival_move){
        rival_move.sort()
        let rival_rank = rival_move[2]
        let new_moves = []
        for (let index = 0; index < moves.length; index++) {
            const move = moves[index];
            move.sort()
            let my_rank = move[2]
            if(parseInt(my_rank) > parseInt(rival_rank))
                new_moves.push(move)
        }
        return new_moves
    }



    public static filter_type_8_serial_single(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
   


    public static filter_type_9_serial_pair(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
    


    public static filter_type_10_serial_triple(moves, rival_move){
        return tools.common_handle(moves, rival_move)
    }
    


    public static filter_type_11_serial_3_1(moves, rival_move){
        let rival = {};
        for (let i = 0; i < rival_move.length; i++) {
          if (!rival[rival_move[i]]) {
            rival[rival_move[i]] = 1;
          } else {
            rival[rival_move[i]]++;
          }
        }
        let rival_rank = Object.keys(rival).reduce((a, b) => rival[a] > rival[b] ? a : b);
        let new_moves = [];
        for (let i = 0; i < moves.length; i++) {
          let mymove = {};
          for (let j = 0; j < moves[i].length; j++) {
            if (!mymove[moves[i][j]]) {
              mymove[moves[i][j]] = 1;
            } else {
              mymove[moves[i][j]]++;
            }
          }
          let my_rank = Object.keys(mymove).reduce((a, b) => mymove[a] > mymove[b] ? a : b);
          if (my_rank > rival_rank) {
            new_moves.push(moves[i]);
          }
        }
        return new_moves;
    }
 


    public static filter_type_12_serial_3_2(moves, rival_move){
        let rival = {};
        for (let i = 0; i < rival_move.length; i++) {
          if (!rival[rival_move[i]]) {
            rival[rival_move[i]] = 1;
          } else {
            rival[rival_move[i]]++;
          }
        }
        let rival_rank = Object.keys(rival).reduce((a, b) => rival[a] > rival[b] ? a : b);
        let new_moves = [];
        for (let i = 0; i < moves.length; i++) {
          let mymove = {};
          for (let j = 0; j < moves[i].length; j++) {
            if (!mymove[moves[i][j]]) {
              mymove[moves[i][j]] = 1;
            } else {
              mymove[moves[i][j]]++;
            }
          }
          let my_rank = Object.keys(mymove).reduce((a, b) => mymove[a] > mymove[b] ? a : b);
          if (my_rank > rival_rank) {
            new_moves.push(moves[i]);
          }
        }
        return new_moves;
    }



    public static filter_type_13_4_2(moves, rival_move){
        rival_move.sort()
        let rival_rank = rival_move[2]
        let new_moves = []
        for (let index = 0; index < moves.length; index++) {
            const move = moves[index];
            move.sort()
            let my_rank = move[2]
            if(parseInt(my_rank) > parseInt(rival_rank))
                new_moves.push(move)
            
        }
        return new_moves
    }
   


    public static filter_type_14_4_22(moves, rival_move){
        var rival = {};
        for (var i = 0; i < rival_move.length; i++) {
            rival[rival_move[i]] = rival[rival_move[i]] ? rival[rival_move[i]] + 1 : 1;
        }
        var rivalRank = 0;
        var myRank = 0;
        for (var key in rival) {
            if (rival.hasOwnProperty(key) && rival[key] === 4) {
                rivalRank = parseInt(key);
                break;
            }
        }
    
        var newMoves = [];
        for (var j = 0; j < moves.length; j++) {
            var myMove = {};
            for (var k = 0; k < moves[j].length; k++) {
                myMove[moves[j][k]] = myMove[moves[j][k]] ? myMove[moves[j][k]] + 1 : 1;
            }
            for (var key in myMove) {
                if (myMove.hasOwnProperty(key) && myMove[key] === 4) {
                    myRank = parseInt(key);
                    break;
                }
            }
            if (myRank > rivalRank) {
                newMoves.push(moves[j]);
            }
        }
    
        return newMoves;
    }
    

    public static getCardMin(list:any[]):string{
        list.sort((a,b)=>{
            return parseInt(a[0] )- parseInt(b[0])
        })
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            if(element!=null&&element!=undefined&&element.length>0){
                return element[0]
            }
        }
        return list[0]
       
    }


    public static isArraysEqual(arr1, arr2) {
        if (arr1.length !== arr2.length) {
        return false;
        }
        for (var i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
        return false;
        }
        }
        return true;
    }

    public static isEqualArray(arr1, arr2) {
        if (arr1.length !== arr2.length) {
          return false;
        }
        
        var isEqual = true;
        
        arr1.forEach(function(element) {
          if (!arr2.includes(element)) {
            isEqual = false;
          }
        });
        
        return isEqual;
    }
    public static delete_element(list:[],element)
    {
        let new_list = []
        let is_delete = false;
        for (let index = 0; index < list.length; index++) {
            const item = list[index];
            if(element===item&&!is_delete){
                is_delete = true;
            }else{
                new_list.push(item)
            }
        }
        return new_list;
    }
    public static delete_card(original_cards,sub_cards){
        let index = 0;
        let list = original_cards
        while(index<sub_cards.length){
            list = tools.delete_element(list,sub_cards[index])
            index++;
        }
        return list;
    }

    public static get_list_element(list:any[],i:number){
        let new_list = []
        new_list.push(list[i])
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            if(index!=i){
                new_list.push(element)
            }
        }
        return new_list;
    }

    public static sortByPercentage(arr) {
            // 计算每个元素的占比
            const counts = {};
            arr.forEach(element => {
                counts[element] = (counts[element] || 0) + 1;
            });
            
            // 排序数组
            const sortedArr = arr.sort((a, b) => {
                return counts[b] / arr.length - counts[a] / arr.length;
            });
            
            // 返回排序后的元素
            return sortedArr;
      }
}


