package div_war_on

import (
	"context"
	"fmt"
	"strings"
	"time"
	"wartank/pkg/arena"
	"wartank/pkg/components/arena_net"
	"wartank/pkg/components/safe_bool"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/division/div_war/div_war_on/health"
	"wartank/server/serv_bots/warbot/angar/division/div_war/div_war_on/manevr"
	"wartank/server/serv_bots/warbot/angar/division/div_war/div_war_on/shot"
)

/*
	Предоставляет сетевой компонент при непосредственном сражении
*/

// DivWarOn -- непосредственно танкует в сражении
type DivWarOn struct {
	types.ИАрена
	bot            types.ИБот
	сеть           types.ИАренаСеть
	ctxDivWar      context.Context // Контекст сражения
	fnCancelDivWar func()          // Функция отмены сражения

	shot      *shot.Shot     // Объект выстрела
	health    *health.Health // Текущее здоровье танка
	manevr    *manevr.Manevr // Возможность маневрирования
	login     string
	isMasking *safe_bool.БезопБул // Признак необходимости маскирования (запрет стрельбы, когда слабое здоровье)
	chTick    chan int            // Ежесекундная проверка на окончание сражения
	isEnd     *safe_bool.БезопБул
}

// NewDivWarOn -- возвращает новый *DivWarOn
func NewDivWarOn(bot types.ИБот) (*DivWarOn, error) {
	if bot == nil {
		return nil, fmt.Errorf("NewDivWarOn(): IBot == nil")
	}
	ctxDivWar, fnCancelDivWar := context.WithTimeout(bot.Контекст(), time.Second*305)
	сам := &DivWarOn{
		bot:            bot,
		ctxDivWar:      ctxDivWar,
		fnCancelDivWar: fnCancelDivWar,
		login:          bot.Имя(),
		isMasking:      safe_bool.НовБезопБул(),
		isEnd:          safe_bool.НовБезопБул(),
	}
	аренаКонфиг := arena.АренаКонфиг{
		Бот_:         bot,
		АренаИмя_:    "Сражение",
		СтрКонтроль_: `<title>Сражения</title>`,
		ФнПуск_:      сам.пуск,
	}
	сам.ИАрена = arena.НовАрена(аренаКонфиг)
	сам.сеть = arena_net.НовАренаСеть(сам, "https://wartank.ru/pve")
	if сам.checkEnd() {
		return nil, fmt.Errorf("NewDivWarOn(): нет страницы для сражения")
	}
	go сам.makeTick()
	go сам.run()
	return сам, nil
}

// пускает сражение
func (сам *DivWarOn) пуск() {
}

// Ежесекудный тик
func (сам *DivWarOn) makeTick() {
	defer func() {
		close(сам.chTick)
		сам.isEnd.Уст()
	}()
	for !сам.isEnd.Получ() {
		select {
		case <-сам.bot.Контекст().Done(): // Отмена контекста приложения
			return
		case <-сам.ctxDivWar.Done(): // Битва закончилась
			return
		default:
			if сам.isEnd.Получ() {
				return
			}
			сам.chTick <- 1
			time.Sleep(time.Second * 1)
		}
	}
}

// запускает сражение
func (сам *DivWarOn) run() {
	// defer log._rintf("DivWarOn.run(): сражение завершено\n")
	{ // Подготовка к сражению
		var err error
		сам.shot, err = shot.NewShot(сам, сам.login) // Объект выстрела
		if err != nil {
			// log._rintf("ERRO DivWarOn.Run(): при создании выстрела танка, err=\n\t%v\n", err)
			return
		}
		сам.health, err = health.NewHealth(сам, сам.shot.IsEnd(), сам.login)
		if err != nil {
			// log._rintf("ERRO DivWarOn.Run(): при создании здоровья танка, err=\n\t%v\n", err)
			сам.shot.IsEnd().Сброс()
			return
		}
		сам.manevr, err = manevr.NewManevr(сам, сам.shot.IsEnd())
		if err != nil {
			// log._rintf("ERRO DivWarOn.Run(): при создании маневра танка, err=\n\t%v\n", err)
			сам.shot.IsEnd().Сброс()
			return
		}
	}
	for { // Рабочий цикл сражения
		select {
		case <-сам.ctxDivWar.Done():
			return
		case <-сам.ВремяОстат().КаналСиг():
			if сам.checkEnd() {
				return
			}
		}
	}
}

// Сеть -- возвращает сетевой компонент секции
func (сам *DivWarOn) Сеть() types.ИАренаСеть {
	return сам.сеть
}

// Проверяет окончание сражения
func (сам *DivWarOn) checkEnd() bool {
	defer func() {
		if сам.isEnd.Получ() {
			сам.fnCancelDivWar()
			// log._rintf("DivWarOn.checkEnd(): сражение завершено\n")
		}
	}()

	сам.сеть.Обновить()
	lstDivWarOn := сам.СписПолучить()
	for _, strOut := range lstDivWarOn {
		if strings.Contains(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`) {
			сам.isEnd.Сброс()
			return false
		}
	}
	сам.isEnd.Уст()
	сам.fnCancelDivWar()
	return true
}

// ЕслиКонец -- возвращает признак окончания сражения (интерфейс)
func (сам *DivWarOn) ЕслиКонец() *safe_bool.БезопБул {
	return сам.isEnd
}

func (сам *DivWarOn) Манёвр() {
	if сам.manevr == nil {
		return
	}
	if сам.manevr.IsReady() {
		сам.manevr.Manevr()
	}
}

// ВыстрелБлок -- признак запрета стрельбы при слабом здоровье
func (сам *DivWarOn) ВыстрелБлок() *safe_bool.БезопБул {
	return сам.isMasking
}

// Ctx -- возвращает контекст отмены сражения
func (сам *DivWarOn) Ctx() context.Context {
	return сам.ctxDivWar
}

// CancelBattle - -вызов функции отмены контекста сражения
func (сам *DivWarOn) CancelBattle() {
	сам.fnCancelDivWar()
}
