package main

import "fmt"

type GameResult int

const (
	GameOngoing GameResult = iota
	WhiteWins
	BlackWins
	Draw
)

type Game struct {
	Board   *Board
	Turn    int
	Over    bool
	Result  GameResult
	MoveNum int
}

func NewGame() *Game {
	return &Game{
		Board:   NewBoard(),
		Turn:    White,
		Over:    false,
		Result:  GameOngoing,
		MoveNum: 1,
	}
}

func (g *Game) MakeMove(input string) (string, error) {
	if g.Over {
		return "", fmt.Errorf("game is over")
	}
	m, err := g.Board.ParseMove(input)
	if err != nil {
		return "", err
	}
	s := g.Board.Grid[m.From.Row][m.From.Col]
	if s.Piece == Empty || s.Color != g.Turn {
		return "", fmt.Errorf("no %s piece on %s", colorName(g.Turn), algebraic(m.From))
	}
	legalMoves := g.Board.generateLegalMoves(g.Turn)
	found := false
	for _, lm := range legalMoves {
		if lm.From == m.From && lm.To == m.To && lm.Promotion == m.Promotion {
			found = true
			break
		}
	}
	if !found {
		return "", fmt.Errorf("illegal move: %s", input)
	}
	g.Board.MoveHistory = append(g.Board.MoveHistory, input)
	g.Board.applyMove(*m)
	if g.Turn == White {
		g.Turn = Black
		g.MoveNum++
	} else {
		g.Turn = White
	}
	oppMoves := g.Board.generateLegalMoves(g.Turn)
	if len(oppMoves) == 0 {
		g.Over = true
		if g.Board.isInCheck(g.Turn) {
			if g.Turn == White {
				g.Result = BlackWins
			} else {
				g.Result = WhiteWins
			}
		} else {
			g.Result = Draw
		}
	}
	return input, nil
}

func (g *Game) Render() string {
	out := g.Board.Display(g.Turn)
	if g.Over {
		switch g.Result {
		case WhiteWins:
			out += "\n  === CHECKMATE! WHITE WINS! ===\n"
		case BlackWins:
			out += "\n  === CHECKMATE! BLACK WINS! ===\n"
		case Draw:
			out += "\n  === STALEMATE! DRAW ===\n"
		}
	} else {
		out += fmt.Sprintf("\n  Move %d | %s to move\n", g.MoveNum, colorName(g.Turn))
	}
	return out
}

func algebraic(p Position) string {
	return string(rune('a'+p.Col)) + string(rune('0'+(8-p.Row)))
}

