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

// touchhandler handles all touch events for the app

package touchhandler

import (
	"fmt"
	"strconv"
	"strings"

	"golang.org/x/mobile/event/touch"
	"golang.org/x/mobile/exp/sprite"

	"hearts/img/reposition"
	"hearts/img/staticimg"
	"hearts/img/uistate"
	"hearts/img/view"
	"hearts/logic/card"
	"hearts/sync"
)

func OnTouch(t touch.Event, u *uistate.UIState) {
	if t.Type == touch.TypeBegin {
		u.ViewOnTouch = u.CurView
	} else if u.CurView != u.ViewOnTouch {
		return
	}
	switch u.CurView {
	case uistate.Discovery:
		switch t.Type {
		case touch.TypeBegin:
			beginClickDiscovery(t, u)
		case touch.TypeMove:
			moveClickDiscovery(t, u)
		case touch.TypeEnd:
			endClickDiscovery(t, u)
		}
	case uistate.Arrange:
		switch t.Type {
		case touch.TypeBegin:
			beginClickArrange(t, u)
		case touch.TypeMove:
			moveClickArrange(t, u)
		case touch.TypeEnd:
			endClickArrange(t, u)
		}
	case uistate.Table:
		switch t.Type {
		case touch.TypeBegin:
			beginClickTable(t, u)
		}
	case uistate.Pass:
		switch t.Type {
		case touch.TypeBegin:
			beginClickPass(t, u)
		case touch.TypeMove:
			moveClickPass(t, u)
		case touch.TypeEnd:
			endClickPass(t, u)
		}
	case uistate.Take:
		switch t.Type {
		case touch.TypeBegin:
			beginClickTake(t, u)
		case touch.TypeMove:
			if u.CurCard != nil {
				moveClickTake(t, u)
			}
		case touch.TypeEnd:
			if u.CurCard != nil {
				endClickTake(t, u.CurCard, u)
				u.CurCard = nil
			}
		}
	case uistate.Play:
		switch t.Type {
		case touch.TypeBegin:
			beginClickPlay(t, u)
		case touch.TypeMove:
			if u.CurCard != nil {
				moveClickPlay(t, u)
			}
		case touch.TypeEnd:
			if u.CurCard != nil {
				endClickPlay(t, u.CurCard, u)
			}
		}
	case uistate.Split:
		switch t.Type {
		case touch.TypeBegin:
			beginClickSplit(t, u)
		case touch.TypeMove:
			if u.CurCard != nil {
				moveClickSplit(t, u)
			}
		case touch.TypeEnd:
			if u.CurCard != nil {
				endClickSplit(t, u.CurCard, u)
				u.CurCard = nil
			}
		}
	case uistate.Score:
		switch t.Type {
		case touch.TypeBegin:
			beginClickScore(t, u)
		case touch.TypeMove:
			moveClickScore(t, u)
		case touch.TypeEnd:
			endClickScore(t, u)
		}
	}
	u.LastMouseXY.X = t.X
	u.LastMouseXY.Y = t.Y
}

func beginClickDiscovery(t touch.Event, u *uistate.UIState) {
	buttonList := findClickedButton(t, u)
	for _, button := range buttonList {
		pressButton(button, u)
	}
}

func moveClickDiscovery(t touch.Event, u *uistate.UIState) {
	curPressed := findClickedButton(t, u)
	alreadyPressed := getPressed(u)
	if len(alreadyPressed) > 0 && len(curPressed) == 0 {
		unpressButtons(u)
	}
}

func endClickDiscovery(t touch.Event, u *uistate.UIState) {
	pressed := unpressButtons(u)
	for _, button := range pressed {
		if button == u.Buttons["newGame"] {
			gameStartData, logName := sync.CreateLogSyncgroup(u)
			settingsName := sync.CreateSettingsSyncgroup(u)
			if logName != "" && settingsName != "" {
				sync.LogSettingsName(settingsName, u)
				u.ScanChan <- true
				u.ScanChan = nil
				u.SGChan = make(chan bool)
				go sync.Advertise(logName, settingsName, gameStartData, u.SGChan, u.Ctx)
				view.LoadArrangeView(u)
			}
		} else {
			for _, b := range u.Buttons {
				if button == b {
					logAddr := b.GetInfo()
					success := sync.JoinLogSyncgroup(logAddr, u)
					if success {
						sgName := sync.CreateSettingsSyncgroup(u)
						if sgName != "" {
							sync.LogSettingsName(sgName, u)
						}
						u.ScanChan <- true
						u.ScanChan = nil
						view.LoadArrangeView(u)
					} else {
						fmt.Println("Failed to join")
					}
				}
			}
		}
	}
}

func beginClickArrange(t touch.Event, u *uistate.UIState) {
	buttonList := findClickedButton(t, u)
	for _, b := range buttonList {
		if b == u.Buttons["exit"] {
			pressButton(b, u)
		} else if b == u.Buttons["start"] {
			if u.CurTable.AllReadyForNewRound() {
				pressButton(b, u)
			}
		} else if u.CurPlayerIndex < 0 || u.Debug {
			for _, button := range u.Buttons {
				if b == button {
					pressButton(b, u)
				}
			}
		}
	}
}

func moveClickArrange(t touch.Event, u *uistate.UIState) {
	curPressed := findClickedButton(t, u)
	alreadyPressed := getPressed(u)
	if len(alreadyPressed) > 0 && len(curPressed) == 0 {
		unpressButtons(u)
	}
}

func endClickArrange(t touch.Event, u *uistate.UIState) {
	pressed := unpressButtons(u)
	for _, b := range pressed {
		if b == u.Buttons["exit"] {
			if u.SGChan != nil {
				u.SGChan <- true
				u.SGChan = nil
			}
			u.IsOwner = false
			u.DiscGroups = make(map[string]*uistate.DiscStruct)
			u.ScanChan = make(chan bool)
			go sync.ScanForSG(u.Ctx, u.ScanChan, u)
			view.LoadDiscoveryView(u)
		} else if b == u.Buttons["start"] {
			if u.CurTable.AllReadyForNewRound() {
				successStart := sync.LogGameStart(u)
				for !successStart {
					successStart = sync.LogGameStart(u)
				}
				newHands := u.CurTable.Deal()
				successDeal := sync.LogDeal(u, u.CurPlayerIndex, newHands)
				for !successDeal {
					successDeal = sync.LogDeal(u, u.CurPlayerIndex, newHands)
				}
			}
		} else {
			for key, button := range u.Buttons {
				if b == button && (u.CurPlayerIndex < 0 || u.Debug) {
					if key == "joinTable" {
						u.CurPlayerIndex = 4
						sync.LogPlayerNum(u)
					} else {
						playerNum := strings.Split(key, "-")[1]
						u.CurPlayerIndex, _ = strconv.Atoi(playerNum)
						sync.LogReady(u)
						sync.LogPlayerNum(u)
					}
				}
			}
		}
	}
}

func beginClickTable(t touch.Event, u *uistate.UIState) {
	buttonList := findClickedButton(t, u)
	if len(buttonList) > 0 {
		updateViewFromTable(buttonList[0], u)
	}
}

func beginClickPass(t touch.Event, u *uistate.UIState) {
	u.CurCard = findClickedCard(t, u)
	if u.CurCard != nil {
		reposition.BringNodeToFront(u.CurCard.GetNode(), u)
	}
	buttonList := findClickedButton(t, u)
	for _, b := range buttonList {
		if b == u.Buttons["table"] {
			view.LoadTableView(u)
		} else if b == u.Buttons["hand"] {
			view.LoadPassOrTakeOrPlay(u)
		} else if b == u.Buttons["pass"] {
			pressButton(b, u)
		}
	}
}

func moveClickPass(t touch.Event, u *uistate.UIState) {
	if u.CurCard != nil {
		reposition.DragCard(t, u)
	}
	curPressed := findClickedButton(t, u)
	alreadyPressed := getPressed(u)
	if len(alreadyPressed) > 0 && len(curPressed) == 0 {
		unpressButtons(u)
	}
}

func endClickPass(t touch.Event, u *uistate.UIState) {
	if u.CurCard != nil {
		if !dropCardOnTarget(u.CurCard, t, u) {
			// check to see if card was removed from a drop target
			removeCardFromTarget(u.CurCard, u)
			// add card back to hand
			reposition.ResetCardPosition(u.CurCard, u.Eng)
			reposition.RealignSuit(u.CurCard.GetSuit(), u.CurCard.GetInitial().Y, u)
		}
		// check to see whether pull tab should be displayed
		readyToPass := true
		for _, d := range u.DropTargets {
			if d.GetCardHere() == nil {
				readyToPass = false
			}
		}
		passButton := u.Buttons["pass"]
		if readyToPass {
			if passButton.GetDisplayingImage() {
				u.Eng.SetSubTex(passButton.GetNode(), passButton.GetImage())
				passButton.SetDisplayingImage(true)
			}
			for _, img := range u.Other {
				if img.GetDisplayingImage() {
					u.Eng.SetSubTex(img.GetNode(), img.GetAlt())
					img.SetDisplayingImage(false)
				}
			}
		} else {
			var emptyTex sprite.SubTex
			u.Eng.SetSubTex(passButton.GetNode(), emptyTex)
			passButton.SetDisplayingImage(true)
			for _, img := range u.Other {
				if !img.GetDisplayingImage() {
					u.Eng.SetSubTex(img.GetNode(), img.GetImage())
					img.SetDisplayingImage(true)
				}
			}
		}
	}
	pressed := unpressButtons(u)
	for _, p := range pressed {
		if p == u.Buttons["pass"] {
			ch := make(chan bool)
			success := passCards(ch, u.CurPlayerIndex, u)
			quit := make(chan bool)
			u.AnimChans = append(u.AnimChans, quit)
			go func() {
				onDone := func() {
					if !success {
						fmt.Println("Invalid pass")
					} else {
						view.LoadTakeView(u)
					}
				}
				reposition.SwitchOnChan(ch, quit, onDone, u)
			}()
		}
	}
	u.CurCard = nil
}

func beginClickTake(t touch.Event, u *uistate.UIState) {
	u.CurCard = findClickedCard(t, u)
	if u.CurCard != nil {
		reposition.BringNodeToFront(u.CurCard.GetNode(), u)
		u.CurCard.GetNode().Arranger = nil
	}
	buttonList := findClickedButton(t, u)
	for _, b := range buttonList {
		if b == u.Buttons["table"] {
			view.LoadTableView(u)
		} else if b == u.Buttons["hand"] {
			view.LoadPassOrTakeOrPlay(u)
		}
	}
}

func moveClickTake(t touch.Event, u *uistate.UIState) {
	reposition.DragCard(t, u)
}

func endClickTake(t touch.Event, c *card.Card, u *uistate.UIState) {
	// check to see if card was removed from a drop target
	removeCardFromTarget(c, u)
	// add card back to hand
	reposition.ResetCardPosition(c, u.Eng)
	reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
	doneTaking := true
	for _, d := range u.DropTargets {
		if d.GetCardHere() != nil {
			doneTaking = false
		}
	}
	if doneTaking {
		ch := make(chan bool)
		success := takeCards(ch, u.CurPlayerIndex, u)
		quit := make(chan bool)
		u.AnimChans = append(u.AnimChans, quit)
		go func() {
			onDone := func() {
				if !success {
					fmt.Println("Invalid take")
				} else {
					view.LoadPlayView(u)
				}
			}
			reposition.SwitchOnChan(ch, quit, onDone, u)
		}()
	}
}

func beginClickPlay(t touch.Event, u *uistate.UIState) {
	u.CurCard = findClickedCard(t, u)
	if u.CurCard != nil {
		reposition.BringNodeToFront(u.CurCard.GetNode(), u)
	}
	buttonList := findClickedButton(t, u)
	for _, b := range buttonList {
		if b == u.Buttons["toggleSplit"] && !u.SwitchingViews {
			view.LoadSplitView(false, u)
		} else if b == u.Buttons["table"] {
			view.LoadTableView(u)
		} else if b == u.Buttons["hand"] {
			view.LoadPassOrTakeOrPlay(u)
		}
	}
}

func moveClickPlay(t touch.Event, u *uistate.UIState) {
	reposition.DragCard(t, u)
}

func endClickPlay(t touch.Event, c *card.Card, u *uistate.UIState) {
	if dropCardOnTarget(c, t, u) {
		ch := make(chan bool)
		if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
			view.ChangePlayMessage(err, u)
			removeCardFromTarget(c, u)
			// add card back to hand
			reposition.ResetCardPosition(c, u.Eng)
			reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
		}
		quit := make(chan bool)
		u.AnimChans = append(u.AnimChans, quit)
		go func() {
			onDone := func() { view.LoadPlayView(u) }
			reposition.SwitchOnChan(ch, quit, onDone, u)
		}()
	} else {
		// check to see if card was removed from a drop target
		removeCardFromTarget(c, u)
		// add card back to hand
		reposition.ResetCardPosition(c, u.Eng)
		reposition.RealignSuit(c.GetSuit(), c.GetInitial().Y, u)
	}
}

func beginClickSplit(t touch.Event, u *uistate.UIState) {
	u.CurCard = findClickedCard(t, u)
	if u.CurCard != nil {
		reposition.BringNodeToFront(u.CurCard.GetNode(), u)
	}
	buttonList := findClickedButton(t, u)
	for _, b := range buttonList {
		if b == u.Buttons["toggleSplit"] && !u.SwitchingViews {
			ch := make(chan bool)
			u.SwitchingViews = true
			reposition.AnimateOutSplit(ch, u)
			quit := make(chan bool)
			u.AnimChans = append(u.AnimChans, quit)
			go func() {
				onDone := func() {
					u.SwitchingViews = false
					view.LoadPlayView(u)
				}
				reposition.SwitchOnChan(ch, quit, onDone, u)
			}()
		} else if b == u.Buttons["table"] {
			view.LoadTableView(u)
		} else if b == u.Buttons["hand"] {
			view.LoadPassOrTakeOrPlay(u)
		}
	}
}

func moveClickSplit(t touch.Event, u *uistate.UIState) {
	reposition.DragCard(t, u)
}

func endClickSplit(t touch.Event, c *card.Card, u *uistate.UIState) {
	if dropCardHere(c, u.DropTargets[0], t, u) {
		ch := make(chan bool)
		if err := playCard(ch, u.CurPlayerIndex, u); err != "" {
			view.ChangePlayMessage(err, u)
			removeCardFromTarget(c, u)
			// add card back to hand
			reposition.ResetCardPosition(c, u.Eng)
		}
	} else {
		// add card back to hand
		reposition.ResetCardPosition(c, u.Eng)
	}
}

func beginClickScore(t touch.Event, u *uistate.UIState) {
	buttonList := findClickedButton(t, u)
	for _, b := range buttonList {
		pressButton(b, u)
	}
}

func moveClickScore(t touch.Event, u *uistate.UIState) {
	curPressed := findClickedButton(t, u)
	alreadyPressed := getPressed(u)
	if len(alreadyPressed) > 0 && len(curPressed) == 0 {
		unpressButtons(u)
	}
}

func endClickScore(t touch.Event, u *uistate.UIState) {
	pressed := unpressButtons(u)
	if len(pressed) > 0 {
		success := sync.LogReady(u)
		for !success {
			sync.LogReady(u)
		}
		view.LoadWaitingView(u)
	}
}

// returns a card object if a card was clicked, or nil if no card was clicked
func findClickedCard(t touch.Event, u *uistate.UIState) *card.Card {
	// i goes from the end backwards so that it checks cards displayed on top of other cards first
	for i := len(u.Cards) - 1; i >= 0; i-- {
		c := u.Cards[i]
		if touchingCard(t, c, u) {
			return c
		}
	}
	return nil
}

// returns a button object if a button was clicked, or nil if no button was clicked
func findClickedButton(t touch.Event, u *uistate.UIState) []*staticimg.StaticImg {
	pressed := make([]*staticimg.StaticImg, 0)
	for _, b := range u.Buttons {
		if touchingStaticImg(t, b, u) {
			pressed = append(pressed, b)
		}
	}
	return pressed
}

// returns true if pass was successful
func passCards(ch chan bool, playerId int, u *uistate.UIState) bool {
	cardsPassed := make([]*card.Card, 0)
	for _, d := range u.DropTargets {
		passCard := d.GetCardHere()
		if passCard != nil {
			cardsPassed = append(cardsPassed, passCard)
		}
	}
	// if the pass is not valid, don't pass any cards
	if !u.CurTable.ValidPass(cardsPassed) || u.CurTable.GetPlayers()[playerId].GetDonePassing() {
		return false
	}
	success := sync.LogPass(u, cardsPassed)
	for !success {
		success = sync.LogPass(u, cardsPassed)
	}
	imgs := append(u.Other, u.DropTargets...)
	imgs = append(imgs, u.Buttons["pass"])
	reposition.AnimateHandCardPass(ch, imgs, u)
	return true
}

func takeCards(ch chan bool, playerId int, u *uistate.UIState) bool {
	player := u.CurTable.GetPlayers()[playerId]
	passedCards := player.GetPassedTo()
	if len(passedCards) != 3 {
		return false
	}
	success := sync.LogTake(u)
	for !success {
		success = sync.LogTake(u)
	}
	reposition.AnimateHandCardTake(ch, u.Other, u)
	return true
}

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 := sync.LogPlay(u, c)
	for !success {
		success = sync.LogPlay(u, c)
	}
	// no animation when in split view
	if u.CurView == uistate.Play {
		reposition.AnimateHandCardPlay(ch, c, u)
	}
	return ""
}

func pressButton(b *staticimg.StaticImg, u *uistate.UIState) {
	u.Eng.SetSubTex(b.GetNode(), b.GetAlt())
	b.SetDisplayingImage(false)
}

// returns buttons that were pressed
func unpressButtons(u *uistate.UIState) []*staticimg.StaticImg {
	pressed := make([]*staticimg.StaticImg, 0)
	for _, b := range u.Buttons {
		if b.GetDisplayingImage() == false {
			u.Eng.SetSubTex(b.GetNode(), b.GetImage())
			b.SetDisplayingImage(true)
			pressed = append(pressed, b)
		}
	}
	return pressed
}

// returns pressed buttons without unpressing them
func getPressed(u *uistate.UIState) []*staticimg.StaticImg {
	pressed := make([]*staticimg.StaticImg, 0)
	for _, b := range u.Buttons {
		if b.GetDisplayingImage() == false {
			pressed = append(pressed, b)
		}
	}
	return pressed
}

// checks all drop targets to see if a card was dropped there
func dropCardOnTarget(c *card.Card, t touch.Event, u *uistate.UIState) bool {
	for _, d := range u.DropTargets {
		// checking to see if card was dropped onto a drop target
		if touchingStaticImg(t, d, u) {
			lastDroppedCard := d.GetCardHere()
			if lastDroppedCard != nil {
				reposition.ResetCardPosition(lastDroppedCard, u.Eng)
				reposition.RealignSuit(lastDroppedCard.GetSuit(), lastDroppedCard.GetInitial().Y, u)
			}
			oldY := c.GetInitial().Y
			suit := c.GetSuit()
			c.Move(d.GetCurrent(), c.GetDimensions(), u.Eng)
			d.SetCardHere(c)
			// realign suit the card just left
			reposition.RealignSuit(suit, oldY, u)
			return true
		}
	}
	return false
}

// checks one specific drop target to see if a card was dropped there
func dropCardHere(c *card.Card, d *staticimg.StaticImg, t touch.Event, u *uistate.UIState) bool {
	if !touchingStaticImg(t, d, u) {
		return false
	}
	lastDroppedCard := d.GetCardHere()
	if lastDroppedCard != nil {
		reposition.ResetCardPosition(lastDroppedCard, u.Eng)
		reposition.RealignSuit(lastDroppedCard.GetSuit(), lastDroppedCard.GetInitial().Y, u)
	}
	oldY := c.GetInitial().Y
	suit := c.GetSuit()
	u.CurCard.Move(d.GetCurrent(), c.GetDimensions(), u.Eng)
	d.SetCardHere(u.CurCard)
	// realign suit the card just left
	reposition.RealignSuit(suit, oldY, u)
	return true
}

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
}

func touchingCard(t touch.Event, c *card.Card, u *uistate.UIState) bool {
	withinXBounds := t.X/u.PixelsPerPt >= c.GetCurrent().X && t.X/u.PixelsPerPt <= c.GetDimensions().X+c.GetCurrent().X
	withinYBounds := t.Y/u.PixelsPerPt >= c.GetCurrent().Y && t.Y/u.PixelsPerPt <= c.GetDimensions().Y+c.GetCurrent().Y
	return withinXBounds && withinYBounds
}

func touchingStaticImg(t touch.Event, s *staticimg.StaticImg, u *uistate.UIState) bool {
	withinXBounds := t.X/u.PixelsPerPt >= s.GetCurrent().X && t.X/u.PixelsPerPt <= s.GetDimensions().X+s.GetCurrent().X
	withinYBounds := t.Y/u.PixelsPerPt >= s.GetCurrent().Y && t.Y/u.PixelsPerPt <= s.GetDimensions().Y+s.GetCurrent().Y
	return withinXBounds && withinYBounds
}

func updateViewFromTable(b *staticimg.StaticImg, u *uistate.UIState) {
	if b == u.Buttons["player0"] {
		u.CurPlayerIndex = 0
		view.LoadPassOrTakeOrPlay(u)
	} else if b == u.Buttons["player1"] {
		u.CurPlayerIndex = 1
		view.LoadPassOrTakeOrPlay(u)
	} else if b == u.Buttons["player2"] {
		u.CurPlayerIndex = 2
		view.LoadPassOrTakeOrPlay(u)
	} else if b == u.Buttons["player3"] {
		u.CurPlayerIndex = 3
		view.LoadPassOrTakeOrPlay(u)
	} else if b == u.Buttons["table"] {
		view.LoadTableView(u)
	} else if b == u.Buttons["hand"] {
		view.LoadPassOrTakeOrPlay(u)
	}
}
