// package win_root_set -- задаёт рутовый пароль на приложение
package win_root_set

import (
	_ "embed"
	"fmt"
	"log"
	"net/url"
	"runtime"
	"sync"
	"time"

	"github.com/zserge/lorca"

	"wartank/pkg/types"
)

//go:embed win_root_set.html
var strWinHtml string

// WinRootMake --  задаёт рутовый пароль на приложение
type WinRootMake struct {
	desktop  types.IDesktop
	store    types.IStore
	win      lorca.UI
	ws       types.IWebSocket
	rootPass string // Пароль рута из формы
	block    sync.Mutex
}

// NewWinRootMake -- возвращает новое окно пароля для рута
func NewWinRootMake(desktop types.IDesktop) (*WinRootMake, error) {
	if desktop == nil {
		return nil, fmt.Errorf("NewWinRootMake(): IDesktop == nil")
	}
	sf := &WinRootMake{
		desktop: desktop,
		store:   desktop.Store(),
		ws:      desktop.Ws(),
	}

	args := []string{}
	if runtime.GOOS == "linux" {
		args = append(args, "--class=Lorca")
	}
	var err error
	sf.win, err = lorca.New("data:text/html,"+url.PathEscape(strWinHtml), "", 640, 480, args...)
	if err != nil {
		return nil, fmt.Errorf("WinRoot(): in create win, err=\n\t%w", err)
	}
	go sf.close()

	return sf, nil
}

// GetPass -- возвращает полученный пароль из формы
func (sf *WinRootMake) GetPass() string {
	fnCheck := func() bool {
		sf.block.Lock()
		defer sf.block.Unlock()
		return len(sf.rootPass) > 7
	}
	for !fnCheck() {
		time.Sleep(time.Millisecond * 20)
	}
	sf.block.Lock()
	defer sf.block.Unlock()
	return sf.rootPass
}

// SetError -- устанавливает признак ошибки при операциях с паролем
func (sf *WinRootMake) SetError(err error) {
	js := fmt.Sprintf(`
	function SetErrorSave(){
		var _el=document.getElementById("/root/password/err");
		_el.innerText="WinRootMake.onSetPass(): ошибка передачи при сохранении пароля, err=\n\t%v"
	}
	SetErrorSave()`, err)
	sf.win.Eval(js)
}

func (sf *WinRootMake) Close() {
	sf.win.Close()
}

// Работает в отдельном потоке, главный цикл окна
func (sf *WinRootMake) Run() {
	log.Println("WinRootMake.Run()")
	sf.win.Bind("close_win", sf.onClose)
	sf.win.Bind("set_pass", sf.onSetPass)
	<-sf.win.Done() // Ожидание закрытия окна
}

// Сохраняет пароль рута
func (sf *WinRootMake) onSetPass() {
	log.Printf("WinRootMake.onSetPass()\n")
	sf.block.Lock()
	defer sf.block.Unlock()
	sf.rootPass = sf.win.Eval(`document.getElementById("/root/password/val").value`).String()
	if len(sf.rootPass) < 8 {
		js := `
		function SetError(){
			var _el=document.getElementById("/root/password/err");
			_el.innerText="WinRootMake.onSetPass(): пароль слишком короткий"
		}
		SetError()
		`
		sf.win.Eval(js)
		return
	}
	js := `
	function ResetError(){
		var _el=document.getElementById("/root/password/err");
		_el.innerText=""
	}
	ResetError()
	`
	sf.win.Eval(js)
	log.Printf("WinRootMake.onSetPass(): pass=%q\n", sf.rootPass)
}

// Закрывает приложение
func (sf *WinRootMake) onClose() {
	log.Println("WinRootMake.onClose()")
	sf.win.Close()
}

// close -- ожидает отмены глобального контекста
func (sf *WinRootMake) close() {
	<-sf.desktop.CtxApp().Done()
	log.Println("WinRootMake.close()")
	sf.win.Close()
}
