import { _decorator, Component, Node } from 'cc';
import { config } from '../../config';
import { tools } from '../../tools';
const { ccclass, property } = _decorator;
@ccclass('MovesGener')
export class MovesGener  {
    public cards_list:any[];
    public cards_dict:Map<string,number>=new Map();
    public single_card_moves:any[];
    public pair_moves:any[];
    public triple_cards_moves:any[];
    public bomb_moves:any[];
    public final_bomb_moves:any[];

    public init(cards_list){
        let self = this;
        self.cards_list = cards_list;
        self.cards_dict.clear()
        for (let index = 0; index < self.cards_list.length; index++) {
            const key = self.cards_list[index];
            if(self.cards_dict.get(key)){
                self.cards_dict.set(key,self.cards_dict.get(key)+1)
            }else{
                self.cards_dict.set(key,1)
            }
            
        }
        self.gen_type_1_single()
        self.pair_moves = []
        self.gen_type_2_pair()
        self.triple_cards_moves = []
        self.gen_type_3_triple()
        self.bomb_moves = []
        self.gen_type_4_bomb()
        self.final_bomb_moves = []
        self.gen_type_5_king_bomb()
    }

    public _gen_serial_moves(cards, min_serial, repeat = 1, repeat_num = 0) {
            if (repeat_num < min_serial) {
            repeat_num = 0;
            }
            console.log("repeat_num",repeat_num)
            // let single_cards:any = [...new Set(cards)].sort();
            let single_cards = cards.filter((card, index, self) => {
                return index === self.indexOf(card);
                }).sort((a,b)=>{return parseInt(a)-parseInt(b)})
               
            let seq_records = [];
            let moves = [];
        
            let start= 0;
            let  i = 0; 
            let longest = 1;
            while (i < single_cards.length) {
            if (i + 1 < single_cards.length && parseInt(single_cards[i + 1])  - parseInt(single_cards[i]) === 1) {
                longest += 1;
                i += 1;
            } else {
                seq_records.push([start, longest]);
                i += 1;
                start = i;
                longest = 1;
            }
            }
        
            for (let seq of seq_records) {
            if (seq[1] < min_serial) {
                continue;
            }
            let [start, longest] = seq;
            let longest_list = single_cards.slice(start, start + longest);
        
            if (repeat_num === 0) {
                let steps = min_serial;
                while (steps <= longest) {
                let index = 0;
                while (steps + index <= longest) {
                    let target_moves = longest_list
                    .slice(index, index + steps)
                    .reduce((acc, element) => acc.concat(Array(repeat).fill(element)), []);
                    target_moves.sort((a, b) => parseInt(a)  - parseInt(b));
                    moves.push(target_moves);
                    index += 1;
                }
                steps += 1;
                }
            } else {
                console.log("longest",longest)
                if (longest < repeat_num) {
                     continue;
                }
                let index = 0;
                while (index + repeat_num <= longest) {
                let target_moves = longest_list
                    .slice(index, index + repeat_num)
                    .reduce((acc, element) => acc.concat(Array(repeat).fill(element)), []);
                target_moves.sort((a, b) => parseInt(a)  - parseInt(b));
                moves.push(target_moves);
                index += 1;
                }
            }
            }
        
            return moves;

        // if (repeat_num < min_serial) {
        //     repeat_num = 0;
        // }
        // let tmep_cards = []
        // for (let index = 0; index < cards.length; index++) {
        //     const card = cards[index];
        //     tmep_cards.push(parseInt(card))
        // }
        // var single_cards = tmep_cards.filter(function(item, index) {
        //     return tmep_cards.indexOf(item) === index;
        // }).sort((a,b)=>{
        //     return a-b
        // })
        // var seq_records = [];
        // var moves = [];
        
        // var start = 0;
        // var i = 0;
        // var longest = 1;
        // while (i < single_cards.length) {
        //     if (i + 1 < single_cards.length && parseInt(single_cards[i + 1]) - parseInt(single_cards[i]) == 1) {
        //         longest += 1;
        //         i += 1;
        //     } else {
        //     seq_records.push([start, longest]);
        //         i += 1;
        //         start = i;
        //         longest = 1;
        //     }
        // }
        // for (let k = 0; k < seq_records.length; k++) {
        //     const seq = seq_records[k];
        //     let start = seq[0];
        //     let longest = seq[1];
        //     let longest_list = single_cards.slice(start, start + longest);

        //     if (repeat_num == 0) {
        //         var steps = min_serial;
        //         while (steps <= longest) {
        //             var index = 0;
        //             while (steps + index <= longest) {
        //             var target_moves = longest_list.slice(index, index + steps).map(function(item) {
        //                 return Array(repeat).fill(item);
        //             }).reduce(function(a, b) {
        //                 return a.concat(b);
        //             }).sort();
        //             moves.push(target_moves);
        //             index += 1;
        //             }
        //             steps += 1;
        //         }
        //         } else {
        //         if (longest < repeat_num) {
        //             return;
        //         }
        //         var index = 0;
        //         while (index + repeat_num <= longest) {
        //             var target_moves = longest_list.slice(index, index + repeat_num).map(function(item) {
        //             return Array(repeat).fill(item);
        //             }).reduce(function(a, b) {
        //             return a.concat(b);
        //             }).sort();
        //             moves.push(target_moves);
        //             index += 1;
        //         }
        //     }

        // }
        // let new_moves = []
        // for (let index = 0; index < moves.length; index++) {
        //     const element = moves[index];
        //     let temp_array = []
        //     for (let i = 0; i < element.length; i++) {
        //         const card = element[i];
        //         temp_array.push(`${card}`)
        //     }
        //     new_moves.push(temp_array)
        // }
        // return new_moves;
    }
      
    public gen_type_1_single(){
        let self = this;
        self.single_card_moves = []
        for (let index = 0; index < self.cards_list.length; index++) {
            const i = self.cards_list[index];
            self.single_card_moves.push([i])
        }
        return self.single_card_moves
    }

    public gen_type_2_pair(){
        let self = this;
        self.pair_moves = []
        self.cards_dict.forEach((v,k)=>{
            if (v >= 2) 
            self.pair_moves.push([k, k])
        })
        return self.pair_moves
    }
    public gen_type_3_triple(){
        let self = this;
        self.triple_cards_moves = []
        self.cards_dict.forEach((v,k)=>{
            if ( v >= 3) 
            self.triple_cards_moves.push([k, k,k])
        })
        return self.triple_cards_moves
    }


    public gen_type_4_bomb(){
        let self = this;
        self.bomb_moves = []
        self.cards_dict.forEach((v,k)=>{
            if ( v == 4) 
            self.bomb_moves.push([k, k,k,k])
        })
        return self.bomb_moves
    }

    public gen_type_5_king_bomb(){
        let self = this;
        self.final_bomb_moves = []
        // if(self.cards_list[20]!=null && self.cards_list[30]!=null){
        //     self.final_bomb_moves.push([20, 30])
        // }
        let count = 0;
        for (let index = 0; index < self.cards_list.length; index++) {
            const element = self.cards_list[index];
            if(element==='20'||element==='30'){
                count++;
            }
            if(count>=2){
                self.final_bomb_moves.push(['20', '30'])
                break;
            }
        }
        return self.final_bomb_moves
    }


    public gen_type_6_3_1(){
        let self = this;
        var result = [];
        for (var t = 0; t < self.single_card_moves.length; t++) {
            for (var i = 0; i < self.triple_cards_moves.length; i++) {
                if (self.single_card_moves[t][0] !== self.triple_cards_moves[i][0]) {
                    result.push(self.single_card_moves[t].concat(self.triple_cards_moves[i]));
                }
            }
        }
        return result;
    }
    

    public gen_type_7_3_2(){
        let self = this;
        let  result = []
        for (let index = 0; index < self.pair_moves.length; index++) {
            const t = self.pair_moves[index];
            for (let j = 0; j <  self.triple_cards_moves.length; j++) {
                const i =  self.triple_cards_moves[j];
                if(t[0] != i[0]){
                    result.push([t[0],t[0],i[0],i[0],i[0]])
                }
            }
        }
        return result
    }


    public gen_type_8_serial_single( repeat_num=0){
        let self = this;
        return self._gen_serial_moves(self.cards_list, config.MIN_SINGLE_CARDS, 1, repeat_num=repeat_num)
    }
   

    public gen_type_9_serial_pair(repeat_num=0){
        let self = this;
        let single_pairs = []
        self.cards_dict.forEach((v,k)=>{
            if(v >= 2){
                single_pairs.push(k)
            }
        })
        return self._gen_serial_moves(single_pairs, config.MIN_PAIRS, 2, repeat_num=repeat_num)
    }


    public gen_type_10_serial_triple( repeat_num=0){
        let self = this;
        let single_triples = []
        self.cards_dict.forEach((v,k)=>{
            if( v >= 3){
                single_triples.push(k)
            }
        })
        return self._gen_serial_moves(single_triples, config.MIN_TRIPLES, 3, repeat_num=repeat_num)
    }



    public gen_type_11_serial_3_1( repeat_num=0){
        let self = this;
        var serial_3_moves = self.gen_type_10_serial_triple(repeat_num);
        var serial_3_1_moves = [];
      
        for (var i = 0; i < serial_3_moves.length; i++) {
          var s3 = serial_3_moves[i];
          var s3_set = [];
          var new_cards = [];
      
          for (var j = 0; j < s3.length; j++) {
            var found = false;
            for (var k = 0; k < s3_set.length; k++) {
              if (s3_set[k] === s3[j]) {
                found = true;
                break;
              }
            }
            if (!found) {
              s3_set.push(s3[j]);
            }
          }
      
          for (var l = 0; l < this.cards_list.length; l++) {
            var found = false;
            for (var m = 0; m < s3_set.length; m++) {
              if (s3_set[m] === this.cards_list[l]) {
                found = true;
                break;
              }
            }
            if (!found) {
              new_cards.push(this.cards_list[l]);
            }
          }
      
          var subcards = self.select(new_cards, s3_set.length);
      
          for (var n = 0; n < subcards.length; n++) {
            var subcard = subcards[n];
            serial_3_1_moves.push(s3.concat(subcard));
          }
        }
      
        var unique_moves = [];
      
        for (var p = 0; p < serial_3_1_moves.length; p++) {
          var joined = serial_3_1_moves[p].join(",");
          var found = false;
          for (var q = 0; q < unique_moves.length; q++) {
            if (unique_moves[q].join(",") === joined) {
              found = true;
              break;
            }
          }
          if (!found) {
            unique_moves.push(serial_3_1_moves[p]);
          }
        }
      
        return unique_moves;
    }


    public gen_type_12_serial_3_2(repeat_num=0){
        function hasKey(obj, key) {
            return Object.prototype.hasOwnProperty.call(obj, key);
        }
        
        function select(arr, n) {
            var results = [];
        
            function backtrack(temp, start) {
                if (temp.length === n) {
                    results.push(temp.slice());
                    return;
                }
        
                for (var i = start; i < arr.length; i++) {
                    temp.push(arr[i]);
                    backtrack(temp, i + 1);
                    temp.pop();
                }
            }
        
            backtrack([], 0);
            return results;
        }
        
        function sorted(arr) {
            return arr.slice().sort(function(a, b) {
                return parseInt(a) - parseInt(b);
            });
        }
        var serial3Moves = this.gen_type_10_serial_triple(repeat_num);
        var serial32Moves = [];
        let self = this;
        // var pairSet = Object.keys(self.cards_dict).filter(function(key) {return self.cards_dict[key] >= 2; }).sort();
        var pairSet = [];
        self.cards_dict.forEach(function(value, key) {
            if (value >= 2) {
                pairSet.push(key);
            }
        });
        pairSet.sort();
        for (var i = 0; i < serial3Moves.length; i++) {
            var s3 = serial3Moves[i];
            var s3Set = {};
            var pairCandidates = [];

            for (var j = 0; j < s3.length; j++) {
                s3Set[s3[j]] = true;
            }

            for (var k = 0; k < pairSet.length; k++) {
                if (!hasKey(s3Set, pairSet[k])) {
                    pairCandidates.push(pairSet[k]);
                }
            }

            var subcards = select(pairCandidates, Object.keys(s3Set).length);
            for (var l = 0; l < subcards.length; l++) {
                var temp = s3.slice();
                for (var m = 0; m < subcards[l].length; m++) {
                    for (var n = 0; n < 2; n++) {
                        temp.push(subcards[l][m]);
                    }
                }
                serial32Moves.push(sorted(temp));
            }
        }

        return serial32Moves;
    }


    public gen_type_13_4_2(){
        let self = this;
        const four_cards = self.bomb_moves;
        // for (const k in self.cards_dict) {
        //   if (self.cards_dict[k] == 4) {
        //     four_cards.push(k);
        //   }
        // }
        var result = [];
        for (let i = 0; i < four_cards.length; i++) {
            const four = four_cards[i];
            // for (let index = 0; index < self.pair_moves.length; index++) {
            //     const pair = self.pair_moves[index];
            //     if(pair[0]!=four[0]){
            //         result.push([pair[0],pair[0],four[0],four[0],four[0],four[0]])
            //     }
                
            // }

            for (let index = 0; index < self.cards_list.length; index++) {
                const card = self.cards_list[index];
                if(card!=four[0]){
                    for (let j = 0; j < self.cards_list.length; j++) {
                        const card_two = self.cards_list[j];
                        if(card_two!=card&&card_two!=four[0]){
                            result.push([card,card_two,four[0],four[0],four[0],four[0]])
                        }
                    }
                }
              
            }
        }

        // for (var fc in four_cards) {
        //     var cards_list = self.cards_list.filter(function(k) {
        //         return k != fc;
        //     });
        //     var subcards = self.select(cards_list, 2);
        //     for (var i in subcards) {
        //         var temp = [fc, fc, fc, fc].concat(i);
        //         var isExists = false;
        //         for (var j in result) {
        //             if (tools.isArraysEqual(temp, result[j])) {
        //                 isExists = true;
        //                 break;
        //             }
        //         }
        //         if (!isExists) {
        //             result.push(temp);
        //         }
        //     }
        // }
        return result;
    }


    public gen_type_14_4_22(){
        const four_cards = [];
        this.cards_dict.forEach((value, key) => {
            if (value === 4) {
                four_cards.push(key);
            }
        });
    
        const result = [];
        for (const fc of four_cards) {
            const cards_list = [];
           
            this.cards_dict.forEach((value, key) => {
                if (key !== fc && value >= 2) {
                    cards_list.push(key);
                }
            });
  
            const subcards = this.select(cards_list, 2);
            for (const i of subcards) {
                result.push([fc, fc, fc, fc, i[0], i[0], i[1], i[1]]);
            }
        }
        return result;
    }



    public select(cards, num) {
        const combinations = [];
      
        function backtrack(startIndex, currentCombination) {
          if (currentCombination.length === num) {
            combinations.push([...currentCombination]);
            return;
          }
      
          for (let i = startIndex; i < cards.length; i++) {
            currentCombination.push(cards[i]);
            backtrack(i + 1, currentCombination);
            currentCombination.pop();
          }
        }
      
        backtrack(0, []);
        return combinations;
      }
      
      public gen_moves() {
            let self = this;
            let moves = [];

            let temp = self.gen_type_1_single();
            if(temp.length>0){
                moves.push(temp)
            }
            temp = self.gen_type_2_pair()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_3_triple()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_4_bomb()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_5_king_bomb()
            if(temp.length>0){
                moves.push(temp)
            }
    
            temp = self.gen_type_6_3_1()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_7_3_2()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_8_serial_single()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_9_serial_pair()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_10_serial_triple()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_11_serial_3_1()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_12_serial_3_2()
            if(temp.length>0){
                moves.push(temp)
            }

            temp = self.gen_type_13_4_2()
            if(temp.length>0){
                moves.push(temp)
            }
     
       
            temp = self.gen_type_14_4_22()
            if(temp.length>0){
                moves.push(temp)
            }
            return moves;
      }
      
}


