// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// table contains and manages the logic half of the game state

package table

import (
	"golang.org/x/mobile/exp/sprite"
	"hearts/img/direction"
	"hearts/logic/card"
	"hearts/logic/player"
	"math/rand"
	"sort"
)

// Returns a table instance with player set length numPlayers
func InitializeGame(numPlayers int, texs map[string]sprite.SubTex) *Table {
	players := make([]*player.Player, 0)
	for i := 0; i < numPlayers; i++ {
		players = append(players, player.NewPlayer(i))
	}
	t := makeTable(players)
	t.GenerateClassicCards()
	t.NewRound()
	return t
}

// Given a group of players, returns a table instance with that group as its player set
func makeTable(p []*player.Player) *Table {
	return &Table{
		players:      p,
		trick:        make([]*card.Card, len(p)),
		firstPlayer:  -1,
		allCards:     nil,
		heartsBroken: false,
		firstTrick:   true,
		winCondition: 100,
		dir:          direction.None,
	}
}

type Table struct {
	// players contains all players in the game, indexed by playerIndex
	players []*player.Player
	// trick contains all cards in the current trick, indexed by the playerIndex of the player who played them
	trick []*card.Card
	// firstPlayer is the index in trick of the card played first
	firstPlayer int
	// allCards contains all 52 cards in the deck. GenerateCards() populates this
	allCards []*card.Card
	// heartsBroken returns true if a heart has been played yet in the round, otherwise false
	heartsBroken bool
	// firstTrick returns true if the current trick is the first in the round, otherwise false
	firstTrick bool
	// winCondition is the number of points needed to win the game
	// traditionally 100, could set higher or lower for longer or shorter game
	winCondition int
	// dir is the current round's passing direction
	dir direction.Direction
}

// Returns the player set of t
func (t *Table) GetPlayers() []*player.Player {
	return t.players
}

// Returns the current trick of t
func (t *Table) GetTrick() []*card.Card {
	return t.trick
}

// Returns the index in t.players and t.trick of the designated first player in the current round
func (t *Table) GetFirstPlayer() int {
	return t.firstPlayer
}

// Returns the deck of all cards stored in t
func (t *Table) GetAllCards() []*card.Card {
	return t.allCards
}

func (t *Table) GetDir() direction.Direction {
	return t.dir
}

// Sets the firstplayer variable of t to index
func (t *Table) SetFirstPlayer(index int) {
	t.firstPlayer = index
}

// Returns the index of the player whose turn it is, -1 if this cannot be determined at this time
func (t *Table) WhoseTurn() int {
	allNil := true
	for i, c := range t.trick {
		nextPlayerIndex := (i + 1) % len(t.players)
		if c != nil {
			allNil = false
			if t.trick[nextPlayerIndex] == nil {
				return nextPlayerIndex
			}
		}
	}
	if allNil {
		return t.firstPlayer
	}
	return -1
}

// This function generates a traditional deck of 52 cards, with 13 in each of the four suits
// Each card has a suit (Club, Diamond, Spade, or Heart)
// Each card also has a face from Two to Ace (Aces are high in Hearts)
func (t *Table) GenerateClassicCards() {
	cardsPerSuit := 13
	t.allCards = make([]*card.Card, 0)
	cardFaces := []card.Face{card.Two, card.Three, card.Four, card.Five, card.Six, card.Seven, card.Eight, card.Nine,
		card.Ten, card.Jack, card.Queen, card.King, card.Ace}
	for i := 0; i < cardsPerSuit; i++ {
		t.allCards = append(t.allCards, card.NewCard(cardFaces[i], card.Club))
		t.allCards = append(t.allCards, card.NewCard(cardFaces[i], card.Diamond))
		t.allCards = append(t.allCards, card.NewCard(cardFaces[i], card.Spade))
		t.allCards = append(t.allCards, card.NewCard(cardFaces[i], card.Heart))
	}
	sort.Sort(card.CardSorter(t.allCards))
}

// Given a card and the index of its player, adds that card to the appropriate spot in the current trick
func (t *Table) SetPlayedCard(c *card.Card, playerIndex int) {
	t.trick[playerIndex] = c
	if c.GetSuit() == card.Heart && !t.heartsBroken {
		t.heartsBroken = true
	}
}

// Returns true if there are exactly three cards being passed (specified by Hearts logic)
func (t *Table) ValidPass(cardsPassed []*card.Card) bool {
	return len(cardsPassed) == 3
}

// Returns whether it is valid for the player at playerIndex to play a card
func (t *Table) ValidPlayOrder(playerIndex int) bool {
	return t.WhoseTurn() == playerIndex
}

// Given a card and the index of its player, returns "" if this move was valid based on game logic
// Otherwise returns a string explaining the error
func (t *Table) ValidPlayLogic(c *card.Card, playerIndex int) string {
	validPlay := ""
	player := t.players[playerIndex]
	if t.firstPlayer == playerIndex {
		if !t.firstTrick {
			if c.GetSuit() != card.Heart || t.heartsBroken {
				return validPlay
			} else {
				if player.HasOnlyHearts() {
					return validPlay
				} else {
					return "Hearts have not been broken"
				}
			}
		} else if c.GetSuit() == card.Club && c.GetFace() == card.Two {
			return validPlay
		} else {
			return "Must open with the Two of Clubs"
		}
	} else {
		firstPlayedSuit := t.trick[t.firstPlayer].GetSuit()
		if c.GetSuit() == firstPlayedSuit || !player.HasSuit(firstPlayedSuit) {
			if !t.firstTrick {
				return validPlay
			} else if !c.WorthPoints() {
				return validPlay
			} else if player.HasAllPoints() {
				return validPlay
			} else {
				return "Point cards not allowed in the first round"
			}
		} else {
			return "Must follow suit"
		}
	}
}

// Returns true if all players have their initial dealt hands
func (t *Table) AllDoneDealing() bool {
	for _, p := range t.players {
		if len(p.GetHand()) == 0 {
			return false
		}
	}
	return true
}

// Returns true if all players have passed cards
func (t *Table) AllDonePassing() bool {
	for _, p := range t.players {
		if !p.GetDonePassing() {
			return false
		}
	}
	return true
}

// Returns true if all players have taken the cards passed to them
func (t *Table) AllDoneTaking() bool {
	for _, p := range t.players {
		if !p.GetDoneTaking() {
			return false
		}
	}
	return true
}

// Returns true if all players have finished looking at their scores
func (t *Table) AllReadyForNewRound() bool {
	for _, p := range t.players {
		if !p.GetDoneScoring() {
			return false
		}
	}
	return true
}

// Returns true if all players have played a card in the current trick
func (t *Table) TrickOver() bool {
	for _, c := range t.trick {
		if c == nil {
			return false
		}
	}
	return true
}

// Returns true if no players have played a card in the current trick
func (t *Table) TrickNew() bool {
	for _, c := range t.trick {
		if c != nil {
			return false
		}
	}
	return true
}

// Returns true if all players are out of cards, indicating the end of a round
func (t *Table) RoundOver() bool {
	for _, p := range t.players {
		if len(p.GetHand()) > 0 {
			return false
		}
	}
	return true
}

// Calculates who should take the cards in the current trick
// Returns -1 if trick is incomplete
func (t *Table) GetTrickRecipient() int {
	if t.firstPlayer < 0 || t.firstPlayer >= len(t.players) || t.trick[t.firstPlayer] == nil {
		return -1
	}
	trickSuit := t.trick[t.firstPlayer].GetSuit()
	highestCardFace := card.Two
	highestIndex := -1
	for i := 0; i < len(t.trick); i++ {
		curCard := t.trick[i]
		if curCard == nil {
			return -1
		}
		if curCard.GetSuit() == trickSuit && curCard.GetFace() >= highestCardFace {
			highestCardFace = curCard.GetFace()
			highestIndex = i
		}
	}
	return highestIndex
}

// Sends cards to recipient. Sets next first player accordingly. Returns true if the round is over
func (t *Table) SendTrick(recipient int) bool {
	// resets all players' donePlaying bools
	for _, p := range t.players {
		p.SetDonePlaying(false)
	}
	// clear trick
	t.players[recipient].TakeTrick(t.trick)
	t.trick = make([]*card.Card, len(t.players))
	if t.firstTrick {
		t.firstTrick = false
	}
	if t.RoundOver() {
		return true
	}
	// set first player for next trick to whoever received the current trick
	t.SetFirstPlayer(recipient)
	return false
}

// Returns the score of the current round
// Accounts for a player possibly shooting the moon
func (t *Table) ScoreRound() []int {
	allPoints := 26
	roundScores := make([]int, len(t.players))
	shotMoon := false
	shooter := -1
	for i := 0; i < len(t.players); i++ {
		roundScores[i] = t.players[i].CalculateScore()
		if roundScores[i] == allPoints {
			shotMoon = true
			shooter = i
		}
	}
	if shotMoon {
		for i := 0; i < len(t.players); i++ {
			if i == shooter {
				roundScores[i] = 0
			} else {
				roundScores[i] = allPoints
			}
		}
	}
	return roundScores
}

// Adds the scores of the current round to the players total scores
func (t *Table) UpdatePlayerScores(roundScores []int) {
	for i := 0; i < len(t.players); i++ {
		t.players[i].UpdateScore(roundScores[i])
	}
}

// Returns set of hands with random, even card distribution
func (t *Table) Deal() [][]*card.Card {
	numPlayers := len(t.players)
	allHands := make([][]*card.Card, numPlayers)
	shuffle := rand.Perm(len(t.allCards))
	for i := 0; i < len(t.allCards); i++ {
		allHands[i%numPlayers] = append(allHands[i%numPlayers], t.allCards[shuffle[i]])
	}
	return allHands
}

// Returns an array of the current round's scores, and an array of the game winners
// The winners array is empty if the game hasn't been won yet, contains all playerIndices of the winners if it has
func (t *Table) EndRound() ([]int, []int) {
	roundScores := t.ScoreRound()
	t.UpdatePlayerScores(roundScores)
	lowestScore := -1
	winningPlayers := make([]int, 0)
	winTriggered := false
	t.dir = (t.dir + 1) % 4
	for _, p := range t.players {
		p.ResetTricks()
		if p.GetScore() >= t.winCondition {
			winTriggered = true
		}
		if p.GetScore() < lowestScore || lowestScore == -1 {
			lowestScore = p.GetScore()
		}
	}
	if winTriggered {
		for _, p := range t.players {
			if p.GetScore() == lowestScore {
				winningPlayers = append(winningPlayers, p.GetPlayerIndex())
			}
		}
	}
	return roundScores, winningPlayers
}

// Resets stats for a new round of the game
func (t *Table) NewRound() {
	t.heartsBroken = false
	t.firstTrick = true
	players := t.GetPlayers()
	for _, p := range players {
		if t.dir != direction.None {
			p.SetDonePassing(false)
			p.SetDoneTaking(false)
			t.SetFirstPlayer(-1)
		} else {
			p.SetDonePassing(true)
			p.SetDoneTaking(true)
			if p.HasTwoOfClubs() {
				t.SetFirstPlayer(p.GetPlayerIndex())
			}
		}
		p.SetDoneScoring(false)
	}
}

// Resets table for start of new game
func (t *Table) NewGame() {
	for _, p := range t.players {
		p.ResetPassedTo()
		p.ResetPassedFrom()
		p.ResetTricks()
		p.ResetScore()
	}
	t.NewRound()
	t.dir = direction.Right
}
