package main

import (
	"log"
	"time"

	"github.com/gdamore/tcell/v2"
)

func initilize() (tcell.Screen, tcell.Style, error) {
	style := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)

	var err error

	screen, err := tcell.NewScreen()
	if err != nil {
		log.Println("Error creating screen: ", err)
	}
	err = screen.Init()
	if err != nil {
		log.Fatalln("Error initializing screen: ", err)
	}
	return screen, style, err
}

func quit(screen tcell.Screen) {
	maybePanic := recover()
	screen.Fini()
	if maybePanic != nil {
		panic(maybePanic)
	}
}

func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, gamestate chan int) {

	// Destined to die, even before I was born.
	defer quit(screen)

	var score int = 0
	var scoreCounter int = 1

	// Board size
	var screenx = 80
	var screeny = 24

	// Have snake start at the center of the board
	var snakex int = (screenx / 2) - 1
	var snakey int = (screeny / 2) - 1

	// Last direction we went in
	var lastpress int = 1

	var snake Snake = initSnake(&snakex, &snakey)
	var apple Apple = placeApple(&snake)

	for {

		// Take input or sleep
		select {
		case press := <-keypresses:
			if validateDirection(&snake, press) {
				snakeDirection(press, &snake)
				lastpress = press
			}
		case <-time.After(500 * time.Millisecond):
			snakeDirection(lastpress, &snake)
		}

		if snake.head.x == apple.x && snake.head.y == apple.y {
			apple = placeApple(&snake)
			score += scoreCounter
			scoreCounter++
			snake.length = 3 + score
		}

		// Call it quits once the snake hits the border.
		if snake.head.x == 0 || snake.head.x == screenx-1 {
			close(gamestate)
			return
		} else if snake.head.y == 0 || snake.head.y == screeny-1 {
			close(gamestate)
			return
		}

		// Check if head intersects with any parts of the body
		if hitsTail(&snake, snake.head.x, snake.head.y) {
			close(gamestate)
			return
		}

		// Clean the screen
		screen.Clear()

		// Draw the screen
		drawBox(screen, style, 0, 0, screenx-1, screeny-1)
		//drawCoords(screen, style, &snake)
		drawApple(screen, style, &apple)
		drawSnake(screen, style, &snake)
		drawScore(screen, style, score)

		// Draw the screen
		screen.Show()

	}

}

func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan int) {
	defer close(keypresses)

	for {

		// Poll for an event
		ev := screen.PollEvent()

		// Fetch the type, and check if any other actions are required.
		switch ev := ev.(type) {
		case *tcell.EventKey:
			if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
				return
			} else if ev.Rune() == 'q' || ev.Rune() == 'Q' {
				return
			} else if ev.Key() == tcell.KeyCtrlL {
				screen.Sync()
			} else if ev.Rune() == 'C' || ev.Rune() == 'c' {
				screen.Clear()
			} else if ev.Key() == tcell.KeyLeft {
				keypresses <- Left
			} else if ev.Key() == tcell.KeyRight {
				keypresses <- Right
			} else if ev.Key() == tcell.KeyDown {
				keypresses <- Down
			} else if ev.Key() == tcell.KeyUp {
				keypresses <- Up
			}
		}

		// This function needs to know if the game is over.
		select {
		case <-time.After(10 * time.Millisecond):
		case _, ok := <-gamestate:
			if !ok {
				return
			}
		}

	}

}