// package dict_warbot -- потокобезопасный словарь ботов
package dict_warbot

import (
	"fmt"
	"log"
	"strings"
	"sync"

	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot"
)

const (
	strBotList = "/bots/list" // Константа путь к списку ботов в базе
)

// DictWarBot -- потокобезопасный словарь ботов
type DictWarBot struct {
	server types.ИСервер
	store  types.IStore
	dict   map[string]types.ИБот
	block  sync.RWMutex
}

// NewDictWarBot -- возвращает новый потокобезопасный словарь ботов
func NewDictWarBot(server types.ИСервер) (*DictWarBot, error) {
	if server == nil {
		return nil, fmt.Errorf("NewDictWarBot(): IServer==nil")
	}
	log.Printf("NewDictWarBot()\n")
	sf := &DictWarBot{
		server: server,
		store:  server.Store(),
		dict:   map[string]types.ИБот{},
	}
	if err := sf.load(); err != nil {
		return nil, fmt.Errorf("NewDictBot(): in load list bots from store, err=%w", err)
	}
	return sf, nil
}

// ListBot -- возвращает список существующих ботов
func (sf *DictWarBot) ListBot() []types.ИБот {
	lst := make([]types.ИБот, 0)
	for _, bot := range sf.dict {
		lst = append(lst, bot)
	}
	return lst
}

// Get -- возвращает бота по имени
func (sf *DictWarBot) Get(botName string) types.ИБот {
	sf.block.RLock()
	defer sf.block.RUnlock()
	bot := sf.dict[botName]
	return bot
}

// Add -- добавляет нового бота в словарь
func (sf *DictWarBot) Add(bot types.ИБот) {
	sf.block.Lock()
	defer sf.block.Unlock()
	if bot == nil {
		return
	}
	sf.dict[bot.Имя()] = bot
	sf.save()
}

// Сохраняет словарь ботов в базе
func (sf *DictWarBot) save() {
	strName := ""
	for name := range sf.dict {
		strName += name + ";"
	}
	strName = strName[:len(strName)-1]
	err := sf.store.Put(strBotList, strName)
	if err != nil {
		sf.server.CancelApp()
	}
}

// Загружает всех ботов с базы
func (sf *DictWarBot) load() error {
	strName, err := sf.store.Get(strBotList)
	if err != nil {
		if !strings.Contains(err.Error(), "not found") {
			return fmt.Errorf("DictWarBot.load(): in get list bot, err=\n\t%w", err)
		}
	}
	if strName == "" {
		return nil
	}
	lstName := strings.Split(strName, ";")
	for _, name := range lstName {
		if name == "" {
			continue
		}
		_, isOk := sf.dict[name]
		if isOk {
			continue
		}
		bot, err := warbot.ЗагрузитьВарБот(sf.server, name)
		if err != nil {
			return fmt.Errorf("ServBots.load(): in create bot %q, err=\n\t%w", name, err)
		}
		if bot.АвтоИграЕсли() {
			go bot.Пуск()
		}
		sf.dict[name] = bot
	}
	return nil
}
