import Cartoon from "./Cartoon"
import defaultData from "./defaultData"
import { jelly } from "./utils"

export default class GameLogic {
  g_cartoon = null;
  g_formData = null
  g_enableClick = true;
  g_canvas = null;
  g_systemOption = null;
  g_useDefaultData = false;
  g_curDragonDisplay = null;
  
  m_questionAudioPlayed = false;
  m_currentQuestion = -1;
  m_questionDone = false;
  m_currentQuestionArray = []
  m_gameEnd = false;
  constructor(formData, systemOption) {
    this.g_systemOption = systemOption;
    this.g_canvas = cc.find('Canvas');
    this.g_cartoon = new Cartoon(cc);

    if(!formData.contentObj.dataArray || formData.contentObj.dataArray.length == 0) {
      this.g_useDefaultData = true;
      this.g_formData = defaultData
      console.warn("User default data =>", this.g_formData)
    } else {
      this.g_formData = formData.contentObj;
      console.log("User saved data =>", this.g_formData)
    }
    

    this.disableClick("Sysyem_init")
    this.g_cartoon.initLocalAudios([])

  
    this.initBg()
    this.initNodes();
    this.playAudio();
    // this.resetPosition();

  }

  initNodes() {
  // 	let dataLength = this.g_formData.dataArray.length;
  // 	this.g_cartoon.initCartoonElement("title_text", this.g_cartoon.getNodeByPath(`Canvas/title/text`))
  //   for(let index=0; index<10; index++) {
  //     const card = this.g_cartoon.initCartoonElement(`card_${index+1}`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}`))
  //     if(index>=dataLength) {
  //     	card.node.active = false;
  //     }

  //     this.g_cartoon.initCartoonElement(`card_${index+1}_star`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/star`));
  //     this.g_cartoon.initCartoonElement(`card_${index+1}_normal`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/normal`));
  //     this.g_cartoon.initCartoonElement(`card_${index+1}_selected`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/selected`));
  //     this.g_cartoon.initCartoonElement(`card_${index+1}_bell`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/bell`))
  //     this.g_cartoon.initCartoonElement(`card_${index+1}_bell_text`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/bell/index`))
  //     this.g_cartoon.initCartoonElement(`card_${index+1}_bell_outline`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/bell/bell_outline`));
  //     this.g_cartoon.initCartoonElement(`card_${index+1}_image_container`, this.g_cartoon.getNodeByPath(`Canvas/card_${index+1}/container/image`));
  //   }

  //   if(dataLength==0) {
  //   	this.g_cartoon.getNodeByPath(`Canvas/shengzi/line_1`).active = false;
  //     this.g_cartoon.getNodeByPath(`Canvas/shengzi/line_2`).active = false;
  //   } else if(dataLength<=5) {
  //   	this.g_cartoon.getNodeByPath(`Canvas/shengzi/line_2`).active = false;
  //   }

  //   this.g_cartoon.initCartoonElement(`snow_container`, this.g_cartoon.getNodeByPath(`Canvas/bgMain/snow_container`));
    
		// this.g_cartoon.initCartoonElement(`bottomButtons`, this.g_cartoon.getNodeByPath(`Canvas/bottomButtons`));
  //   this.g_cartoon.initCartoonElement(`restart_button`, this.g_cartoon.getNodeByPath(`Canvas/bottomButtons/restart`));

  //   this.g_cartoon.initCartoonElement(`bird_1`, this.g_cartoon.getNodeByPath(`Canvas/bird_1`));
  //   this.g_cartoon.initCartoonElement(`bird_2`, this.g_cartoon.getNodeByPath(`Canvas/bird_2`));
  //   this.g_cartoon.initCartoonElement(`birdStatic_1`, this.g_cartoon.getNodeByPath(`Canvas/bird_1/static`));
  //   this.g_cartoon.initCartoonElement(`birdStatic_2`, this.g_cartoon.getNodeByPath(`Canvas/bird_2/static`));
  //   this.g_cartoon.initCartoonElement(`birdAniFly_1`, this.g_cartoon.getNodeByPath(`Canvas/bird_1/fly`));
  //   this.g_cartoon.initCartoonElement(`birdAniFly_2`, this.g_cartoon.getNodeByPath(`Canvas/bird_2/fly`));
  //   this.g_cartoon.initCartoonElement(`birdAniWrong_1`, this.g_cartoon.getNodeByPath(`Canvas/bird_1/wrong`));
  //   this.g_cartoon.initCartoonElement(`birdAniWrong_2`, this.g_cartoon.getNodeByPath(`Canvas/bird_2/wrong`));

  //   this.g_cartoon.initCartoonElement(`birdAudio`, this.g_cartoon.getNodeByPath(`Canvas/bgMain/bird_audio`));
  //   this.g_cartoon.initCartoonElement(`birdAudioClickTarget`, this.g_cartoon.getNodeByPath(`Canvas/bgMain/bird_audio/clickTarget`));
  //   this.g_cartoon.initCartoonElement(`birdAudioNormal`, this.g_cartoon.getNodeByPath(`Canvas/bgMain/bird_audio/normal`));
  //   this.g_cartoon.initCartoonElement(`birdAudioWrong`, this.g_cartoon.getNodeByPath(`Canvas/bgMain/bird_audio/wrong`));
  //   this.g_cartoon.initCartoonElement(`birdAudioPlaying`, this.g_cartoon.getNodeByPath(`Canvas/bgMain/bird_audio/playing`));
    this.g_cartoon.initCartoonElement(`video_container`, this.g_cartoon.getNodeByPath(`Canvas/video_container`));
    this.g_cartoon.initCartoonElement(`video_container_video`, this.g_cartoon.getNodeByPath(`Canvas/video_container/video`));
  }

  initBg() {
    const bgNode_A = cc.find('Canvas/bgMain/bg_A');
    bgNode_A.scale = this.g_systemOption.mapScaleMax;
    // bgNode_A.height = cc.winSize.height;
    // bgNode_A.width = cc.winSize.width;
    console.log(bgNode_A.height, bgNode_A.width)
  }

  playAudio() {
  	var container = this.g_cartoon.getCartoonElement("video_container_video")
  	var video = container.node.getComponent(cc.VideoPlayer)
  	video.play()
  }
  /*
  
  initBGMusic() {
  	if(this.g_formData.bgMusic) {
			this.g_cartoon.playAudio(this.g_formData.bgMusic).then(audioID => {
        cc.audioEngine.setLoop(audioID, true);
        cc.audioEngine.setVolume(audioID, 0.3);
			})
  	}
  }

  resetPosition() {
    const bgNodeTitle= cc.find('Canvas/title');
    const bgNodeSnow = cc.find('Canvas/bgMain/bg_snow');
    const bgNodeShuicao = cc.find('Canvas/bgMain/shuicao');
    bgNodeTitle.y = cc.winSize.height / 2 - bgNodeTitle.height / 2 - 50
    bgNodeSnow.y = -cc.winSize.height / 2 + bgNodeSnow.height / 2
    bgNodeShuicao.y = -cc.winSize.height / 2 + bgNodeShuicao.height / 2

    const cardPos = [
  		{x: -500, y: 128}, {x: -250, y: 128}, {x: 0, y: 128}, {x: 250, y: 128}, {x: 500, y: 128},
  		{x: -500, y: -114}, {x: -250, y: -114}, {x: 0, y: -114}, {x: 250, y: -114}, {x: 500, y: -114}
  	]

		for(let index=0; index<10; index++) {
      const card = this.g_cartoon.getCartoonElement(`card_${index+1}`)
      card.node.setPosition(cardPos[index].x, cardPos[index].y)
    }
  }

  initImageCards() {
  	let dataLength = this.g_formData.dataArray.length;
    if(dataLength == 0) {
      return 
    }
    let newIndex = [0];
    if(dataLength!=1) {
      newIndex = this.getRandomArray(dataLength)
    }

    this.m_currentQuestionArray = []
    for(let index=0; index<dataLength; index++) {
    	this.m_currentQuestionArray.push(index)
    }

  	for (let index = 0; index<dataLength; index++) {
      let dataItem = this.g_formData.dataArray[newIndex[index]];
      let card = this.g_cartoon.getCartoonElement(`card_${index+1}`)
      card.open = false;

      let cardNormal = this.g_cartoon.getCartoonElement(`card_${index+1}_normal`)
      let cardSelected = this.g_cartoon.getCartoonElement(`card_${index+1}_selected`)
      let imageContainer = this.g_cartoon.getCartoonElement(`card_${index+1}_image_container`)
      imageContainer.cardIndex = index;
      imageContainer.correctIndex = newIndex[index];

      let bellOutline = this.g_cartoon.getCartoonElement(`card_${index+1}_bell_outline`)
      let bellText = this.g_cartoon.getCartoonElement(`card_${index+1}_bell_text`)
      bellText.node.getComponent(cc.Label).font = this.g_cartoon.getFontFamily("Comic Sans MS")
    	bellText.node.getComponent(cc.Label).fontSize = 20

      card.playAudio = (callback) => {
        if(dataItem.audio_url) {
          this.g_cartoon.playAudio(dataItem.audio_url, ()=>{
            if(callback) {
              callback()
            }
          })
        } else {
          if(callback) {
            callback()
          }
        }
      }

      if(this.g_useDefaultData || !dataItem) {
        let fr = this.getSpriteFrimeByResName("card_demo")
        imageContainer.node.setScale(1)
        imageContainer.node.getComponent(cc.Sprite).spriteFrame = fr
      } else {
        this.getSpriteFrimeByUrl(dataItem.image_url, (fr)=>{
          let sx = 220 / fr.getRect().width;
          let sy = 110 / fr.getRect().height;
          let s = Math.min(sx, sy)
          imageContainer.node.width = s * fr.getRect().width;
          imageContainer.node.height = s * fr.getRect().height;
          imageContainer.node.getComponent(cc.Sprite).spriteFrame = fr
        })
      }

      bellOutline.node.setScale(0);

      this.g_cartoon.subscribeTouchEvent(`card_${index+1}_image_container`, ()=>{
        if(!this.checkClickEnable()) {
          return
        }
      	if(card.open || this.m_gameEnd) {
      		return;
      	}

        this.disableClick(`card_${index+1}_image_container`)
        let birdStandCard = this.g_cartoon.getCartoonElement(`card_${this.m_currentQuestionArray[this.m_currentQuestion]+1}_image_container`)
        if(this.m_currentQuestion == imageContainer.correctIndex ) {
          this.g_cartoon.playAudio("good_job", ()=>{
            this.g_cartoon.playAudio(this.g_formData.dataArray[this.m_currentQuestion].audio_url)
          })

          let bell1 = this.g_cartoon.getCartoonElement(`card_${this.m_currentQuestionArray[this.m_currentQuestion]+1}_bell`)
          let bell2 = this.g_cartoon.getCartoonElement(`card_${imageContainer.cardIndex+1}_bell`)
          
          this.g_cartoon.tweenChange(bell1.node, {scaleX: 1.2, scaleY: 1.2}, 0.3, ()=>{
            this.g_cartoon.tweenChange(bell1.node, {scaleX: 0, scaleY: 0}, 0.4);
          });
          this.g_cartoon.tweenChange(bell2.node, {scaleX: 1.2, scaleY: 1.2}, 0.3, ()=>{
            this.g_cartoon.tweenChange(bell2.node, {scaleX: 0, scaleY: 0}, 0.4);
          });

        	card.open = true;
        	this.g_cartoon.getCartoonElement(`card_${imageContainer.cardIndex+1}_normal`).node.opacity = 0;
			    this.g_cartoon.getCartoonElement(`card_${imageContainer.cardIndex+1}_selected`).node.opacity = 255;
			    this.g_cartoon.getCartoonElement("bird_2").flyTo(imageContainer.cardIndex, ()=>{
			    	this.switchCard(this.m_currentQuestion, imageContainer.cardIndex, ()=>{
              this.loadQuestion(()=>{
                this.enableClick(`card_${index+1}_image_container`)
              })
            })
			    })
        } else {
          if(birdStandCard.cardIndex != index) {
            this.g_cartoon.getCartoonElement("bird_1").wrong()
            this.g_cartoon.getCartoonElement("bird_2").wrong()
            this.g_cartoon.playAudio("try_again", ()=>{
              setTimeout(()=>{
                this.g_cartoon.playAudio(this.g_formData.dataArray[this.m_currentQuestion].audio_url)
                this.enableClick(`card_${index+1}_image_container`)
              }, 1000)
            })
          } else {
            this.enableClick(`card_${index+1}_image_container`)
          }
        }
      })

      card.tweenHandle = null;
      const runBell = () => {
      	bellOutline.node.setScale(1, 1)
      	bellOutline.node.opacity = 255;
      	card.tweenHandle = this.g_cartoon.tweenChange(bellOutline.node, {scaleX: 2, scaleY: 2, opacity: 0}, 0.4, ()=>{
      		runBell()
      	})
      }

      const stopBell = () => {
      	if(card.tweenHandle) {
      		card.tweenHandle.stop();
      		card.tweenHandle = null
      	}
      	bellOutline.node.setScale(0, 0)
      	bellOutline.node.opacity = 0;
      }

      this.g_cartoon.subscribeTouchEvent(`card_${index+1}_bell`, ()=>{
        if(!this.checkClickEnable()) {
          return
        }
        if(dataItem.audio_url) {
          this.g_cartoon.stopAllAudio([this.g_formData.bgMusic?this.g_formData.bgMusic:""])
          card.playAudio(()=>{
            stopBell()
          })
          runBell()
        }
      })
    }
  }

  switchCard(fromIndex, toIndex, callback) {
    let i1 = this.m_currentQuestionArray[fromIndex]+1;
    let i2 = this.m_currentQuestionArray[toIndex]
    let card_1 = this.g_cartoon.getCartoonElement(`card_${i1}`)
    let card_2 = this.g_cartoon.getCartoonElement(`card_${toIndex+1}`)
    let cardStar_1 = this.g_cartoon.getCartoonElement(`card_${i1}_star`)
    let cardStar_2 = this.g_cartoon.getCartoonElement(`card_${toIndex+1}_star`)
    let cardStarAni_1 = this.g_cartoon.getCartoonElement(`card_${i1}_star`).node.getComponent(cc.Animation);
    let cardStarAni_2 = this.g_cartoon.getCartoonElement(`card_${toIndex+1}_star`).node.getComponent(cc.Animation);

    // console.log("交换",`card_${i1}`,`card_${toIndex+1}`)
    let x_1 = card_1.node.x
    let y_1 = card_1.node.y
    let x_2 = card_2.node.x
    let y_2 = card_2.node.y

 		let bell1 = this.g_cartoon.getCartoonElement(`card_${i1}_bell`)
    let bell2 = this.g_cartoon.getCartoonElement(`card_${toIndex+1}_bell`)
    
    this.g_cartoon.playAudio("bird_fly")
    this.g_cartoon.tweenChange(card_1.node, {x: x_2, y: y_2}, 1, ()=>{
      cardStar_1.node.opacity = 255;
      cardStarAni_1.play()
      this.g_cartoon.playAudio("star_boom")
      cardStarAni_1.on("finished", ()=>{
        cardStar_1.node.opacity = 0;
      })
      this.g_cartoon.tweenChange(bell1.node, {scaleX: 1, scaleY: 1}, 0.2);
    });

    this.g_cartoon.tweenChange(card_2.node, {x: x_1, y: y_1}, 1, ()=>{
      cardStar_2.node.opacity = 255;
      cardStarAni_2.play()
      cardStarAni_2.on("finished", ()=>{
        cardStar_2.node.opacity = 0;
      })
      this.g_cartoon.tweenChange(bell2.node, {scaleX: 1, scaleY: 1}, 0.2, ()=>{
        this.g_cartoon.getCartoonElement("bird_1").flyBack(()=>{
          setTimeout(()=>{
            if(callback) {
              callback();
            }
          }, 1500)
        })
        this.g_cartoon.getCartoonElement("bird_2").flyBack()
      });
    });

    let bellText1 = this.g_cartoon.getCartoonElement(`card_${i1}_bell_text`)
    let bellText2 = this.g_cartoon.getCartoonElement(`card_${toIndex+1}_bell_text`)
    toIndex = this.getCurrentIndex(toIndex)
    bellText1.node.getComponent(cc.Label).string = "" + (toIndex+1)
    bellText2.node.getComponent(cc.Label).string = "" + (fromIndex+1)

    let temp = this.m_currentQuestionArray[fromIndex]
    this.m_currentQuestionArray[fromIndex] = this.m_currentQuestionArray[toIndex]
    this.m_currentQuestionArray[toIndex] = temp;
  }

  getCurrentIndex(index) {
    return this.m_currentQuestionArray.indexOf(index)
  }

  initTitle() {
		let textNode = this.g_cartoon.getCartoonElement("title_text")
    let fontSize = 36
    if(this.g_formData.titleText.length>=32 && this.g_formData.titleText.length<48) {
      fontSize = 26
    } else if(this.g_formData.titleText.length>=48) {
      fontSize = 20
    }
    textNode.node.getComponent(cc.Label).string = this.g_formData.titleText;
		textNode.node.getComponent(cc.Label).font = this.g_cartoon.getFontFamily("Comic Sans MS")
    textNode.node.getComponent(cc.Label).fontSize = fontSize

    textNode.audioID = null
    this.g_cartoon.subscribeTouchEvent(textNode.key, ()=>{
      if(!this.checkClickEnable()) {
        return
      }
      if(textNode.audioID) {
        cc.audioEngine.stop(textNode.audioID);
        textNode.audioID = null
      }
      this.g_cartoon.playAudio(this.g_formData.questionAudio_url).then((audio_id) =>{
        textNode.audioID = audio_id
      })
    })
  }

  getRandomArray(length) {
    Array.prototype.shuffle = function() {
      let m = this.length, i;
      while (m) {
          i = (Math.random() * m--) >>> 0;
          [this[m], this[i]] = [this[i], this[m]]
      }
      return this;
    }
    
    const gameLogicCheck = (array, startIndex) => {
      let res = true;
      for(let index=startIndex; index<array.length; index++) {
        let changeIndex = array.indexOf(index)
        if(array[index]==index) {
          res = false
          break;
        }
      }
      return res;
    }

    let indexArray = []
    for(let index=0; index<length; index++) {
      indexArray.push(index)
    }
    var arr = indexArray.shuffle()
    var result = false;
    var temp = null;
    var count = 0;
    var arrayCanUse = []
    do{
      result = false;
      arr = indexArray.shuffle()
      arrayCanUse = JSON.parse(JSON.stringify(arr))

      for(let index=0; index<arr.length; index++) {
        if(index==arr[index]) {
          result = true;
          break
        }
      }
    
      if(!result) {
        for(let index=0; index<arr.length-2; index++) {
          var indexChange = arr.indexOf(index)
          temp = arr[index]
          arr[index] = index;
          arr[indexChange] = temp;
          if(!gameLogicCheck(arr, index+1)) {
            result = true;
            break
          }
        }

      }
      if(count>20000) {
        console.log("已经尝试超过两万次，终止生成", arr)
        result = false
      }
    } while(result)

    return arrayCanUse
  }

  loadQuestion(callback) {
    let index = null;
    let dataLength = this.g_formData.dataArray.length;
    for(let i=0; i<10; i++) {
      this.g_cartoon.getCartoonElement(`card_${i+1}_normal`).node.opacity = 255;
      this.g_cartoon.getCartoonElement(`card_${i+1}_selected`).node.opacity = 0;
    }
    this.m_currentQuestion++;
    if((this.m_currentQuestion+1)==dataLength) {
    	this.endGame()
      if(callback) {
        callback()
      }
    } else {
    	index = this.m_currentQuestionArray[this.m_currentQuestion]
      console.log(this.m_currentQuestion, index)
    	this.g_cartoon.getCartoonElement("bird_1").flyTo(index, ()=>{
        this.enableClick("bird_1")
        this.g_cartoon.playAudio(this.g_formData.dataArray[this.m_currentQuestion].audio_url)
        if(callback) {
          callback()
        }
      })
	    this.g_cartoon.getCartoonElement(`card_${index+1}_normal`).node.opacity = 0;
	    this.g_cartoon.getCartoonElement(`card_${index+1}_selected`).node.opacity = 255;
    }
  }

  endGame() {
    this.m_gameEnd = true;
    
  	// let resetBtn = this.g_cartoon.getCartoonElement("restart_button")
  	// resetBtn.node.active = true;
  }

  restartGame(callback) {
    let bird_1 = this.g_cartoon.getCartoonElement("bird_1");
    let bird_2 = this.g_cartoon.getCartoonElement("bird_2");
    if(bird_1.up) {
      bird_1.flyBack()
    }
    if(bird_2.up) {
      bird_2.flyBack()
    }

  	this.m_questionAudioPlayed = false;
	  this.m_currentQuestion = -1;
	  this.m_questionDone = false;
	  this.m_currentQuestionArray = []
	  this.m_gameEnd = false;
		for(let index=0; index<10; index++) {
      const card = this.g_cartoon.getCartoonElement(`card_${index+1}`)
    }
  	this.g_cartoon.stopAllAudio([this.g_formData.bgMusic?this.g_formData.bgMusic:""])
    this.showMaskLayer(()=>{
    	this.resetPosition();
    	this.initImageCards();
	    this.initTitle();
      this.hideMaskLayer(()=>{ 
        this.loadQuestion(()=>{
          if(callback) {
            callback()
          }
        });
      })
    })
  }

  initBottomButtons() {
  	let bottomButtons = this.g_cartoon.getCartoonElement("bottomButtons")
  	bottomButtons.node.x = cc.winSize.width / 2 - 100
  	bottomButtons.node.y = -cc.winSize.height / 2 + 50

  	let resetBtn = this.g_cartoon.getCartoonElement("restart_button")

  	this.g_cartoon.subscribeTouchEvent(resetBtn.key, ()=>{
      if(!this.checkClickEnable()) {
        return
      }

      this.disableClick(resetBtn.key)
      resetBtn.node.opacity = 128;
  		jelly(resetBtn.node)
      this.restartGame(()=>{
        this.enableClick(resetBtn.key)
        resetBtn.node.opacity = 255;
      })
  	})
  }

  initBirds() {
  	let bird_1 = this.g_cartoon.getCartoonElement("bird_1");
    let bird_2 = this.g_cartoon.getCartoonElement("bird_2");
    let birdAniFly_1 = this.g_cartoon.getCartoonElement("birdAniFly_1");
    let birdAniFly_2 = this.g_cartoon.getCartoonElement("birdAniFly_2");
    let birdStatic_1 = this.g_cartoon.getCartoonElement("birdStatic_1");
    let birdStatic_2 = this.g_cartoon.getCartoonElement("birdStatic_2");
    let birdAniWrong_1 = this.g_cartoon.getCartoonElement("birdAniWrong_1");
    let birdAniWrong_2 = this.g_cartoon.getCartoonElement("birdAniWrong_2");

    let birdAudioClickTarget = this.g_cartoon.getCartoonElement("birdAudioClickTarget");
    let birdAudio = this.g_cartoon.getCartoonElement("birdAudio");
    let birdAudioNormal = this.g_cartoon.getCartoonElement("birdAudioNormal");
    let birdAudioWrong = this.g_cartoon.getCartoonElement("birdAudioWrong");
    let birdAudioPlaying = this.g_cartoon.getCartoonElement("birdAudioPlaying");

    // Normal
    birdAniFly_1.node.opacity = 0;
    birdAniFly_2.node.opacity = 0;

    // Wrong
    birdAniWrong_1.node.opacity = 0;
    birdAniWrong_2.node.opacity = 0;

    birdAudioWrong.node.opacity = 0;
    birdAudioPlaying.node.opacity = 0;

    birdAudio.switchAni = (type) => {
      switch(type) {
        case 0:
          birdAudioNormal.node.opacity = 255;
          birdAudioWrong.node.opacity = 0;
          birdAudioPlaying.node.opacity = 0;
          break;
        case 1:
          birdAudioNormal.node.opacity = 0;
          birdAudioWrong.node.opacity = 255;
          birdAudioPlaying.node.opacity = 0;
          break;
        case 2:
          birdAudioNormal.node.opacity = 0;
          birdAudioWrong.node.opacity = 0;
          birdAudioPlaying.node.opacity = 255;
          break;
        default: 
          birdAudioNormal.node.opacity = 255;
          birdAudioWrong.node.opacity = 0;
          birdAudioPlaying.node.opacity = 0;
          break;
      }
    }

  	bird_1.flyTo = (cardIndex, callback)=>{

      this.g_cartoon.playAudio("bird_fly")
      let card = this.g_cartoon.getCartoonElement(`card_${cardIndex+1}`)
      card.node.setSiblingIndex(100)

  		const worldPos = cc.find("Canvas").convertToWorldSpaceAR(cc.v2(bird_1.node.x, bird_1.node.y));
			const localPos = card.node.convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y));

			bird_1.node.x = localPos.x;
  		bird_1.node.y = localPos.y;
  		bird_1.node.parent = card.node;
      birdAniFly_1.node.opacity = 255;
      birdStatic_1.node.opacity = 0;
      bird_1.up = true;
  		this.g_cartoon.tweenChange(bird_1.node, {x: -80, y: 90}, 1, ()=>{
        birdAniFly_1.node.opacity = 0;
        birdStatic_1.node.opacity = 255;
  			if(callback) {
  				callback()
  			}
  		})
  	}

  	bird_1.flyBack = (callback)=>{
      this.g_cartoon.playAudio("bird_fly")
  		let parent = bird_1.node.parent
  		const worldPos = parent.convertToWorldSpaceAR(cc.v2(bird_1.node.x, bird_1.node.y));
			const localPos = cc.find("Canvas").convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y));
			bird_1.node.x = localPos.x;
  		bird_1.node.y = localPos.y;
  		bird_1.node.parent = cc.find("Canvas");
      birdAniFly_1.node.opacity = 255;
      birdStatic_1.node.opacity = 0;
      bird_1.up = false;

  		this.g_cartoon.tweenChange(bird_1.node, {x: -100, y: -cc.winSize.height / 2 + bird_2.node.height + 10}, 0.5, ()=>{
        birdAniFly_1.node.opacity = 0;
        birdStatic_1.node.opacity = 255;
  			if(callback) {
  				callback()
  			}
  		})
  	}

  	bird_2.flyTo = (cardIndex, callback)=>{
      this.g_cartoon.playAudio("bird_fly")
      let card = this.g_cartoon.getCartoonElement(`card_${cardIndex+1}`)

      card.node.setSiblingIndex(100)

  		const worldPos = cc.find("Canvas").convertToWorldSpaceAR(cc.v2(bird_2.node.x, bird_2.node.y));
			const localPos = card.node.convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y));

			bird_2.node.x = localPos.x;
  		bird_2.node.y = localPos.y;
  		bird_2.node.parent = card.node;
      birdAniFly_2.node.opacity = 255;
      birdStatic_2.node.opacity = 0;
      bird_2.up = true;

  		this.g_cartoon.tweenChange(bird_2.node, {x: 80, y: 90}, 1, ()=>{
        birdAniFly_2.node.opacity = 0;
        birdStatic_2.node.opacity = 255;
  			if(callback) {
  				callback()
  			}
  		})
  	}

  	bird_2.flyBack = (callback)=>{
  		let parent = bird_2.node.parent
  		const worldPos = parent.convertToWorldSpaceAR(cc.v2(bird_2.node.x, bird_2.node.y));
			const localPos = cc.find("Canvas").convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y));
			bird_2.node.x = localPos.x;
  		bird_2.node.y = localPos.y;
  		bird_2.node.parent = cc.find("Canvas");
      birdAniFly_2.node.opacity = 255;
      birdStatic_2.node.opacity = 0;
      bird_2.up = false;

  		this.g_cartoon.tweenChange(bird_2.node, {x: 105, y: -cc.winSize.height / 2 + bird_2.node.height}, 0.5, ()=>{
        birdAniFly_2.node.opacity = 0;
        birdStatic_2.node.opacity = 255;
  			if(callback) {
  				callback()
  			}
  		})
  	}

    bird_1.wrong = ()=>{
      birdAniWrong_1.node.opacity = 255;
      birdStatic_1.node.opacity = 0;
      birdAudio.switchAni(1)
      setTimeout(() => {
        birdAniWrong_1.node.opacity = 0;
        birdStatic_1.node.opacity = 255;
        birdAudio.switchAni(0)
      }, 1000);
    }

    bird_2.wrong = ()=>{
      birdAniWrong_2.node.opacity = 255;
      birdStatic_2.node.opacity = 0;

      setTimeout(() => {
        birdAniWrong_2.node.opacity = 0;
        birdStatic_2.node.opacity = 255;
      }, 1000);
    }

    bird_1.node.y = -cc.winSize.height / 2 + bird_1.node.height + 10
    bird_2.node.y = -cc.winSize.height / 2 + bird_2.node.height
    birdAudio.node.y = -cc.winSize.height / 2 + bird_2.node.height + 20
    birdAudio.audioID = null

    this.g_cartoon.subscribeTouchEvent(birdAudioClickTarget.key, ()=>{
      if(!this.checkClickEnable()) {
        return
      }

      if(birdAudio.audioID) {
        cc.audioEngine.stop(birdAudio.audioID);
        birdAudio.audioID = null;
      }

      if(this.m_currentQuestion!=-1 && this.g_formData.dataArray[this.m_currentQuestion].audio_url) {
        birdAudio.switchAni(2)
        this.g_cartoon.playAudio(this.g_formData.dataArray[this.m_currentQuestion].audio_url, ()=>{
          birdAudio.switchAni(0)
        }).then(audio_id=>{
          birdAudio.audioID = audio_id
        })
      }
    })
  }

  snowing(time=5000) {
    const parent = this.g_cartoon.getCartoonElement("snow_container")
    const downHeigth = parent.node.height / 2 + 50
    console.log(downHeigth, this.g_systemOption.mapScaleMax)
    const getSnow = (index) => {
      const snowArray = [
        this.getSprNode('snow_1'), this.getSprNode('snow_2'), this.getSprNode('snow_3'), this.getSprNode('snow_4')
      ]
      const sf = this.getSprNode(`snow_${index}`).getComponent(cc.Sprite).spriteFrame;
      const node = new cc.Node();
      node.addComponent(cc.Sprite).spriteFrame = sf;
      node.y = downHeigth
      node.x = Math.ceil(Math.random() * cc.winSize.width) - cc.winSize.width / 2
      node.parent = parent.node

      return node;
    }
    
    const downTime = Math.ceil((cc.winSize.height / 100) * 1000) / 1000
    console.log(downTime)
    let intervalID = setInterval(() => {
      let snow = getSnow( Math.ceil(Math.random()*4) )
      // this.g_cartoon.tweenChange(snow, {y: -cc.winSize.height / 2}, downTime)
      cc.tween(snow).to(downTime, {y: -cc.winSize.height / 2}).call(()=>snow.destroy()).start()
    }, 100);

    // setTimeout(() => {
    //   clearInterval(intervalID)
    // }, time);

  }

	*/












  // Common function
  maskLayer = null;
  initMaskLayer() {
    const parentNode = this.g_cartoon.getNodeByPath("MaskLayer")
    parentNode.x = cc.winSize.width / 2
    parentNode.y = cc.winSize.height / 2
    const bNode = this.getSprNode('black');
    bNode.scaleX = cc.winSize.width / bNode.width;
    bNode.scaleY = cc.winSize.height / bNode.height;
    bNode.x = 0
    bNode.y = 0
    parentNode.setSiblingIndex(255)
    bNode.parent = cc.find('MaskLayer');
    bNode.active = false;
    this.maskLayer = bNode;
  }

  showMaskLayer(cb) {
    this.maskLayer.opacity = 0;
    this.maskLayer.active = true;
    cc.tween(this.maskLayer)
      .to(0.5, {opacity: 255}, {easing: 'sineOut'})
      .call(() => {
        cb()
      })
      .start()
  }

  hideMaskLayer(cb = null) {
    this.maskLayer.opacity = 255;
    cc.tween(this.maskLayer)
    .to(0.5, {opacity: 0}, {easing: 'sineIn'})
    .call(() => {
      this.maskLayer.active = false;
      if (cb) {
        cb()
      }
    })
    .start()
  }





  // Common API
  getSpriteFrimeByUrl(url, cb) {
		cc.assetManager.loadRemote(url, (err, img) => {
			const spriteFrame = new cc.SpriteFrame(img)
			if (cb) {
				cb(spriteFrame);
			}
		})
  }

  getSpriteFrimeByResName(name) {
    const sf = cc.find('Canvas/res/img/' + name).getComponent(cc.Sprite).spriteFrame;
    // const node = new cc.Node();
    // node.addComponent(cc.Sprite).spriteFrame = sf;
    return sf;
  }

  getSprNode(resName) {
    const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame;
    const node = new cc.Node();
    node.addComponent(cc.Sprite).spriteFrame = sf;
    return node;
  }



  // Sysyem function
  checkClickEnable(eventName) {
    if(this.g_enableClick) {
      return true;
    } else {
      console.log(`Click disabled by event [${this.g_disableClickEventName}]!`)
      return false;
    }
  }

  disableClick(eventName) {
    this.g_enableClick = false;
    this.g_disableClickEventName = eventName
    console.log(`Click disabled! [${eventName}]`)
  }

  enableClick(eventName) {
    this.g_enableClick = true;
    this.g_disableClickEventName = ""
    console.log(`Click enabled! [${eventName}]`)
  }

}
