import { SoSUtility } from "./sos-utility.js";

/* -------------------------------------------- */
const NB_POKER_CARD = 54;
const IDX2CARDFAMILY = ['c', 'd', 'h', 's'];

/* -------------------------------------------- */
export class SoSCardDeck  {

  /* -------------------------------------------- */
  initCardDeck(actor, savedDeck = undefined ) {
    
    this.data = {};
    
    this.data.deck = [];
    this.data.discard = [];
    this.data.cardState = [];
    this.data.cardEdge  = [];

    if ( savedDeck.deck && savedDeck.deck.length > 0 ) {
      this.data.deck = duplicate(savedDeck.deck);
    }
    if ( savedDeck.discard && savedDeck.discard.length > 0 ) {
      this.data.discard = duplicate(savedDeck.discard);
    }
    if ( savedDeck.cardEdge && savedDeck.cardEdge.length > 0 ) {
      this.data.cardEdge = duplicate(savedDeck.cardEdge);
    }

    this.data.actor = actor;    
    if ( this.data.deck.length == 0 && this.data.discard.length == 0) {
      this.shuffleDeck();
    }
  }

  /* -------------------------------------------- */
  shuffleDeck() {
    this.cleanCardList();
    // Randomize deck
    while (this.data.deck.length != NB_POKER_CARD) {
      let idx = new Roll("1d54").roll( {async:false} ).total;
      if (!this.data.cardState[idx - 1]) {
        if (idx == 53) { // Red Joker
          this.data.deck.push( { cardName: 'jr' } );
        } else if (idx == 54) { // Black Joker
          this.data.deck.push({ cardName: 'jb' });
        } else {
          let familyIdx = idx % 4;
          let cardIdx = String( (idx % 13) + 1);
          cardIdx = (cardIdx.length < 2) ? "0"+cardIdx: cardIdx;
          let cardName = IDX2CARDFAMILY[familyIdx] + cardIdx;
          this.data.deck.push( { cardName: cardName } );
        }
        this.data.cardState[idx - 1] = true;
      }
    }    
  }

  /* -------------------------------------------- */
  resetDeck() {
    let newdeck = duplicate(this.data.deck).concat( duplicate (this.data.discard) )
    this.data.discard = [] // Reinit discard pile
    this.data.deck = [] 
    let decklen = newdeck.length
    let cardState = []
    for (let i = 0; i <decklen; i++) {
      cardState[i] = false
    }
    // Randomize deck
    while (this.data.deck.length != decklen) {
      let idx = new Roll("1d"+decklen).roll({async : false}).total
      //console.log("Deck stuff", this.data.deck.length, decklen, idx)
      if (!cardState[idx-1]) {
        this.data.deck.push( newdeck[idx-1] )
      }
      cardState[idx-1] = true
    }
  }
  
  /* -------------------------------------------- */
  discardEdge( cardName ) {
    let newEdge = this.data.cardEdge.filter( card => card.cardName != cardName);
    this.data.cardEdge = newEdge; // New edge list
    this.data.discard.push( { cardName: cardName }); // And push in the discard pile
  }

  /* -------------------------------------------- */
  drawEdge( edgeNumber = 1 ) {
    for (let i=0; i<edgeNumber; i++) {
      this.data.cardEdge.push( this.data.deck.pop() );
      console.log("DRAW EDGE", this.data.cardEdge);
    }
  }

  /* -------------------------------------------- */
  cleanCardList() {
    this.data.discard = []; // Reinit discard pile
    this.data.deck = [];
    this.data.cardEdge = [];
    for (let i = 0; i < NB_POKER_CARD; i++) {
      this.data.cardState[i] = false;
    }
  }

  /* -------------------------------------------- */
  getDeckSize() {
    return this.data.deck.length;    
  }

  /* -------------------------------------------- */
  getCardSuit( cardName ) {
    if ( cardName[0] == 'c') return 'club';
    if ( cardName[0] == 'd') return 'diamond';
    if ( cardName[0] == 'h') return 'hearts';
    if ( cardName[0] == 's') return 'spade';
    if ( cardName[0] == 'j') return 'joker';
  }

  /* -------------------------------------------- */
  drawFromDeck() { 
    let card = this.data.deck.pop();
    this.data.discard.push( card ); 
    return card;
  }

  /* -------------------------------------------- */
  getFromEdge( cardName) {
    let card = this.data.cardEdge.find( card => card.cardName == cardName); // Get the card
    let newEdge =  this.data.cardEdge.filter(card => card.cardName != cardName); // Remove used card
    this.data.cardEdge = newEdge;
    return card;
  }

  /* -------------------------------------------- */
  getCardValue( cardName ) {
    console.log(cardName);
    if (cardName[0] == 'j' ) return 0; // Joker case
    let parsed = cardName.match( /\w(\d\d)/i );
    let value = Number( parsed[1] );
    if ( value  > 10 ) value  -= 10;
    return value;
  }
  /* -------------------------------------------- */
  isCardFace(cardName) {
    if (cardName[0] == 'j' ) return false; // Joker case
    let parsed = cardName.match( /\w(\d\d)/i );
    let value = Number( parsed[1] );
    return (value > 10) ? true : false;
  }
  
  /* -------------------------------------------- */
  setJoker( flipData ) {
    console.log("THIS IS A JOKER !!!!");
    flipData.cardSlot[0].total = 0;
    flipData.cardSlot[0].card1Path =  `systems/foundryvtt-shadows-over-sol/img/cards/${flipData.cardSlot[0].card1.cardName}.webp`;
    flipData.isJoker = true;
  }
  /* -------------------------------------------- */
  isJoker( cardName) {
    return cardName[0] == 'j';
  }

  /* -------------------------------------------- */
  async doFlipFromDeckOrEdge( flipData  ) {
    flipData.cardSlot = [ { total: 0}];
    flipData.isTrump = false;
    flipData.isJoker = false;
    flipData.fullTrump = false;

    if ( flipData.edgeLuck ) { 
      flipData.cardOrigin == "Deck"; // Force Deck
    }

    // Select card origin
    if ( flipData.cardOrigin == "Deck") {
      flipData.cardSlot[0].card1 = this.drawFromDeck();
    } else {
      flipData.cardSlot[0].card1 = this.getFromEdge( flipData.edgeName );
    }   

    let cardsuit = this.getCardSuit(flipData.cardSlot[0].card1.cardName);
    if ( cardsuit == 'joker' ) {
      this.setJoker( flipData );
    } else {

      //console.log("First card : ", flipData.cardSlot[0].card1);
      // Face check for first card
      flipData.cardSlot[0].value1  = this.getCardValue(flipData.cardSlot[0].card1.cardName);
      flipData.cardSlot[0].isFace1 = this.isCardFace(flipData.cardSlot[0].card1.cardName);    
      flipData.cardSlot[0].card1Path =  `systems/foundryvtt-shadows-over-sol/img/cards/${flipData.cardSlot[0].card1.cardName}.webp`;
      flipData.cardSlot[0].card2 = false;
      if ( flipData.cardSlot[0].isFace1 ) {
        flipData.cardSlot[0].card2   = this.drawFromDeck();
        flipData.isJoker = this.isJoker(flipData.cardSlot[0].card2.cardName);
        flipData.cardSlot[0].value2  = this.getCardValue(flipData.cardSlot[0].card2.cardName);
        flipData.cardSlot[0].isFace2 = this.isCardFace(flipData.cardSlot[0].card2.cardName);
        flipData.cardSlot[0].card2Path = `systems/foundryvtt-shadows-over-sol/img/cards/${flipData.cardSlot[0].card2.cardName}.webp`;
      } else {
        flipData.cardSlot[0].value2 = 0; // Safe init
      }
      flipData.cardSlot[0].total =  flipData.cardSlot[0].value1 + flipData.cardSlot[0].value2;

      // Trump check
      flipData.cardSlot[0].cardsuit  = cardsuit;
      if ( !flipData.isJoker && ( cardsuit == flipData.stat.cardsuit || flipData.edgeLuck) ) {
        // This is a trump !
        flipData.cardSlot[1] = { total: 0 };
        flipData.isTrump = true;
        flipData.cardSlot[1].card1 = this.drawFromDeck();
        flipData.isJoker = this.isJoker(flipData.cardSlot[1].card1.cardName);
        flipData.cardSlot[1].card1Path = `systems/foundryvtt-shadows-over-sol/img/cards/${flipData.cardSlot[1].card1.cardName}.webp`;
        flipData.cardSlot[1].cardsuit  = this.getCardSuit(flipData.cardSlot[1].card1.cardName);
        flipData.cardSlot[1].value1  = this.getCardValue(flipData.cardSlot[1].card1.cardName);
        flipData.cardSlot[1].isFace1 = this.isCardFace(flipData.cardSlot[1].card1.cardName);        
        if ( !flipData.isJoker && flipData.cardSlot[1].isFace1 ) {
          flipData.cardSlot[1].card2   = this.drawFromDeck();
          flipData.isJoker = this.isJoker(flipData.cardSlot[1].card2.cardName);
          flipData.cardSlot[1].value2  = this.getCardValue(flipData.cardSlot[1].card2.cardName);
          flipData.cardSlot[1].isFace2 = this.isCardFace(flipData.cardSlot[1].card2.cardName);    
          flipData.cardSlot[1].card2Path = `systems/foundryvtt-shadows-over-sol/img/cards/${flipData.cardSlot[1].card2.cardName}.webp`;
        } else {
          flipData.cardSlot[1].value2 = 0; // Safe init
        }
        if ( flipData.cardSlot[1].cardsuit == cardsuit ) {
          flipData.fullTrump = true;
        }
        flipData.cardSlot[1].total =  flipData.cardSlot[1].value1 + flipData.cardSlot[1].value2;
      }
    }

    // Card Total
    flipData.cardTotal = flipData.cardSlot[0].total;
    flipData.cardSlotIndex = 0;
    if ( flipData.fullTrump ) {
      flipData.cardTotal = flipData.cardSlot[0].total + flipData.cardSlot[1].total;
    } else if (flipData.isTrump) {
      if (flipData.cardSlot[0].total > flipData.cardSlot[1].total ) {
        flipData.cardSlotIndex = 0;
        flipData.cardTotal = flipData.cardSlot[0].total;
      } else {
        flipData.cardSlotIndex = 0;
        flipData.cardTotal = flipData.cardSlot[1].total;
      }
    }

    // Compute final result and compare
    if ( flipData.mode == 'stat' || flipData.mode == 'weapon' ) {
      flipData.baseScore = flipData.stat.value + flipData.malusConsequence + flipData.bonusConsequence + flipData.woundMalus;
    } else if (flipData.mode == 'skill') {
      flipData.baseScore = Math.floor(flipData.stat.value/2) + flipData.skill.data.value + flipData.malusConsequence + flipData.bonusConsequence + flipData.woundMalus;
    }
    flipData.finalScore = flipData.baseScore + flipData.cardTotal + Number(flipData.modifier);
    flipData.magnitude = flipData.finalScore - flipData.tn;
    flipData.result = (flipData.magnitude >= 0) ? "Success": "Failure";

    //console.log(flipData);
    this.data.actor.saveDeck();
    flipData.alias  =  this.data.actor.name;
    let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-flip.html', flipData);
    ChatMessage.create( { content: html });

    if ( flipData.mode == 'weapon' && flipData.magnitude >= 0 && !flipData.isJoker) { // Success
      this.processWeapon( flipData );
    }

    if (flipData.isJoker) { // Critical mismatch !
      // TODO
    }
  }
  
  /* -------------------------------------------- */
  async processWeapon( flipData ) {
    flipData.damageCardsuit = flipData.cardSlot[flipData.cardSlotIndex].cardsuit;
    let damageKey = 'damage_'+ flipData.damageCardsuit;
    flipData.damageString = flipData.weapon.data[damageKey];
    if (flipData.damageString.includes('Str') ) {
      let damageRegexp = flipData.damageString.match(  /Str([\d])?\+?([\d])?([LMSC])/i );
      flipData.damageValue = (flipData.actor.data.data.stats.strength.value * Number(damageRegexp[1]?damageRegexp[1]:1)) + Number(damageRegexp[2]?damageRegexp[2]:0);
      flipData.damageSeverity = damageRegexp[3];
    } else {
      let damageRegexp = flipData.damageString.match( /(\d*)([LMSC])/i );
      flipData.damageValue = damageRegexp[1];
      flipData.damageSeverity = damageRegexp[2];
    }
    
    // Now process damage
    if ( flipData.target) {
      if ( game.user.isGM ) { // Direct access
        SoSUtility.applyDamage( flipData );
      } else {
        game.socket.emit("system.foundryvtt-shadows-over-sol", {
          msg: "msg_request_defense", data: flipData } );
      }
    } else {
      let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-only.html', flipData );
      ChatMessage.create( { content: html });
    }
  }

  /* -------------------------------------------- */
  getDeckHTML( ) {
    return "<a class='view-deck'><img class='flip-card deck-card' src='systems/foundryvtt-shadows-over-sol/img/cards/card_back.webp' /></a>";
  }

  /* -------------------------------------------- */
  getEdgeHTML( ) {
    let html = "";
    for (let edge of this.data.cardEdge) {
      html += `<a class='view-edge'><img class='flip-card edge-card' data-edge-card='${edge.cardName}' src='systems/foundryvtt-shadows-over-sol/img/cards/${edge.cardName}.webp' /></a>`
    }
    return html;
  }

    /* -------------------------------------------- */
    getEdgeHTMLForFlip( ) {
      let html = "";
      for (let edge of this.data.cardEdge) {
        html += `<a class='view-edge'><img class='flip-card edge-card' data-edge-card='${edge.cardName}' src='systems/foundryvtt-shadows-over-sol/img/cards/${edge.cardName}.webp' /></a>`
      }
      return html;
    }
  
  /* -------------------------------------------- */
  getDiscardTopHTML( ) {
    let html = "";
    console.log( "DISCARD: ", this.data.discard );
    if ( this.data.discard.length > 0) {
      let card = this.data.discard[this.data.discard.length-1];
      html = `<img class='view-discard flip-card' src='systems/foundryvtt-shadows-over-sol/img/cards/${card.cardName}.webp' />`;
    }
    return html;
  }
}