import { Component, Input, ViewChildren, QueryList, ElementRef, EventEmitter, Output, Renderer2, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { GestureController } from '@ionic/angular';
import { AlertService } from '../services/alert.service';
import { GameService } from '../services/game.service';

@Component({
  selector: 'app-home',
  templateUrl: 'valuesSorting.page.html',
  styleUrls: ['valuesSorting.page.scss'],
})
export class ValuesSortingPage {

  @ViewChildren('card') cards: QueryList<ElementRef>;
  cardsArray: Array<ElementRef>;

  @ViewChild('cross') cross: ElementRef;
  @ViewChild('heart') heart: ElementRef;


  @Output() choiceMade = new EventEmitter();
  moveOutWidth: number;
  shiftRequired: boolean;
  transitionInProgress: boolean;
  isHearts: boolean;
  heartVisible: boolean;
  crossVisible: boolean;
  deckAmount: number;
  deckCount: number = 0;

  constructor(private router: Router, private renderer: Renderer2, private gestureCtrl: GestureController, public alertService: AlertService, public game: GameService, public alert: AlertService) {}

  ngAfterViewInit() {
    this.moveOutWidth = document.documentElement.clientWidth * 1.5;
    this.cardsArray = this.cards.toArray();
    this.cards.changes.subscribe(()=>{
      this.cardsArray = this.cards.toArray();
    })
    this.deckAmount = this.game.cardset.length;
    this.swiper();
  };

  async swiper() {
    // select all cards one by one
    for(let i = 0; i < this.cardsArray.length; i++){
      const card = this.cardsArray[i];

      // create swipe gesture
      const gesture = this.gestureCtrl.create({
        el: card.nativeElement,
        gestureName: 'swiping',
        onMove: event => {
          if (event.deltaX === 0 || !this.game.cardset.length) return;
      
          // is transitioning stop swiper availability
          if (this.transitionInProgress) {
            this.handleShift();
          }
      
          this.renderer.addClass(card.nativeElement, 'moving');
      
          // set heart or cross icon
          if (event.deltaX > 0) { 
            this.toggleChoiceIndicator(false,true);
          }
          if (event.deltaX < 0) { 
            this.toggleChoiceIndicator(true,false);
          }
      
          // Create a small rotation to the swipe
          let xMulti = event.deltaX * 0.03;
          let yMulti = event.deltaY / 80;
          let rotate = xMulti * yMulti;
      
          this.renderer.setStyle(card.nativeElement, 'transform', 'translate(' + event.deltaX + 'px, ' + event.deltaY + 'px) rotate(' + rotate + 'deg)');
      
          this.shiftRequired = true;
        },
        onEnd: event => {

          // remove indicators
          this.toggleChoiceIndicator(false,false);

          if (!this.game.cardset.length) return;
      
          this.renderer.removeClass(card.nativeElement, 'moving');

          // Create a save state (in which movement the card needs to stay)
          let keep = Math.abs(event.deltaX) < 80;
          if (keep) {
            // trasform to startplace
            this.renderer.setStyle(card.nativeElement, 'transform', '');
            this.shiftRequired = false;
      
          } else {
            
            // create animation for fading away
            let endX = Math.max(Math.abs(event.velocityX) * this.moveOutWidth, this.moveOutWidth);
            let toX = event.deltaX > 0 ? endX : -endX;
            let endY = Math.abs(event.velocityY) * this.moveOutWidth;
            let toY = event.deltaY > 0 ? endY : -endY;
            let xMulti = event.deltaX * 0.03;
            let yMulti = event.deltaY / 80;
            let rotate = xMulti * yMulti;
      
            this.renderer.setStyle(card.nativeElement, 'transform', 'translate(' + toX + 'px, ' + (toY + event.deltaY) + 'px) rotate(' + rotate + 'deg)');
      
            // do actual stuff with the card
            this.shiftRequired = true;
            this.emitChoice(!!(event.deltaX > 0), this.game.cardset[0]);
            this.isHearts = !!(event.deltaX > 0);
          }

          // make sure swipe cant be used
          this.transitionInProgress = true;
        }
        
      });
      gesture.enable(true);
    }
  }

  async userClickedButton(event, heart) {
    event.preventDefault();
    if (!this.game.cardset.length) return false;
    // if value is true than its a heart
    if (heart) {

      // fade away the card
      this.renderer.setStyle(this.cardsArray[0].nativeElement, 'transform', 'translate(' + this.moveOutWidth + 'px, -100px) rotate(-30deg)');
      // set indicator
      this.toggleChoiceIndicator(false,true);

      // set state of the card
      this.emitChoice(heart, this.game.cardset[0]);
      this.isHearts = true;
    } else {
      // fade away the card
      this.renderer.setStyle(this.cardsArray[0].nativeElement, 'transform', 'translate(-' + this.moveOutWidth + 'px, -100px) rotate(30deg)');
      // set indicator
      this.toggleChoiceIndicator(true,false);
     
      // set state of the card
      this.emitChoice(heart, this.game.cardset[0]);
      this.isHearts = false;
    };

    // make sure swiping cant be used
    this.shiftRequired = true;
    this.transitionInProgress = true;
  };

  // set card value
  async toggleChoiceIndicator(cross, heart) {
    this.crossVisible = cross;
    this.heartVisible = heart;

    // set opacity of the card
    if(this.heartVisible){
      this.renderer.setStyle(this.heart.nativeElement, 'opacity', '1');
      this.renderer.setStyle(this.cross.nativeElement, 'opacity', '0');
    }else if(this.crossVisible){
      this.renderer.setStyle(this.heart.nativeElement, 'opacity', '0');
      this.renderer.setStyle(this.cross.nativeElement, 'opacity', '1');
    }else{
      this.renderer.setStyle(this.heart.nativeElement, 'opacity', '0');
      this.renderer.setStyle(this.cross.nativeElement, 'opacity', '0');
    }
  };

  // handle stack change
  async handleShift() {
    this.transitionInProgress = false;
    this.toggleChoiceIndicator(false,false)

    if (this.shiftRequired) {
      this.shiftRequired = false;

      // If the answer is true keep in stack
      if(this.isHearts){
        this.game.cardset[this.game.cardset.push(this.game.cardset.shift())-1];
      }else{
        this.game.cardset.shift();
      }

      // go to rearrange page
      if(this.game.cardset.length <= 5){
        await this.game.saveGameStorage("Values", "Align", this.game.cardset);
        await this.alertService.presentAlert("Done!","You've selected 5 cards, continue to the next page.");
        this.router.navigateByUrl(`/valuesAlign`);
      }
      await this.cycleCount();
    };

  };

  async cycleCount(){
    // set deck counter +1
    this.deckCount++;

    // check if the deck count reached the max of the deck
    if(this.deckCount >= this.deckAmount){
      await this.alertService.presentAlert("End of the deck reached","Make sure there are only 5 cards left");
      
      // reset the values
      this.deckCount = 0;
      this.deckAmount = this.game.cardset.length;

    }

  }

  async emitChoice(heart, card) {
    this.choiceMade.emit({
      choice: heart,
      payload: card
    })
  };
  
}