package main

import (
	"github.com/nsf/termbox-go"
	"runtime"
)

type KeyInput struct {
	stopped      bool
	chanStop     chan struct{}
	chanKeyInput chan *termbox.Event
}

func NewKeyInput() *KeyInput {
	return &KeyInput{
		chanStop:     make(chan struct{}, 1),
		chanKeyInput: make(chan *termbox.Event, 8),
	}
}

func (keyInput *KeyInput) Run() {
	logger.Info("KeyInput Run start")

loop:
	for {
		select {
		case <-keyInput.chanStop:
			break loop
		default:
		}
		event := termbox.PollEvent()
		if event.Type == termbox.EventKey {
			select {
			case <-keyInput.chanStop:
				break loop
			default:
				select {
				case keyInput.chanKeyInput <- &event:
				case <-keyInput.chanStop:
					break loop
				}
			}
		}
	}

	logger.Info("KeyInput Run end")
}

func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {

	if event.Key == termbox.KeyCtrlI {
		// ctrl i to log stack trace
		buffer := make([]byte, 1<<16)
		length := runtime.Stack(buffer, true)
		logger.Debug("Stack trace", "buffer", string(buffer[:length]))
		return
	}

	if event.Ch == 'q' || event.Key == termbox.KeyCtrlC {
		if !keyInput.stopped {
			keyInput.stopped = true
			close(keyInput.chanStop)
		}
		engine.Stop()
		return
	}

	if engine.gameOver {
		if event.Key == termbox.KeySpace {
			engine.NewGame()
		}
		return
	}

	if engine.paused {
		if event.Ch == 'p' {
			engine.UnPause()
		}
		return
	}

	if engine.aiEnabled {
		switch event.Ch {
		case 'p':
			engine.Pause()
		case 'i':
			engine.DisableAi()
		}
		return
	}

	if event.Ch == 0 {
		switch event.Key {
		case termbox.KeySpace:
			board.MinoDrop()
		case termbox.KeyArrowUp:
			board.MinoDrop()
		case termbox.KeyArrowDown:
			board.MinoMoveDown()
		case termbox.KeyArrowLeft:
			board.MinoMoveLeft()
		case termbox.KeyArrowRight:
			board.MinoMoveRight()
		}
	} else {
		switch event.Ch {
		case 'z':
			board.MinoRotateLeft()
		case 'x':
			board.MinoRotateRight()
		case 'p':
			engine.Pause()
		case 'i':
			engine.EnabledAi()
		}
	}

}