import { Component, OnInit, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { Title } from '@angular/platform-browser';
import { webSocket } from "rxjs/webSocket";

interface UnoCard {
    id: number;
    number: string;
    color: string;
    tx: string;
}


@Component({
    selector: 'app-game',
    templateUrl: './game.component.html',
    styleUrls: ['./game.component.scss'],
    animations: [
        // the fade-in/fade-out animation.
        trigger('simpleFadeAnimation', [

            // the "in" style determines the "resting" state of the element when it is visible.
            state('in', style({ opacity: 1 })),

            // fade in when created. this could also be written as transition('void => *')
            transition(':enter', [
                style({ opacity: 0 }),
                animate(150)
            ]),

            // fade out when destroyed. this could also be written as transition('void => *')
            transition(':leave',
                animate(300, style({ opacity: 0 })))
        ]),
        trigger('flyInOut', [
            state('in', style({ transform: 'translateX(0)' })),
            transition('void => *', [
                style({ transform: 'translateX(100%)' }),
                animate(100)
            ]),
            transition('* => void', [
                animate(100, style({ opacity: 0}))
            ])
        ])
    ]
})

export class GameComponent implements OnInit {

    pulled: boolean = false;
    nextPlayerId: string = '';
    conn;
    myLastId: number = -1;

    //new objects
    playerList: any = [];
    winnerList: any = [];
    topCard: any = {};
    currentPlayer: any = {};
    lastPlayer: any = {};
    direction: number;
    gameStarted: boolean = false;
    thisPlayer: any = {};
    handCards: UnoCard[] = [];

    bannerText: string = "test";
    bannerShow: boolean = false;
    bannerError: boolean = false;
    bannerTimer;

    chatText = "";
    selectedCard: UnoCard;
    doubleCard: UnoCard;

    currentVote: any = undefined;

    options:any;

    timer: number = -1;

    constructor(
        private httpClient: HttpClient,
        private router: Router,
        private titleService: Title,
        @Inject(Window) private _window: Window
    ) {
        this.conn = webSocket(`ws${location.origin.replace(/http/,'')}/stream/uno.io`);
    }

    ngOnInit(): void {
        setInterval(() => {
            this.conn.next({action: 'heartbeat'});
            console.log("players", this.playerList)
        }, 4000);
        this.openSocket();
    }

    private showBanner(message, type) {
        if (this.bannerTimer) {
            clearTimeout(this.bannerTimer);
        }
        this.bannerError = type;
        this.bannerText = message;
        this.bannerShow = true;

        this.bannerTimer = setTimeout(() => {
            this.bannerShow = false;
        }, 2000)
    }

    private openSocket(){
        

        this.conn.subscribe(
            msg => this.processMessage(msg), // Called whenever there is a message from the server.
            err => {
                console.log(err)
                this.router.navigate(['/browser'])
            }, // Called if at any point WebSocket API signals some kind of error.
            () => this.router.navigate(['/browser']) // Called when connection is closed (for whatever reason).
          );

        this.conn.next({
            action: 'register', 
            id: localStorage.getItem('uid'),
            lobby: localStorage.getItem('session'),
        });
        this.conn.next({action: 'initData'});
        //this.conn.emit('new-message', "RAS@" + localStorage.getItem('uid'));
    }

    private processMessage(msg){
        if (msg.notify){ this.showBanner(msg.notify,!msg.warning); return; }
        if (msg.player){ this.processPlayerList(msg); return; }
        if (msg.chat){ this.chatText += msg.chat;  return; }
        if (msg.initClientData){this.processInitClient(msg); return; }
        if (msg.kick){
            this.conn.complete();
            this.router.navigate(['/browser']); 
        }
        if (msg.gameUpdate){this.processGameUpdate(msg); return;}
        if (msg.hand){this.processHand(msg); return; }
        if (msg.vote){this.startVote(msg); return; }
        if (msg.voteres){this.updateVote(msg); return; }
        if (msg.endvote){this.stopVote(); return; }
        if (msg.timer || msg.timer == 0){this.updateTimer(msg); return; }
        if (msg.sound){this.playSound(msg); return; }
        if (msg.changprop){
            if (msg.changprop == 'canskip'){
                this.pulled = true; // kann jetzt uno sagen
            }
        }
    }
    //new update functions

    private playSound(msg){
        let audio = new Audio();
        audio.src = msg.sound;
        audio.load();
        audio.play();
    }
    
    private updateTimer(msg){
        if (msg.timer >= 0){
            let audio = new Audio();
            audio.src = "../assets/tick.wav";
            audio.load();
            audio.play();
        }
        this.timer = msg.timer;
    }

    private startVote(msg){
        this.currentVote = {
            ...msg,
            voted: false,
            all: 0,
            timer: setTimeout(() => this.stopVote(),msg.time)
        }

        console.log("startvote",this.currentVote )
    }

    private stopVote(){
        clearTimeout(this.currentVote.timer)
        this.currentVote = undefined;
        console.log("stopvote",this.currentVote )
    }

    private updateVote(msg){
        this.currentVote.questions[0].counter = msg.voteres[0].counter;
        this.currentVote.all = msg.voteres[0].counter.reduce((a, b) => a + b, 0)
        console.log("updatevote",this.currentVote )

    }

    public vote(id){
        console.log("vote")
        this.conn.next({vote: id + 1});

    }

    private processPlayerList(msg){
        if(msg.player == 'modify'){
            let pfound: boolean= false;
            //search winner
            this.winnerList.forEach((player, ix) => {
                if(player.userId == msg.data.userId){
                    pfound = true;
                    this.winnerList[ix] = msg.data;
                    console.log("update winner",msg.data)
                }
            });
            if (!pfound){
                this.playerList.forEach((player, ix) => {
                    if(player.userId == msg.data.userId){
                        pfound = true;
                        this.playerList[ix] = msg.data;
                        console.log("update player",msg.data)
                    }
                });
            }
            if (!pfound){
                console.log("add player to list",msg.data )
                this.playerList.push(msg.data);
            }
        }else if(msg.player == 'remove'){
            this.playerList = this.playerList.filter(el => el.userId != msg.data.userId);
            console.log("remove player from list",msg.data )
        }else if(msg.player == 'winners'){
            this.winnerList = msg.data
        }else if(msg.player == 'all'){
            this.playerList = msg.players
            this.winnerList = msg.winners
            
        }
        this.processPlayerUpdate();
        this.playerChangeEvent();
    }

    private processHand(msg){
        if(msg.hand == 'add'){
            this.handCards.push(msg.card)
            let audio = new Audio();
            audio.src = "../assets/cardSlide7.wav";
            audio.load();
            audio.play();
        }else if(msg.hand == 'remove'){
            this.handCards = this.handCards.filter(el => el.id != msg.card.id);
        }else if(msg.hand == 'all'){
            this.handCards = msg.cards;
        }
    }

    private processInitClient(msg){
        this.playerList = msg.initClientData.players;
        this.winnerList = msg.initClientData.winners;
        //karten
        this.topCard = msg.initClientData.cardsPlayed[msg.initClientData.cardsPlayed.length -1 ];
        for (let pi = 0; pi < this.playerList.length; pi++) {
            if (this.playerList[pi].userId == msg.initClientData.currentPlayer) {
                this.currentPlayer = this.playerList[pi];
            }
        }
        this.handCards = msg.initClientData.hand;
        this.direction = msg.initClientData.direction;
        this.updateCardColor();
        this.processPlayerUpdate();
        this.playerChangeEvent();
        this.gameStarted = msg.initClientData.started;
        this.options = msg.initClientData.extraRules;
        document.getElementById("open_rules_modal").click();

    }

    private processGameUpdate(msg){
        switch(msg.gameUpdate){
            case 'playedStack':
                this.topCard = msg.card[msg.card.length -1 ];
                this.updateCardColor();
                let audio = new Audio();
                audio.src = "../assets/cardPlace1.wav";
                audio.load();
                audio.play();
                break;
            case 'currentPlayer':
                for (let pi = 0; pi < this.playerList.length; pi++) {
                    if (this.playerList[pi].userId == msg.currentplayer) {
                        this.currentPlayer = this.playerList[pi];
                    }
                }
                this.direction = msg.direction;
                this.playerChangeEvent();
                break;
            case 'status':
                this.gameStarted = msg.started;
                this.processPlayerUpdate();
                this.playerChangeEvent();
                break;
        }
    }

    //helper functions
    private updateCardColor(){
        if (this.topCard){
            if (this.topCard.number == 'wild') {
                switch (this.topCard.color) {
                    case 'blue': this.topCard.tx = "/assets/cards/311.png"; break;
                    case 'green': this.topCard.tx = "/assets/cards/321.png"; break;
                    case 'red': this.topCard.tx = "/assets/cards/331.png"; break;
                    case 'yellow': this.topCard.tx = "/assets/cards/341.png"; break;
                }
            }
            if (this.topCard.number == 'wild+4') {
                switch (this.topCard.color) {
                    case 'blue': this.topCard.tx = "/assets/cards/312.png"; break;
                    case 'green': this.topCard.tx = "/assets/cards/322.png"; break;
                    case 'red': this.topCard.tx = "/assets/cards/332.png"; break;
                    case 'yellow': this.topCard.tx = "/assets/cards/342.png"; break;
                }
            }
        }
        
    }

    private playerChangeEvent(){
        
        
        if (this.currentPlayer.userId != this.thisPlayer.userId) {
            this.pulled = false;
            this.titleService.setTitle("UNO - " + this.thisPlayer.nickname);
        } else {
            this.titleService.setTitle("DU BIST DRAN! - UNO - " + this.thisPlayer.nickname);
            
        }
        //get next player
        let index = 0;
        this.playerList.forEach((obj, ix) => {
            if (obj.userId == this.currentPlayer.userId) {index = ix;}
        });
        let newIndex = index + this.direction;
        if (newIndex < 0) { newIndex +=  this.playerList.length }
        if (newIndex > ( this.playerList.length - 1)) { newIndex -=  this.playerList.length }
        this.nextPlayerId =  this.playerList[newIndex].userId;

        if (this.currentPlayer.userId != this.lastPlayer){
            if (this.currentPlayer.userId == this.thisPlayer.userId){
                let audio = new Audio();
                audio.src = "../assets/when.mp3";
                audio.load();
                audio.play();
            }
            this.lastPlayer = this.currentPlayer.userId;
        }
        
    }

    private processPlayerUpdate(){
        const userId = localStorage.getItem('uid');
        for (let pi = 0; pi < this.playerList.length; pi++) {
            if (this.playerList[pi].userId == userId) {
                this.thisPlayer = this.playerList[pi];
            }
        }
        for (let pi = 0; pi < this.winnerList.length; pi++) {
            if (this.winnerList[pi].userId == userId) {
                this.thisPlayer = this.winnerList[pi];
            }
        }
    }


    //old 

    private comparer(otherArray) {
        return function (current) {
            return otherArray.filter(function (other) {
                return other.value == current.value && other.display == current.display
            }).length == 0;
        }
    }

    private updateHand(newCards) {
        if (!newCards) { return; } //wenn fertig oder nicht begonnen tue nichts
        //prüfe differenz

        newCards.forEach(el => {
            if ((this.handCards.filter(nel => el.id == nel.id)).length == 0) {
                this.handCards.push(el);
            }
        });
        this.handCards.forEach(el => {
            if ((newCards.filter(nel => el.id == nel.id)).length == 0) {
                this.handCards = this.handCards.filter(fel => fel.id != el.id);
            }
        });

    }


    public leave() {
        this.conn.next({action: 'uibutton',button:'leave'});
        this.conn.complete();
    }

    public ready() {
        this.conn.next({action: 'uibutton',button:'ready'});
    }

    public skip() {
        this.conn.next({action: 'uibutton',button:'skip'});
    }

    public uno() {
        this.conn.next({action: 'uibutton',button:'uno'});
    }

    public pull() {
        this.conn.next({action: 'uibutton',button:'pull'});
    }

    public play(card) {
        //
        let doubleFound = -1;
        this.handCards.forEach(el => {
            if (el.id != card.id && el.color == card.color && el.number == card.number && card.number != '+2' && card.number != 'wild+4'){
                doubleFound = el.id;
                this.doubleCard = el;
            }
        })
        console.log(doubleFound)
        if (doubleFound > -1){
            document.getElementById("open_rdouble_modal").click();
        }else{
            this.playSingle();
        }
    }

    public playSingle() {
        console.log("play single ", this.selectedCard)
        this.conn.next({action: 'uibutton',button:'play',card:this.selectedCard});
    }

    public playDouble(){
        console.log("play double ", this.selectedCard)
        this.conn.next({action: 'uibutton',button:'double',card:[this.selectedCard,this.doubleCard]});
    }

    public playwild(number, color) {
        this.conn.next({action: 'uibutton',button:'play',card:{
            id: this.selectedCard.id,
            number: number,
            color: color,
            tx: this.selectedCard.tx,
        }});
    }

}
