// 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.

// player keeps track of all player-specific variables, as well as some basic logic functions to support more complex table logic

package player

import (
	"golang.org/x/mobile/exp/sprite"
	"hearts/logic/card"
)

// Returns a player instance with playerIndex equal to index
func NewPlayer(index int, name string, iconTex, deviceTex sprite.SubTex) *Player {
	return &Player{
		hand:              nil,
		tricks:            make([]*card.Card, 0),
		score:             0,
		playerIndex:       index,
		playerName:        name,
		playerIconImage:   iconTex,
		playerDeviceImage: deviceTex,
		donePassing:       false,
		doneTaking:        false,
		doneScoring:       false,
	}
}

type Player struct {
	hand              []*card.Card
	passedFrom        []*card.Card
	passedTo          []*card.Card
	tricks            []*card.Card
	score             int
	playerIndex       int
	playerName        string
	playerIconImage   sprite.SubTex
	playerDeviceImage sprite.SubTex
	donePassing       bool
	doneTaking        bool
	donePlaying       bool
	doneScoring       bool
}

// Returns the hand of p
func (p *Player) GetHand() []*card.Card {
	return p.hand
}

// Returns the cards that have been passed to p
func (p *Player) GetPassedTo() []*card.Card {
	return p.passedTo
}

// Returns the cards that p passed
func (p *Player) GetPassedFrom() []*card.Card {
	return p.passedFrom
}

// Returns the score of p
func (p *Player) GetScore() int {
	return p.score
}

// Returns the playerIndex of p
func (p *Player) GetPlayerIndex() int {
	return p.playerIndex
}

func (p *Player) GetName() string {
	return p.playerName
}

func (p *Player) GetIconImage() sprite.SubTex {
	return p.playerIconImage
}

func (p *Player) GetDeviceImage() sprite.SubTex {
	return p.playerDeviceImage
}

// Returns true if p has finished the pass phase of the current round
func (p *Player) GetDonePassing() bool {
	return p.donePassing
}

// Returns true if p has finished the take phase of the current round
func (p *Player) GetDoneTaking() bool {
	return p.doneTaking
}

// Returns true if p has finished the play phase of the current trick
func (p *Player) GetDonePlaying() bool {
	return p.donePlaying
}

// Returns true if p has finished the score phase of the current round
func (p *Player) GetDoneScoring() bool {
	return p.doneScoring
}

// Adds card to the hand of p
func (p *Player) AddToHand(card *card.Card) {
	p.hand = append(p.hand, card)
}

// Removes card from the hand of p, every time it appears
func (p *Player) RemoveFromHand(card *card.Card) {
	for i, c := range p.hand {
		if c == card {
			p.hand = append(p.hand[:i], p.hand[i+1:]...)
		}
	}
}

// Sets hand of p in one chunk of cards
func (p *Player) SetHand(cards []*card.Card) {
	p.hand = cards
}

// Sets passedTo of p to cards
func (p *Player) SetPassedTo(cards []*card.Card) {
	p.passedTo = cards
}

// Sets passedFrom of p to cards
func (p *Player) SetPassedFrom(cards []*card.Card) {
	p.passedFrom = cards
}

// Sets p.donePassing to isDone
func (p *Player) SetDonePassing(isDone bool) {
	p.donePassing = isDone
}

// Sets p.doneTaking to isDone
func (p *Player) SetDoneTaking(isDone bool) {
	p.doneTaking = isDone
}

// Sets p.donePlaying to isDone
func (p *Player) SetDonePlaying(isDone bool) {
	p.donePlaying = isDone
}

// Sets p.doneScoring to isDone
func (p *Player) SetDoneScoring(isDone bool) {
	p.doneScoring = isDone
}

// Adds cards to the tricks deck of p
func (p *Player) TakeTrick(cards []*card.Card) {
	p.tricks = append(p.tricks, cards...)
}

// Adds points to the total score of p
func (p *Player) UpdateScore(points int) {
	p.score += points
}

// Calculates and returns the total point value of the cards in the tricks deck of p
func (p *Player) CalculateScore() int {
	score := 0
	for _, c := range p.tricks {
		if c.GetSuit() == card.Heart {
			score += 1
		} else if c.GetSuit() == card.Spade && c.GetFace() == card.Queen {
			score += 13
		}
	}
	return score
}

// Sets the passedTo deck of p to a new empty list
func (p *Player) ResetPassedTo() {
	p.passedTo = make([]*card.Card, 0)
}

// Sets the passedFrom deck of p to a new empty list
func (p *Player) ResetPassedFrom() {
	p.passedFrom = make([]*card.Card, 0)
}

// Sets the tricks deck of p to a new empty list
func (p *Player) ResetTricks() {
	p.tricks = make([]*card.Card, 0)
}

// Resets the score of p to 0 for a new game
func (p *Player) ResetScore() {
	p.score = 0
}

// Given a suit, returns whether not there is at least one card of that suit in the hand of p
func (p *Player) HasSuit(suit card.Suit) bool {
	for _, c := range p.hand {
		if c.GetSuit() == suit {
			return true
		}
	}
	return false
}

// Returns true if p has at least one heart card in hand and no cards of any other suit
func (p *Player) HasOnlyHearts() bool {
	return !(p.HasSuit(card.Club) || p.HasSuit(card.Diamond) || p.HasSuit(card.Spade) || !p.HasSuit(card.Heart))
}

// Returns true if the hand of p doesn't contain any 0-point cards (all clubs and diamonds, and all spades aside from the queen)
func (p *Player) HasAllPoints() bool {
	for _, c := range p.hand {
		if !c.WorthPoints() {
			return false
		}
	}
	return true
}

// Returns true if p has the two of clubs in hand
func (p *Player) HasTwoOfClubs() bool {
	for _, c := range p.hand {
		if c.GetSuit() == card.Club && c.GetFace() == card.Two {
			return true
		}
	}
	return false
}
