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

// watch.go holds all code to handle updates to the syncbase gamelog.
// Update() is to be run as a goroutine, getting a watchstream from
// the syncgroup and updating the game state and UI display as a result
// of any changes that come along.

package watch

import (
	"fmt"
	"hearts/img/direction"
	"hearts/img/reposition"
	"hearts/img/uistate"
	"hearts/img/view"
	"hearts/logic/card"
	"hearts/syncbase/client"
	"hearts/syncbase/gamelog"
	"strconv"
	"strings"
	"v.io/v23/syncbase/nosql"
)

func Update(u *uistate.UIState) {
	stream, err := client.WatchData(u)
	if err != nil {
		fmt.Println("WatchData error:", err)
	}
	for {
		if updateExists := stream.Advance(); updateExists {
			c := stream.Change()
			if c.ChangeType == nosql.PutChange {
				var value string
				if err := c.Value(&value); err != nil {
					fmt.Println("Value error:", err)
				}
				updateType := strings.Split(value, "|")[0]
				switch updateType {
				case gamelog.Deal:
					onDeal(value, u)
				case gamelog.Pass:
					onPass(value, u)
				case gamelog.Take:
					onTake(value, u)
				case gamelog.Play:
					onPlay(value, u)
				case gamelog.Ready:
					onReady(value, u)
				}
			} else {
				fmt.Println("Unexpected ChangeType: ", c.ChangeType)
			}
		}
	}
}

func onDeal(value string, u *uistate.UIState) {
	playerInt, curCards := parsePlayerAndCards(value, u)
	u.CurTable.GetPlayers()[playerInt].SetHand(curCards)
	if u.CurTable.AllDoneDealing() {
		u.CurTable.NewRound()
		view.LoadTableView(u)
	}
}

func onPass(value string, u *uistate.UIState) {
	// logic
	playerInt, curCards := parsePlayerAndCards(value, u)
	var receivingPlayer int
	switch u.CurTable.GetDir() {
	case direction.Right:
		receivingPlayer = (playerInt + 3) % u.NumPlayers
	case direction.Left:
		receivingPlayer = (playerInt + 1) % u.NumPlayers
	case direction.Across:
		receivingPlayer = (playerInt + 2) % u.NumPlayers
	}
	for _, c := range curCards {
		u.CurTable.GetPlayers()[playerInt].RemoveFromHand(c)
	}
	if u.CurPlayerIndex >= 0 {
		u.Cards = u.CurTable.GetPlayers()[u.CurPlayerIndex].GetHand()
	}
	u.CurTable.GetPlayers()[playerInt].SetPassedFrom(curCards)
	u.CurTable.GetPlayers()[receivingPlayer].SetPassedTo(curCards)
	u.CurTable.GetPlayers()[playerInt].SetDonePassing(true)
	// UI
	if u.CurView == uistate.Table {
		for i, c := range curCards {
			reposition.AnimateTableCardPass(c, receivingPlayer, i, u)
		}
	}
}

func onTake(value string, u *uistate.UIState) {
	// logic
	playerInt, _ := parsePlayerAndCards(value, u)
	p := u.CurTable.GetPlayers()[playerInt]
	passed := p.GetPassedTo()
	for _, c := range passed {
		p.AddToHand(c)
	}
	u.CurTable.GetPlayers()[playerInt].SetDoneTaking(true)
	if u.CurPlayerIndex >= 0 {
		u.Cards = u.CurTable.GetPlayers()[u.CurPlayerIndex].GetHand()
	}
	if p.HasTwoOfClubs() {
		u.CurTable.SetFirstPlayer(p.GetPlayerIndex())
	}
	// UI
	if u.CurView == uistate.Table {
		for i, c := range passed {
			reposition.AnimateTableCardTake(c, i, u.CurTable.GetPlayers()[playerInt])
		}
	} else if u.CurPlayerIndex == playerInt {
		//view.LoadPassOrTakeOrPlay(u)
	}
}

func onPlay(value string, u *uistate.UIState) {
	// logic
	playerInt, curCards := parsePlayerAndCards(value, u)
	playedCard := curCards[0]
	u.CurTable.GetPlayers()[playerInt].RemoveFromHand(playedCard)
	u.CurTable.SetPlayedCard(playedCard, playerInt)
	u.CurTable.GetPlayers()[playerInt].SetDonePlaying(true)
	if u.CurPlayerIndex >= 0 {
		u.Cards = u.CurTable.GetPlayers()[u.CurPlayerIndex].GetHand()
	}
	trickOver := true
	trickCards := u.CurTable.GetTrick()
	for _, c := range trickCards {
		if c == nil {
			trickOver = false
		}
	}
	roundOver := false
	var recipient int
	if trickOver {
		roundOver, recipient = u.CurTable.SendTrick()
	}
	var winners []int
	if roundOver {
		winners = u.CurTable.EndRound()
	}
	// UI
	if u.CurView == uistate.Table {
		c := make(chan bool)
		go reposition.AnimateTableCardPlay(c, playedCard, playerInt, u)
		<-c
		if trickOver {
			var trickDir direction.Direction
			switch recipient {
			case 0:
				trickDir = direction.Down
			case 1:
				trickDir = direction.Left
			case 2:
				trickDir = direction.Across
			case 3:
				trickDir = direction.Right
			}
			for _, c := range trickCards {
				ch := make(chan bool)
				reposition.AnimateTableCardTakeTrick(ch, c, trickDir, u)
				<-ch
			}
		}
	} else if u.CurView == uistate.Play && roundOver {
		view.LoadScoreView(winners, u)
	}
	// logic
	if len(winners) > 0 {
		u.CurTable.NewGame()
	}
}

func onReady(value string, u *uistate.UIState) {
	// logic
	playerInt, _ := parsePlayerAndCards(value, u)
	u.CurTable.GetPlayers()[playerInt].SetDoneScoring(true)
	if u.CurTable.AllReadyForNewRound() {
		newHands := u.CurTable.Deal()
		success := gamelog.LogDeal(u, playerInt, newHands)
		for !success {
			success = gamelog.LogDeal(u, playerInt, newHands)
		}
	}
	// UI
	if playerInt == u.CurPlayerIndex {
		view.LoadTableView(u)
	}
}

func parsePlayerAndCards(value string, u *uistate.UIState) (int, []*card.Card) {
	updateContents := strings.Split(value, "|")[1]
	playerIntPlusCards := strings.Split(updateContents, ":")
	playerInt, _ := strconv.Atoi(playerIntPlusCards[0])
	cardList := u.CurTable.GetAllCards()
	curCards := make([]*card.Card, 0)
	for i := 1; i < len(playerIntPlusCards)-1; i++ {
		cardInfo := playerIntPlusCards[i]
		cardSuitFace := strings.Split(cardInfo, " ")[1]
		cardSuit := card.ConvertToSuit(string(cardSuitFace[0]))
		cardFace := card.ConvertToFace(string(cardSuitFace[1:]))
		cardIndex := int(cardSuit*13) + int(cardFace) - 2
		curCards = append(curCards, cardList[cardIndex])
	}
	return playerInt, curCards
}
