// package warbot -- бот для игры в wartank
package warbot

import (
	"fmt"

	"wartank/pkg/components/safebool"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar"
	"wartank/server/serv_bots/warbot/tank"
	"wartank/server/serv_bots/warbot/warbot_net"
)

// WarBot -- бот для игры в вартанк
type WarBot struct {
	server   types.IServer
	store    types.IStore
	tank     *tank.Tank
	errFinal error // Финальная ошибка работы, если была
	angar    types.IAngar
	botNet   types.IBotNet
	name     string // Имя бота
	pass     string // Пароль бота
	isRun    *safebool.SafeBool
}

// NewWarBot -- возвращает новый WarBot
func NewWarBot(server types.IServer, name string) (*WarBot, error) {
	{ // Предусловия
		if server == nil {
			return nil, fmt.Errorf("NewWarBot(): IApp is nil")
		}
		if name == "" {
			return nil, fmt.Errorf("NewWarBot(): name is empty")
		}
	}

	tank, err := tank.NewTank(server)
	if err != nil {
		return nil, fmt.Errorf("NewWarBot(): in create Tank, err=\n\t%w", err)
	}
	sf := &WarBot{
		server: server,
		store:  server.Store(),
		tank:   tank,
		name:   name,
		isRun:  safebool.NewSafeBool(),
	}
	sf.pass, err = sf.store.Get("/bot/" + sf.name)
	if err != nil {
		return nil, fmt.Errorf("NewWarBot(): in get pass from store, err=\n\t%w", err)
	}

	{ // WarBotNet
		sf.botNet, err = warbot_net.NewWarBotNet(server, sf)
		if err != nil {
			return nil, fmt.Errorf("NewWarBot(): in make IBotNet, err=\n\t%w", err)
		}
	}
	sf.angar, err = angar.NewAngar(sf.server, sf)
	if err != nil {
		return nil, fmt.Errorf("NewWarBot(): bot(%q) in make IAngar, err=\n\t%w", sf.name, err)
	}
	return sf, nil
}

// Name -- возвращает имя бота
func (sf *WarBot) Name() string {
	return sf.name
}

// Pass -- возвращает пароль бота
func (sf *WarBot) Pass() string {
	return sf.pass
}

// Run -- запускает бот в работу
func (sf *WarBot) Run() (err error) {
	if sf.isRun.Get() {
		return nil
	}
	err = sf.botNet.Login()
	if err != nil {
		return fmt.Errorf("WarBot.Run(): bot(%q) in net login, err=\n\t%w", sf.name, err)
	}
	if err := sf.angar.Run(); err != nil {
		return fmt.Errorf("WarBot.Run(): bot(%q) in run angar, err=\n\t%w", sf.name, err)
	}
	sf.isRun.Set()
	return nil
}

// Error -- возвращает финальную ошибку работы, если была
func (sf *WarBot) Error() error {
	return sf.errFinal
}

// Angar -- возвращает ангар игры
func (sf *WarBot) Angar() types.IAngar {
	return sf.angar
}

// Tank -- возвращает объект танка
func (sf *WarBot) Tank() types.ITank {
	return sf.tank
}

// BotNet -- возвращает ссылку на свой сетевой клиент
func (sf *WarBot) BotNet() types.IBotNet {
	return sf.botNet
}
