// package win_root_login -- запрашивает рутовый пароль при запуске
package win_root_login

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

	"github.com/zserge/lorca"

	"wartank/pkg/types"
)

//go:embed win_root_login.html
var strWinHtml string

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

// NewWinRootLogin -- возвращает новое окно запроса пароля для рута
func NewWinRootLogin(desktop types.IDesktop) (*WinRootLogin, error) {
	if desktop == nil {
		return nil, fmt.Errorf("NewWinRootLogin(): IDesktop == nil")
	}
	sf := &WinRootLogin{
		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("NewWinRootLogin(): in create win, err=\n\t%w", err)
	}
	go sf.close()

	return sf, nil
}

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

func (sf *WinRootLogin) SetError(err error) {
	js := fmt.Sprintf(`
	function SetErrorGet(){
		var _el=document.getElementById("/root/password/err");
		_el.innerText="WinRootLogin.onCheckPass(): ошибка проверки пароля, err=\n\t%v"
	}
	SetErrorGet()
	`, err)
	sf.win.Eval(js)
}

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

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

// Проверяет пароль рута
func (sf *WinRootLogin) onCheckPass() {
	log.Printf("WinRootLogin.onCheckPass()\n")
	sf.block.Lock()
	defer sf.block.Unlock()
	sf.rootPass = sf.win.Eval(`document.getElementById("/root/password/val").value`).String()
}

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