package battle

import (
	"fmt"
	"net/http"
	"time"

	"wartank/pkg/components/section"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/battle/battle_register"
	"wartank/server/serv_bots/warbot/angar/battle/battle_wait"
	"wartank/server/serv_bots/warbot/angar/battle/battle_worker"
)

/*
	Объект ожидания сражения на базе
*/

// Battle -- объект ожидания сражения на базе
type Battle struct {
	*section.Section
	server types.IServer
	bot    types.IServBot
	conn   *http.Client

	battleRegister *battle_register.BattleRegister // Регистратор на сражение
	battleWaiter   *battle_wait.BattleWait         // Ождатель начала сражения
	battleWorker   *battle_worker.BattleWorker     // Исполнитель сражения

}

// NewBattle -- возвращает новый *Battle
func NewBattle(server types.IServer, bot types.IServBot) (*Battle, error) {
	{ // Предусловия
		if server == nil {
			return nil, fmt.Errorf("NewBattle(): IServer == nil")
		}
		if bot == nil {
			return nil, fmt.Errorf("NewBattle(): IServBot == nil")
		}
	}

	sf := &Battle{
		server: server,
		bot:    bot,
		conn:   bot.BotNet().Conn(),
	}
	var err error
	{
		sf.battleRegister, err = battle_register.NewBattleRegister(server, bot)
		if err != nil {
			return nil, fmt.Errorf("NewBattle(): при создании регистратора на сражения, err=\n\t%w", err)
		}
		sf.battleWaiter, err = battle_wait.NewBattleWait(server, bot)
		if err != nil {
			return nil, fmt.Errorf("NewBattle(): при создании ожидателя сражения, err=\n\t%w", err)
		}
		sf.battleWorker, err = battle_worker.NewBattleWorker(server, bot)
		if err != nil {
			return nil, fmt.Errorf("NewBattle(): при создании исполнителя сражения, err=\n\t%w", err)
		}
	}

	// sf.shotTimeFull.Set(8000) // 8000 msec

	return sf, nil
}

func (sf *Battle) Run() error {
	var err error
	{ // ISection
		sf.Section, err = section.NewSection(sf.server, `<span>до начала `)
		if err != nil {
			return fmt.Errorf("Battle.Run(): in create *Section, err=\n\t%w", err)
		}
	}
	sf.battleRegister.Run()
	sf.battleWaiter.Run()
	sf.battleWorker.Run()
	go sf.run()
	return nil
}

// запускает в работу сражение
func (sf *Battle) run() {
	// sf.CountDown().SetInt(2)
	for {
		select {
		case <-sf.server.Done():
			return
		default:
			sf.battleRegister.Register()
			sf.battleWaiter.Wait()
			sf.battleWorker.Work()
			for len(sf.CountDown().ChanSig()) > 0 {
				<-sf.CountDown().ChanSig()
			}
			time.Sleep(time.Second * 2) // Пауза между циклами, чтобы сервер не долбить запросами
		}
	}
}

// Alarm -- возвращает признак начала сражения (для браузера)
func (sf *Battle) Alarm() types.IStatParam {
	return sf.battleWorker.Alarm()
}
