// package screen -- объект экрана
package screen

import (
	"fmt"

	"github.com/gdamore/tcell"
	"p78git.ddns.net/svi/libtui/alias"
	"p78git.ddns.net/svi/libtui/cell"
	"p78git.ddns.net/svi/libtui/screen/scr_cursor"
	"p78git.ddns.net/svi/libtui/screen/win_debug"
	"p78git.ddns.net/svi/libtui/size"
	"p78git.ddns.net/svi/libtui/types"
)

// Screen -- объект экрана
type Screen struct {
	app      types.IApp
	scr      tcell.Screen
	size     types.ISize     // Размер экрана
	winDebug types.IWinDebug // Окно отладки
	cursor   *scr_cursor.ScrCursor
}

// NewScreen -- возвращаетновый экран
func NewScreen(app types.IApp) (*Screen, error) {
	if app == nil {
		return nil, fmt.Errorf("NewScreen(): IApp==nil")
	}
	sf := &Screen{
		app:  app,
		scr:  app.Scr(),
		size: size.NewSize(),
	}
	var err error
	sf.winDebug, err = win_debug.NewWinDebug(sf)
	if err != nil {
		return nil, fmt.Errorf("NewScreen(): in creatre IWinDebug, err=\n\t%w", err)
	}
	sf.cursor, err = scr_cursor.NewScrCursor(sf)
	if err != nil {
		return nil, fmt.Errorf("NewScreen(): in create ScrCursor, err=\n\t%w", err)
	}
	sf.scr.HideCursor()
	return sf, nil
}

// Size -- возвращает размер экрана
func (sf *Screen) Size() (alias.SizeX, alias.SizeY) {
	return sf.size.Get()
}

// WinDebug -- возвращает объект окна отладки экрана
func (sf *Screen) WinDebug() types.IWinDebug {
	return sf.winDebug
}

// Resize -- изменяет размер экрана
func (sf *Screen) Resize(x alias.SizeX, y alias.SizeY) {
	sf.size.Set(x, y)
}

// SetMousePos -- устанавливает позицию мыши
func (sf *Screen) SetMousePos(x alias.PosX, y alias.PosY) {
	sf.cursor.SetPos(x, y)
	if sf.winDebug.IsVisible() { // Установить позицию окна отладки, если оно видно
		sf.winDebug.SetPos(x, y)
	}
}

// App -- возвращает объект приложения
func (sf *Screen) App() types.IApp {
	return sf.app
}

// MousePos -- возвращает позицию мыши
func (sf *Screen) MousePos() (alias.PosX, alias.PosY) {
	return sf.cursor.Pos()
}

// GetCell -- возвращает ячейку по указанному знакоместу
func (sf *Screen) GetCell(posX alias.PosX, posY alias.PosY) types.ICell {
	rune_, _, style, _ := sf.scr.GetContent(int(posX), int(posY))
	cell := cell.NewCell()
	cell.SetLit(alias.Lit(rune_))
	cell.SetStyle(alias.Style(style))
	return cell
}

// SetCell -- устанавливает ячейку на экран
func (sf *Screen) SetCell(cell types.ICell) {
	x, y := cell.Pos()
	style := cell.Style()
	lit := cell.Lit()
	sf.scr.SetCell(int(x), int(y), tcell.Style(style), rune(lit))
}

// Draw -- отрисовка экранасебя по требованию
func (sf *Screen) Draw() {
	sf.scr.Clear()
	sf.winDebug.Draw()
	sf.cursor.Draw()
	sf.scr.Show() // Обновить экран
}

// Clear -- очистка экрана
func (sf *Screen) Clear() {
	sf.scr.Clear() // Зачистить экран перед началом работы
}
