const rollButton = document.querySelector('#rollButton');
const diceHtml = document.querySelectorAll('.die');
const currentPlayerHtml = document.querySelector('#currentPlayer');
const rollsHtml = document.querySelector('#rolls');
const surrenderButton = document.querySelector('#surrenderButton');
const addPlayerButton = document.querySelector('#addPlayer');
const startGameButton = document.querySelector('#startButton');
const playerNameInput = document.querySelector('#nameInput');
const playerList = document.querySelector('#playerList');

let started = false;
let playerNames = [];
let rollTurn = 0;
let diceData = [
    1,
    2,
    3,
    4,
    5
]
let rolling = false;
let players = [    
];

let rounds = 0;

// EVENT LISTENERS FOR DICE
diceHtml.forEach(die => {
    die.addEventListener('click', function() {holdDie(die);});
});

// ROLL BUTTON EVENT LISTENER
rollButton.addEventListener('click', rollDice);

// KEYBOARD EVENT LISTENER
window.addEventListener('keydown', (event) => {
    if ((event.key === 'r' || event.key === "Enter") && started) {
        event.preventDefault();
        rollDice();
    };
    if(event.key === "Enter" && !started) {
        event.preventDefault();
        addPlayer();
    };
});

// SURRENDER BUTTON EVENT LISTENER
surrenderButton.addEventListener('click', surrender);

// EVENT LISTENERS FOR ADD PLAYER BUTTON
addPlayerButton.addEventListener('click', addPlayer);


// EVENT LISTENER FOR START GAME BUTTON
startGameButton.addEventListener('click', () => {
    if (playerNames.length < 1) return;

    started = true;
    document.querySelector('body').classList.add('started');
    playerNames.forEach(name => {
        createPlayer(name.name);
    });
    console.log(players);
    players[0].turn = true;
    players[0].ui.forEach(element => {
        element.classList.add('currentPlayer');
    });
    currentPlayerHtml.textContent = players[0].name;
    highlightClosePlayers();    
    
});

// ADD PLAYER TO LIST
function addPlayer(){
    if (playerNameInput.value === '') return;
    if (playerNameInput.value.length >= 16) {
        alert("Keep Player Name under 16 characters");
        return;
    }
    let row = document.createElement('tr');
    
    let playerName = {
        name: playerNameInput.value,
        ui: row,
        index: playerNames.length
    }
    let name = document.createElement('td');
    let nameText = document.createElement('h5');
    nameText.textContent = playerNameInput.value;
    name.appendChild(nameText);
    let deleteTd = document.createElement('td');
    let deleteButton = document.createElement('button');
    deleteButton.addEventListener('click', () => {
        row.remove();
        playerNames.splice(playerName.index, 1);
        console.log(playerNames);
    });
    deleteButton.innerHTML = '<img src="img/delete.svg">';
    deleteTd.appendChild(deleteButton);
    row.appendChild(name);
    row.appendChild(deleteTd);
    playerList.appendChild(row);

    playerNameInput.value = '';
    playerNames.push(playerName);
}

// ADD PLAYER ROW
function addPlayerRow(inName){
    playerId = players.length + 1;
    let UI = [];
    thead = document.querySelector('#game thead tr');
    th = document.createElement('th');
    th.textContent = inName;
    th.classList.add('currentPlayer');
    thead.appendChild(th);
    let width = th.clientWidth >= 70 ? th.clientWidth : 70;
    th.style.width = width + 'px';    
    th.classList.remove('currentPlayer');
    UI.push(th);
    document.querySelectorAll('#game tbody tr').forEach(tr => {
        td = document.createElement('td');
        td.id = inName + tr.id;
        td.style.width = width + 'px';
        tr.appendChild(td);
        UI.push(td);
    });
    return UI;
}

// CREATE PLAYER
function createPlayer(inName) {
    const ui = addPlayerRow(inName);
    const id = players.length + 1;
    let player = {
        ui: ui,
        removeUI: function() {
            this.ui.forEach(element => {
                element.remove();
            });
        },
        name: inName,
        id: id,
        scoresheet: {
            uiElements: {
                totalScore: document.querySelector('#total td:nth-child(' + (id + 1) + ')'),
                sum: document.querySelector('#sum td:nth-child(' + (id + 1) + ')'),
                bonus: document.querySelector('#bonus td:nth-child(' + (id + 1) + ')')
            },
            ones: {
                name: 'Ones',
                score: 0,
                used: false,
                ui: document.querySelector('#ones td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    return diceData.filter(die => die === 1).length;
                }
            },
            twos: {
                name: 'Twos',
                score: 0,
                used: false,
                ui: document.querySelector('#twos td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    return diceData.filter(die => die === 2).length * 2;
                }
            },
            threes: {
                name: 'Threes',
                score: 0,
                used: false,
                ui: document.querySelector('#threes td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    return diceData.filter(die => die === 3).length * 3;
                }
            },
            fours: {
                name: 'Fours',
                score: 0,
                used: false,
                ui: document.querySelector('#fours td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    return diceData.filter(die => die === 4).length * 4;
                }
            },
            fives: {
                name: 'Fives',
                score: 0,
                used: false,
                ui: document.querySelector('#fives td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    return diceData.filter(die => die === 5).length * 5;
                }
            },
            sixes: {
                name: 'Sixes',
                score: 0,
                used: false,
                ui: document.querySelector('#sixes td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    return diceData.filter(die => die === 6).length * 6;
                }
            },
            sum: function() {
                return this.ones.score + this.twos.score + this.threes.score + this.fours.score + this.fives.score + this.sixes.score;
            },
            bonus: function() {
                return this.sum() >= 84 ? 50 : 0;
            },
            onePair: {
                name: 'One Pair',
                score: 0,
                used: false,
                ui: document.querySelector('#onePair td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let score = 0;
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length >= 2) {
                            score = index * 2;
                            break;
                        }
                    }
                    return score;
                }
            },
            twoPairs: {
                name: 'Two Pairs',
                score: 0,
                used: false,
                ui: document.querySelector('#twoPairs td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let score = 0;
                    let pairs = 0;
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length >= 2) {
                            score += index * 2;
                            pairs++;
                        }
                    }
                    return pairs === 2 ? score : 0;
                }
            },
            threePairs: {
                name: 'Three Pairs',
                score: 0,
                used: false,
                ui: document.querySelector('#threePairs td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let score = 0;
                    let pairs = 0;
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length >= 2) {
                            score += index * 2;
                            pairs++;
                        }
                    }
                    return pairs === 3 ? score : 0;
                }
            },
            threeOfAKind: {
                name: 'Three of a Kind',
                score: 0,
                used: false,
                ui: document.querySelector('#threeOfAKind td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length >= 3) {
                            return index * 3;
                        }
                    }
                    return 0;
                }
            },
            twoThreeOfAKind: {
                name: 'Two Three of a Kind',
                score: 0,
                used: false,
                ui: document.querySelector('#twoThreeOfAKind td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let score = 0;
                    let three = 0;
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length >= 3) {
                            score += index * 3;
                            three++;
                        }
                    }
                    return three === 2 ? score : 0;
                }
            },
            fourOfAKind: {
                name: 'Four of a Kind',
                score: 0,
                used: false,
                ui: document.querySelector('#fourOfAKind td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length >= 4) {
                            return index * 4;
                        }
                    }        
                    return 0;            
                }
            },
            smallStraight: {
                name: 'Small Straight',
                score: 0,
                used: false,
                ui: document.querySelector('#smallStraight td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let straight = 0;
                    for (let index = 1; index <= 5; index++) {
                        if (diceData.includes(index)) {
                            straight++;
                        }
                    }
                    return straight === 5 ? 15 : 0;
                }
            },
            largeStraight: {
                name: 'Large Straight',
                score: 0,
                used: false,
                ui: document.querySelector('#largeStraight td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let straight = 0;
                    for (let index = 2; index <= 6; index++) {
                        if (diceData.includes(index)) {
                            straight++;
                        }
                    }
                    return straight === 5 ? 20 : 0;
                }
            },
            poker: {
                name: 'Poker',
                score: 0,
                used: false,
                ui: document.querySelector('#poker td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    numbersHit = [];
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length === 1) {
                            numbersHit.push(index);
                        }
                    }
                    return numbersHit.length === 6 ? 21 : 0;
                }
            },
            fullHouse: {
                name: 'Full House',
                score: 0,
                used: false,
                ui: document.querySelector('#fullHouse td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let score = 0;
                    let pairs = 0;
                    let four = 0;
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length === 2) {
                            score += index * 2;
                            pairs++;
                        }
                        if (diceData.filter(die => die === index).length === 4) {
                            score += index * 4;
                            four++;
                        }
                    }
                    return pairs === 1 && four === 1 ? score : 0;
                }
            },
            chance: {
                name: 'Chance',
                score: 0,
                used: false,
                ui: document.querySelector('#chance td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    let total = 0;
                    diceData.forEach(die => total += die);
                    return total;
                }
            },
            yatzy: {
                name: 'Yatzy',
                score: 0,
                used: false,
                ui: document.querySelector('#yatzy td:nth-child(' + (id + 1) + ')'),
                getScore: function() {
                    for (let index = 6; index > 0; index--) {
                        if (diceData.filter(die => die === index).length === 6) {
                            return 50 + index * 6;
                        }
                    }
                    return 0;
                }
            },
            total: function() {
                return this.sum() + this.bonus() + this.onePair.score + this.twoPairs.score + this.threePairs.score + this.threeOfAKind.score + this.twoThreeOfAKind.score + this.fourOfAKind.score + this.smallStraight.score + this.largeStraight.score + this.poker.score + this.fullHouse.score + this.chance.score + this.yatzy.score;
            },
            updateUI: function(){
                updatePlayerUI(this);
            },
            showPotential: function() {
                showPotential(this.ones);
                showPotential(this.twos);
                showPotential(this.threes);
                showPotential(this.fours);
                showPotential(this.fives);
                showPotential(this.sixes);
                showPotential(this.onePair);
                showPotential(this.twoPairs);
                showPotential(this.threePairs);
                showPotential(this.threeOfAKind);
                showPotential(this.twoThreeOfAKind);
                showPotential(this.fourOfAKind);
                showPotential(this.smallStraight);
                showPotential(this.largeStraight);
                showPotential(this.poker);
                showPotential(this.fullHouse);
                showPotential(this.chance);
                showPotential(this.yatzy);
            }
        },
        turn: false
    }
    players.push(player);
}

// UPDATE UI
function updatePlayerUI(input) {
    function scoreToText(element){
        if(element.used) element.ui.textContent = element.score === 0 ? "X" : element.score;
        else element.ui.textContent = "";
    }    
    scoreToText(input.ones);
    scoreToText(input.twos);
    scoreToText(input.threes);
    scoreToText(input.fours);
    scoreToText(input.fives);
    scoreToText(input.sixes);
    scoreToText(input.onePair);
    scoreToText(input.twoPairs);
    scoreToText(input.threePairs);
    scoreToText(input.threeOfAKind);
    scoreToText(input.twoThreeOfAKind);
    scoreToText(input.fourOfAKind);
    scoreToText(input.smallStraight);
    scoreToText(input.largeStraight);
    scoreToText(input.poker);
    scoreToText(input.fullHouse);
    scoreToText(input.chance);
    scoreToText(input.yatzy);
    input.uiElements.sum.textContent = input.sum();
    if (input.ones.used && input.twos.used && input.threes.used && input.fours.used && input.fives.used && input.sixes.used) input.uiElements.bonus.textContent = input.bonus();
    else input.uiElements.bonus.textContent = "";
    input.uiElements.totalScore.textContent = input.total();
}

// POTENIAL SCORES
function showPotential(input){
    if (!input.used) {
        input.ui.textContent = input.getScore();
        input.ui.classList.add('potential');
        input.ui.addEventListener('click', () => {
            if (!input.ui.classList.contains('potential')) return;
            input.score = input.getScore();
            input.used = true;
            document.querySelectorAll('.potential').forEach(element => {
                element.classList.remove('potential');
            });
            input.ui.textContent = input.score;
            getCurrentPlayer().scoresheet.updateUI();
            switchTurns();
        });
    }
}

// SURRENDERS THE GAME
function surrender(){
    started = false;
    players.forEach(player => {
        player.removeUI();
        players.splice(players.indexOf(player), 1);
    });
    document.querySelectorAll('.die').forEach(element => { 
        for (var i = 1; i <= 6; i++) {
            element.classList.remove('show-' + i);
        }
        if (element.classList.contains('hold')) element.classList.remove('hold');
    });
    rollTurn = 0;    
    rollsHtml.textContent = rollTurn;
    rolling = false;
    diceData = [
        1,
        2,
        3,
        4,
        5,
        6
    ];
    rounds = 0;
    document.body.classList.remove('started');
}

// GET CURRENT PLAYER
function getCurrentPlayer() {
    return players.filter(player => player.turn)[0];
}

// HOLD DICE
function holdDie(input){
    if (rolling || rollTurn === 0) return;
    input.classList.toggle('hold');
}

// ROLL DICE
function rollDice() {
    if (rolling || rollTurn >= 3) return;
    rolling = true;
    rollTurn++;
    rollsHtml.textContent = rollTurn;
    for (var i = 1; i <= 6; i++) {
        diceHtml.forEach(element => {
            if (!element.classList.contains('hold')) element.classList.remove('show-' + i);
        });        
    }
    if (rollTurn === 1) {
        for (let index = 0; index < diceHtml.length; index++) {
            const die = diceHtml[index];
            if (!die.classList.contains('hold')){            
                roll = Math.floor(Math.random() * 6) + 1;
                diceData[index] = roll;
                die.classList.add('show-' + roll);
                getCurrentPlayer().scoresheet.showPotential();            
                rolling = false;
            }
        };
    } else{
        setTimeout(() => {
            for (let index = 0; index < diceHtml.length; index++) {
                const die = diceHtml[index];
                if (!die.classList.contains('hold')){            
                    roll = Math.floor(Math.random() * 6) + 1;
                    diceData[index] = roll;
                    die.classList.add('show-' + roll);
                    getCurrentPlayer().scoresheet.showPotential();            
                    rolling = false;
                }
            };
        }, 200);
    }
    
}

// SWITCH TURNS
function switchTurns() {
    const currentPlayer = getCurrentPlayer();
    currentPlayer.ui.forEach(element => {
        element.classList.remove('currentPlayer');
    });
    currentPlayer.turn = false;
    rollTurn = 0;
    rollsHtml.textContent = rollTurn;
    if (players.indexOf(currentPlayer) === players.length - 1) {
        players[0].turn = true;
        if (++rounds === 17) {
            const winner = players.sort((a, b) => b.scoresheet.total() - a.scoresheet.total())[0];
            alert(winner.name + " won the game!");
            surrender();
            return;
        }
    }
    else {
        players[players.indexOf(currentPlayer) + 1].turn = true;
    }
    currentPlayerHtml.textContent = getCurrentPlayer().name;
    document.querySelectorAll('.die').forEach(element => { 
        for (var i = 1; i <= 6; i++) {
            element.classList.remove('show-' + i);
        }
        if (element.classList.contains('hold')) element.classList.remove('hold');
    });
    getCurrentPlayer().ui.forEach(element => {
        element.classList.add('currentPlayer');
    });
    document.querySelectorAll('.nextPlayer').forEach(element => {
        element.classList.remove('nextPlayer');
    });
    document.querySelectorAll('.previousPlayer').forEach(element => {
        element.classList.remove('previousPlayer');
    });
    highlightClosePlayers();
}

// HIGHLIGHT PLAYERS WITHIN 1 TURN
function highlightClosePlayers() {
    if (players.length === 1) return;
    const index = players.indexOf(getCurrentPlayer());
    const nextPlayer = index === players.length - 1 ? players[0] : players[index + 1];
    nextPlayer.ui.forEach(element => {
        element.classList.add('nextPlayer');
    });
    if (players.length === 2) return;
    const previousPlayer = index === 0 ? players[players.length - 1] : players[index - 1];    
    previousPlayer.ui.forEach(element => {
        element.classList.add('previousPlayer');
    });
}

// MAKE DICE SWITCH NUMBER WHILE ROLLING
function dieShuffle() {
    if (!rolling) return;
    setTimeout(() => {
        if (!rolling) return;
        for (let index = 0; index < diceHtml.length; index++) {
            const die = diceHtml[index];
            if (!die.classList.contains('hold')){
                roll = Math.floor(Math.random() * 6) + 1;
                die.textContent = roll;
            }
        }   
        dieShuffle();
    }, 100);
}