// package app -- главный объект приложения
package app

import (
	"fmt"

	"github.com/gdamore/tcell"

	"p78git.ddns.net/svi/libtui/alias"
	"p78git.ddns.net/svi/libtui/screen"
	"p78git.ddns.net/svi/libtui/types"
)

// App -- объектприложения
type App struct {
	screen types.IScreen // Объект приложения
	scr    tcell.Screen  // Библиотечный экран
}

// NewApp -- возвращает новый объект приложения
func NewApp() (*App, error) {
	sf := &App{}
	var err error
	sf.scr, err = tcell.NewScreen()
	if err != nil {
		return nil, fmt.Errorf("NewApp(): in create tcell.Screen, err=\n\t%w", err)
	}
	sf.screen, err = screen.NewScreen(sf)
	if err != nil {
		return nil, fmt.Errorf("NewApp(): i create IScreen, err=\n\t%w", err)
	}
	return sf, nil
}

// Screen -- возвращает объект экрана
func (sf *App) Screen() types.IScreen {
	return sf.screen
}

// Run -- запускает объект приложения в работу
func (sf *App) Run() error {
	defer func() {
		sf.scr.Fini() // Завершить работу с экраном
	}()
	if err := sf.run_init(); err != nil {
		return fmt.Errorf("App.Run(): ininit screen, err=\n\t%w", err)
	}
	sf.screen.Clear()
	sf.screen.Draw()// sf.scr.Show()  // Обновить экран
	sf.scr.EnableMouse()
	for { // Главный цикл работы
		ev := sf.scr.PollEvent() // Получить событие

		// Process event
		switch ev := ev.(type) {
		case *tcell.EventResize:
			sf.scr.Sync()
			x, y := ev.Size()
			sf.screen.Resize(alias.SizeX(x), alias.SizeY(y))
		case *tcell.EventKey:
			if ev.Key() == tcell.KeyCtrlQ { // ev.Key() == tcell.KeyEscape
				return nil
			}
			if ev.Key() == tcell.KeyCtrlD { // Показать отладочную информацию
				if sf.screen.WinDebug().IsVisible() { // Переключение состояния показа окна отладки
					sf.screen.WinDebug().Hide()
				} else {
					sf.screen.WinDebug().Show()
				}
			}
		case *tcell.EventMouse: // Мышка подвинулась
			x, y := ev.Position()
			sf.screen.SetMousePos(alias.PosX(x), alias.PosY(y))
		}
		sf.screen.Draw()
	}
}

// Включение экрана терминала
func (sf *App) run_init() error {
	var err error
	if err = sf.scr.Init(); err != nil {
		return fmt.Errorf("App.run_init(): in init tcell.Screen, err=\n\t%w", err)
	}
	return nil
}

// Scr -- возвращает аппаратный экран
func (sf *App) Scr() tcell.Screen {
	return sf.scr
}
