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

import (
	"encoding/json"
	"fmt"
	"golang.org/x/mobile/exp/sprite"
	"hearts/img/direction"
	"hearts/img/reposition"
	"hearts/img/uistate"
	"hearts/img/view"
	"hearts/logic/card"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"
	"v.io/v23/syncbase/nosql"
)

func UpdateSettings(u *uistate.UIState) {
	scanner := ScanData(SettingsName, "users", u)
	for {
		if updateExists := scanner.Advance(); updateExists {
			key := scanner.Key()
			var value []byte
			if err := scanner.Value(&value); err != nil {
				fmt.Println("Value error:", err)
			}
			handleSettingsUpdate(key, value, u)
		} else {
			break
		}
	}
	stream, err := WatchData(SettingsName, "users", u)
	if err != nil {
		fmt.Println("WatchData error:", err)
	} else {
		for {
			if updateExists := stream.Advance(); updateExists {
				c := stream.Change()
				if c.ChangeType == nosql.PutChange {
					key := c.Row
					var value []byte
					if err := c.Value(&value); err != nil {
						fmt.Println("Value error:", err)
					}
					handleSettingsUpdate(key, value, u)
				} else {
					fmt.Println("Unexpected ChangeType: ", c.ChangeType)
				}
			}
		}
	}
}

func handleSettingsUpdate(key string, value []byte, u *uistate.UIState) {
	var valueMap map[string]interface{}
	err := json.Unmarshal(value, &valueMap)
	if err != nil {
		fmt.Println("Unmarshal error:", err)
	}
	userID, _ := strconv.Atoi(strings.Split(key, "/")[1])
	u.UserData[userID] = valueMap
	for _, v := range u.PlayerData {
		if v == userID {
			view.ReloadView(u)
		}
	}
	if u.CurView == uistate.Discovery {
		view.LoadDiscoveryView(u)
	}
}

func UpdateGame(u *uistate.UIState) {
	stream, err := WatchData(LogName, fmt.Sprintf("%d", u.GameID), u)
	fmt.Println("STARTING WATCH FOR GAME", u.GameID)
	if err != nil {
		fmt.Println("WatchData error:", err)
	}
	file, err2 := os.OpenFile("/sdcard/test.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err2 != nil {
		fmt.Println("err2:", err2)
	}
	fmt.Fprintf(file, fmt.Sprintf("\n***NEW GAME: %d\n", u.GameID))
	defer file.Close()
	updateBlock := make([]nosql.WatchChange, 0)
	for {
		if updateExists := stream.Advance(); updateExists {
			c := stream.Change()
			updateBlock = append(updateBlock, c)
			if !c.Continued {
				sort.Sort(updateSorter(updateBlock))
				handleGameUpdate(file, updateBlock, u)
				updateBlock = make([]nosql.WatchChange, 0)
			}
		}
	}
}

func handleGameUpdate(file *os.File, changes []nosql.WatchChange, u *uistate.UIState) {
	for _, c := range changes {
		if c.ChangeType == nosql.PutChange {
			key := c.Row
			curTime := time.Now().UnixNano() / 1000000
			var value []byte
			if err := c.Value(&value); err != nil {
				fmt.Println("Value error:", err)
			}
			valueStr := string(value)
			fmt.Fprintf(file, fmt.Sprintf("key: %s\n", key))
			fmt.Fprintf(file, fmt.Sprintf("value: %s\n", valueStr))
			fmt.Fprintf(file, fmt.Sprintf("time: %v\n", curTime))
			tmp := strings.Split(key, "/")
			if len(tmp) == 3 {
				keyTime, _ := strconv.ParseInt(strings.Split(tmp[2], "-")[0], 10, 64)
				fmt.Fprintf(file, fmt.Sprintf("diff: %d milliseconds\n\n", curTime-keyTime))
			} else {
				fmt.Fprintf(file, "\n")
			}
			fmt.Println(key, valueStr)
			keyType := strings.Split(key, "/")[1]
			switch keyType {
			case "log":
				updateType := strings.Split(valueStr, "|")[0]
				switch updateType {
				case Deal:
					onDeal(valueStr, u)
				case Pass:
					onPass(valueStr, u)
				case Take:
					onTake(valueStr, u)
				case Play:
					onPlay(valueStr, u)
				case TakeTrick:
					onTakeTrick(valueStr, u)
				case Ready:
					onReady(valueStr, u)
				}
			case "players":
				switch strings.Split(key, "/")[3] {
				case "player_number":
					onPlayerNum(key, valueStr, u)
				case "settings_sg":
					onSettings(key, valueStr, u)
				}

			}
		} else {
			fmt.Println("Unexpected ChangeType: ", c.ChangeType)
		}
	}
}

func onPlayerNum(key, value string, u *uistate.UIState) {
	userID, _ := strconv.Atoi(strings.Split(key, "/")[2])
	playerNum, _ := strconv.Atoi(value)
	if playerNum >= 0 && playerNum < 4 {
		u.PlayerData[playerNum] = userID
		u.CurTable.GetPlayers()[playerNum].SetDoneScoring(true)
	}
	if playerNum == u.CurPlayerIndex && userID != UserID {
		u.CurPlayerIndex = -1
	}
	if u.CurView == uistate.Arrange {
		view.LoadArrangeView(u)
		if u.CurTable.AllReadyForNewRound() && u.IsOwner {
			b := u.Buttons["start"]
			u.Eng.SetSubTex(b.GetNode(), b.GetImage())
			b.SetDisplayingImage(true)
			if u.SGChan != nil {
				u.SGChan <- true
				u.SGChan = nil
			}
		}
	}
}

func onSettings(key, value string, u *uistate.UIState) {
	JoinSettingsSyncgroup(value, u)
}

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()
		if u.CurPlayerIndex >= 0 && u.CurPlayerIndex < u.NumPlayers {
			view.LoadPassOrTakeOrPlay(u)
		} else {
			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)
	}
	u.CurTable.GetPlayers()[playerInt].SetPassedFrom(curCards)
	u.CurTable.GetPlayers()[receivingPlayer].SetPassedTo(curCards)
	u.CurTable.GetPlayers()[playerInt].SetDonePassing(true)
	// UI
	if u.CurView == uistate.Table {
		quit := make(chan bool)
		u.AnimChans = append(u.AnimChans, quit)
		reposition.AnimateTableCardPass(curCards, receivingPlayer, quit, u)
		view.LoadTableView(u)
	} else if u.CurView == uistate.Take {
		if u.SequentialPhases {
			if u.CurTable.AllDonePassing() {
				view.LoadTakeView(u)
			}
		} else if u.CurPlayerIndex == receivingPlayer {
			view.LoadTakeView(u)
		}
	} else if u.CurView == uistate.Play && u.CurTable.AllDonePassing() {
		view.LoadPlayView(true, 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.SequentialPhases {
		if u.CurTable.AllDoneTaking() {
			for _, player := range u.CurTable.GetPlayers() {
				if player.HasTwoOfClubs() {
					u.CurTable.SetFirstPlayer(player.GetPlayerIndex())
				}
			}
			// UI
			if u.CurView == uistate.Play {
				view.LoadPlayView(true, u)
			}
		}
	} else if p.HasTwoOfClubs() {
		u.CurTable.SetFirstPlayer(p.GetPlayerIndex())
		// UI
		if u.CurView == uistate.Play && u.CurPlayerIndex != playerInt {
			view.LoadPlayView(true, u)
		}
	}
	// UI
	if u.CurView == uistate.Table {
		quit := make(chan bool)
		u.AnimChans = append(u.AnimChans, quit)
		reposition.AnimateTableCardTake(passed, u.CurTable.GetPlayers()[playerInt], quit, u)
		view.LoadTableView(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)
	trickOver := u.CurTable.TrickOver()
	var recipient int
	if trickOver {
		recipient = u.CurTable.GetTrickRecipient()
	}
	// UI
	if u.CurView == uistate.Table {
		quit := make(chan bool)
		u.AnimChans = append(u.AnimChans, quit)
		reposition.AnimateTableCardPlay(playedCard, playerInt, quit, u)
		reposition.SetTableDropColors(u)
		if trickOver {
			// display take trick button
			b := u.Buttons["takeTrick"]
			u.Eng.SetSubTex(b.GetNode(), b.GetImage())
		}
	} else if u.CurView == uistate.Split {
		if playerInt != u.CurPlayerIndex {
			quit := make(chan bool)
			u.AnimChans = append(u.AnimChans, quit)
			reposition.AnimateSplitCardPlay(playedCard, playerInt, quit, u)
		}
		reposition.SetSplitDropColors(u)
		view.LoadSplitView(true, u)
		if trickOver {
			if recipient == u.CurPlayerIndex {
				// display take trick button
				b := u.Buttons["takeTrick"]
				u.Eng.SetSubTex(b.GetNode(), b.GetImage())
			}
		} else if u.CardToPlay != nil && u.CurTable.WhoseTurn() == u.CurPlayerIndex {
			ch := make(chan bool)
			if err := PlayCard(ch, u.CurPlayerIndex, u); err != "" {
				view.ChangePlayMessage(err, u)
				RemoveCardFromTarget(u.CardToPlay, u)
				// add card back to hand
				reposition.ResetCardPosition(u.CardToPlay, u.Eng)
			}
			u.CardToPlay = nil
			u.BackgroundImgs[0].GetNode().Arranger = nil
			var emptyTex sprite.SubTex
			u.Eng.SetSubTex(u.BackgroundImgs[0].GetNode(), emptyTex)
		}
	} else if u.CurView == uistate.Play && u.CurPlayerIndex != playerInt {
		view.LoadPlayView(true, u)
		if u.CardToPlay != nil && u.CurTable.WhoseTurn() == u.CurPlayerIndex {
			ch := make(chan bool)
			if err := PlayCard(ch, u.CurPlayerIndex, u); err != "" {
				view.ChangePlayMessage(err, u)
				RemoveCardFromTarget(u.CardToPlay, u)
				// add card back to hand
				reposition.ResetCardPosition(u.CardToPlay, u.Eng)
				reposition.RealignSuit(u.CardToPlay.GetSuit(), u.CardToPlay.GetInitial().Y, u)
			}
			u.CardToPlay = nil
			quit := make(chan bool)
			u.AnimChans = append(u.AnimChans, quit)
			go func() {
				onDone := func() {
					if u.CurView == uistate.Play {
						view.LoadPlayView(true, u)
					}
				}
				reposition.SwitchOnChan(ch, quit, onDone, u)
			}()
		}
	}
}

func onTakeTrick(value string, u *uistate.UIState) {
	trickCards := u.CurTable.GetTrick()
	recipient := u.CurTable.GetTrickRecipient()
	roundOver := u.CurTable.SendTrick(recipient)
	if roundOver {
		u.RoundScores, u.Winners = u.CurTable.EndRound()
	}
	// UI
	if u.CurView == uistate.Table {
		var emptyTex sprite.SubTex
		u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
		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
		}
		quit := make(chan bool)
		u.AnimChans = append(u.AnimChans, quit)
		reposition.AnimateTableCardTakeTrick(trickCards, trickDir, quit, u)
		reposition.SetTableDropColors(u)
		view.SetNumTricksTable(u)
	} else if u.CurView == uistate.Split {
		var emptyTex sprite.SubTex
		u.Eng.SetSubTex(u.Buttons["takeTrick"].GetNode(), emptyTex)
		if roundOver {
			view.LoadScoreView(u)
		} else {
			var trickDir direction.Direction
			switch recipient {
			case u.CurPlayerIndex:
				trickDir = direction.Down
			case (u.CurPlayerIndex + 1) % u.NumPlayers:
				trickDir = direction.Left
			case (u.CurPlayerIndex + 2) % u.NumPlayers:
				trickDir = direction.Across
			case (u.CurPlayerIndex + 3) % u.NumPlayers:
				trickDir = direction.Right
			}
			quit := make(chan bool)
			u.AnimChans = append(u.AnimChans, quit)
			reposition.AnimateTableCardTakeTrick(trickCards, trickDir, quit, u)
			view.LoadSplitView(true, u)
		}
	} else if u.CurView == uistate.Play {
		if roundOver {
			view.LoadScoreView(u)
		} else {
			view.LoadPlayView(true, u)
		}
	}
	// logic
	if len(u.Winners) > 0 {
		u.CurTable.NewGame()
	}
}

func onReady(value string, u *uistate.UIState) {
	// logic
	playerInt, _ := parsePlayerAndCards(value, u)
	u.CurTable.GetPlayers()[playerInt].SetDoneScoring(true)
	// UI
	if u.CurTable.AllReadyForNewRound() && u.IsOwner {
		if u.CurView == uistate.Arrange {
			b := u.Buttons["start"]
			u.Eng.SetSubTex(b.GetNode(), b.GetImage())
			b.SetDisplayingImage(true)
			if u.SGChan != nil {
				u.SGChan <- true
				u.SGChan = nil
			}
		} else if u.CurView == uistate.Score {
			newHands := u.CurTable.Deal()
			successDeal := LogDeal(u, u.CurPlayerIndex, newHands)
			for !successDeal {
				successDeal = LogDeal(u, u.CurPlayerIndex, newHands)
			}
		}
	}
}

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
}

// Used to sort an array of watch changes
type updateSorter []nosql.WatchChange

// Returns the length of the array
func (us updateSorter) Len() int {
	return len(us)
}

// Swaps the positions of two changes in the array
func (us updateSorter) Swap(i, j int) {
	us[i], us[j] = us[j], us[i]
}

// Compares two changes-- one card is less than another if it has an earlier timestamp
func (us updateSorter) Less(i, j int) bool {
	iKey := us[i].Row
	jKey := us[j].Row
	return iKey < jKey
}

func PlayCard(ch chan bool, playerId int, u *uistate.UIState) string {
	c := u.DropTargets[0].GetCardHere()
	if c == nil {
		return "No card has been played"
	}
	// checks to make sure that:
	// -player has not already played a card this round
	// -all players have passed cards
	// -the play is in the right order
	// -the play is valid given game logic
	if u.CurTable.GetPlayers()[playerId].GetDonePlaying() {
		return "You have already played a card in this trick"
	}
	if !u.CurTable.AllDonePassing() {
		return "Not all players have passed their cards"
	}
	if !u.CurTable.ValidPlayOrder(playerId) {
		return "It is not your turn"
	}
	if err := u.CurTable.ValidPlayLogic(c, playerId); err != "" {
		return err
	}
	success := LogPlay(u, c)
	for !success {
		success = LogPlay(u, c)
	}
	// no animation when in split view
	if u.CurView == uistate.Play {
		reposition.AnimateHandCardPlay(ch, c, u)
	}
	return ""
}

func RemoveCardFromTarget(c *card.Card, u *uistate.UIState) bool {
	for _, d := range u.DropTargets {
		if d.GetCardHere() == c {
			d.SetCardHere(nil)
			return true
		}
	}
	return false
}
