// package dict_bot -- словарь ботов в игре
package dict_bot

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"

	"wartank/desktop/dict_bot/bot"
	"wartank/desktop/dict_bot/win_bot_add"
	"wartank/desktop/dict_bot/win_bot_view"
	"wartank/desktop/dict_bot/win_bots"
	"wartank/pkg/types"
)

// DictBot -- словарь ботов в игре
type DictBot struct {
	desktop types.IDesktop
	store   types.IStore
	ws      types.IWebSocket
	dict    map[string]types.IBot
	winBots *win_bots.WinBots
}

// NewDictBot -- возвращает новый словарь ботов
func NewDictBot(desktop types.IDesktop) (*DictBot, error) {
	if desktop == nil {
		return nil, fmt.Errorf("NewDictBot(): IDesktop == nil")
	}
	sf := &DictBot{
		desktop: desktop,
		store:   desktop.Store(),
		ws:      desktop.Ws(),
		dict:    make(map[string]types.IBot),
	}
	sf.load()
	return sf, nil
}

// Загружает список ботов, к этому моменту логин рута точно прошёл
func (sf *DictBot) load() {
	log.Println("DictBot.load()")
	dictResp, err := sf.ws.Read("/bot/list/load")
	if err != nil {
		if strings.Contains(err.Error(), "not found") {
			return
		}
		log.Printf("DictBot.load(): in get bot, err=\n\t%v\n", err)
		return
	}
	strErr := dictResp["err"]
	if strErr != "" {
		if strings.Contains(strErr, "not found") { // Это был первый запуск
			lstBot := make([]string, 0)
			binList, _ := json.Marshal(&lstBot)
			dictReq := make(map[string]string)
			dictReq["binData"] = string(binList)
			err := sf.ws.Write("/bot/list/save", dictReq)
			if err != nil {
				log.Printf("DictBot.load(): in write new list bot, err=\n\t%v\n", strErr)
			}
		} else {
			log.Printf("DictBot.load(): in response, err=\n\t%v\n", strErr)
		}
	}
	log.Printf("DictBot.load(): dictResp=%#v\n", dictResp)
	strList := dictResp["/bot/list"]
	lstBot := make([]string, 0)
	err = json.Unmarshal([]byte(strList), &lstBot)
	if err != nil {
		log.Printf("DictBot.load(): in unmarshal list bot, err=\n\t%v\n", err)
		return
	}
	for _, bot := range lstBot {
		sf.dict[bot] = ""
	}
}

// Show -- показывает окно списка ботов
func (sf *DictBot) Show() {
	log.Println("DictBot.Show()")
	dictBot := make(map[string]string)
	for key := range sf.dict {
		dictBot[key] = ""
	}
	var err error
	sf.winBots, err = win_bots.NewWinBots(sf.desktop, sf.addShow, sf.view, dictBot)
	if err != nil {
		log.Printf("DictBot.Show(): in create WinBots, err=\n\t%v\n", err)
		return
	}
	go sf.winBots.Run()
}

// Показывает окно добавления бота
func (sf *DictBot) addShow() {
	log.Println("DictBot.addShow()")
	winBotAdd, err := win_bot_add.NewWinBotAdd(sf.desktop, sf.addNew)
	if err != nil {
		log.Printf("DictBot.addShow(): in create WinBotAdd, err=\n\t%v\n", err)
		return
	}
	go winBotAdd.Run()
}

// Команда обратного вызова для добавления нового бота
func (sf *DictBot) addNew(name, pass string) {
	log.Printf("DictBot.addNew(): name=%q\tpass=%q\n", name, pass)
	_, isOk := sf.dict[name]
	if isOk {
		log.Printf("DictBot.addNew(): бот с именем(%q) уже существует\n", name)
		return
	}
	bot, err := bot.NewBot(name, pass)
	if err != nil {
		log.Printf("DictBot.addNew(): in add new bot(%q), err=\n\t%v\n", name, err)
		return
	}
	sf.dict[name] = bot
	{ // Работа с хранилищем
		// Сохранить бота в хранилище
		err = sf.store.Put("/bot/"+name, pass)
		if err != nil {
			log.Printf("DictBot.addNew(): in save new bot(%q), err=\n\t%v\n", name, err)
			return
		}
		// Обновить список ботов
		lstBot := make([]string, 0)
		for key := range sf.dict {
			lstBot = append(lstBot, key)
		}
		// Сохранить обновлённый список ботов
		binNewList, err := json.Marshal(&lstBot)
		if err != nil {
			log.Printf("DictBot.addNew(): in marshal new list bots, err=\n\t%v\n", err)
			return
		}
		err = sf.store.Put("/bot/list", string(binNewList))
		if err != nil {
			log.Printf("DictBot.addNew(): in save new bot(%q), err=\n\t%v\n", name, err)
			return
		}
	}

	if sf.winBots == nil {
		return
	}
	dictBot := make(map[string]string)
	for key := range sf.dict {
		dictBot[key] = ""
	}
	sf.winBots.UpdateList(dictBot)
}

// Команда просмотра существующего бота
func (sf *DictBot) view(nameBot string) {
	log.Printf("DictBot.view(): nameBot=%q\n", nameBot)
	winBotView, err := win_bot_view.NewWinBotView(sf.desktop, nameBot)
	if err != nil {
		log.Printf("DictBot.view(): in create win view on bot(%q), err=\n\t%v\n", nameBot, err)
		return
	}
	go winBotView.Run()
}
