package manevr

import (
	"fmt"
	// "log"
	"strings"
	"time"

	"github.com/sirupsen/logrus"

	"wartank/server/serv_bots/warbot/angar/battle/battle_worker/battleon/health/repairtime"
	"wartank/server/serv_bots/warbot/angar/battle/battle_worker/battleon/manevr/ismanevr"

	// "wartank/internal/components/sound"
	"wartank/pkg/types"
)

/*
	Пытается маневрировать после выстрела
*/

// Манёвр -- маневрирует после выстрела
type Манёвр struct {
	types.ИСражениеДействие                        // FIXME:
	еслиМанёврНадо          *ismanevr.IsManevr     // Требование выполнить манёвр
	времяЖдать              *repairtime.RepairTime // Время до востановления манёвра
	chTick                  chan int               // Тики для поиска маневра
}

// НовМанёвр -- возвращает новый *Manevr
func НовМанёвр(действие types.ИСражениеДействие) (*Манёвр, error) {
	{ // Предусловия
		if действие == nil {
			return nil, fmt.Errorf("НовМанёвр(): действие==nil")
		}
	}
	sf := &Манёвр{
		ИСражениеДействие: действие,
		еслиМанёврНадо:    ismanevr.NewIsManevr(),
		времяЖдать:        repairtime.NewRepairTime(),
		chTick:            make(chan int, 1),
	}
	_ = sf.времяЖдать.Set("0") // При запуске боя есть возможность маневрировать
	go sf.makeTick()
	go sf.пуск()
	return sf, nil
}

// Генерирует тик для уменьшения времени ожидания восстановления возможности манёвра
func (sf *Манёвр) makeTick() {
	defer func() {
		close(sf.chTick)
		// log._rintf("Manevr.makeTick(): сражение завершено\n")
	}()
	for {
		select {
		case <-sf.Кнт().Done():
			return
		default:
			if sf.времяЖдать.Получ() <= 0 {
				sf.chTick <- 1
			}
			sf.времяЖдать.Dec()
			time.Sleep(time.Second * 1)
		}
	}
}

// Рабочий цикл поиска маневра (~)
func (сам *Манёвр) пуск() {
	for range сам.chTick {
		if !сам.еслиМанёврНадо.Get() { // Если нет требования манёвра -- пропускаем
			continue
		}
		сам.манёвр()
		сам.времяМанёврНайти() // Найти время после манёвра
	}
}

// Ищет время для манёвра
func (сам *Манёвр) времяМанёврНайти() {
	var (
		isFind      bool
		ind         int
		lstBattleOn = сам.СписПолучить()
		strOut      string
	)
	for ind, strOut = range lstBattleOn {
		// <a href="pve?4-88.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>5 секунд</span></span></a>
		if strings.Contains(strOut, `-currentControl-maneuverLink`) {
			isFind = true
			break
		}
	}
	if !isFind { // Или манёвр успел восстановиться, или конец сражения
		if strings.Contains(strOut, `<span>Маневр</span>`) {
			_ = сам.времяЖдать.Set("0")
			return
		}
		logrus.WithField("strOut", strOut).Warn("Манёвр.времяМанёврНайти(): ошибка в поиске времени манёвра")
		сам.Отменить()
		return
	}
	{ // Найти время манёвра
		lstTime := strings.Split(strOut, `ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>`)
		if len(lstTime) != 2 {
			logrus.WithField("ind", ind).
				WithField("lstBattleOn[-1]", lstBattleOn[ind-1]).
				WithField("lstBattleOn[ind]", strOut).
				WithField("lstBattleOn[+1]", lstBattleOn[ind+1]).
				Errorf("Manevr.findManevrTime(): нет двух полей во времени ожидания")
			сам.Отменить()
			return
		}
		strTime := lstTime[1]
		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
		strTime = lstTime[0]
		if err := сам.времяЖдать.Set(strTime); err != nil {
			logrus.WithError(err).Error("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
			сам.Отменить()
			return
		}
	}
	logrus.WithField("время", сам.времяЖдать.Получ()).Info("Manevr.findManevrTime(): до манёвра")
}

// Манёвр по возможности
func (сам *Манёвр) манёвр() {
	var (
		isFind      = false
		lstBattleOn = сам.СписПолучить()
		strOut      = ""
	)
	for _, strOut = range lstBattleOn {
		// <a href="pve?4-21.ILinkListener-currentControl-maneuverLink" class="simple-but blue"><span><span>Маневр</span></span></a>
		if strings.Contains(strOut, `<span>Маневр</span>`) {
			isFind = true
			break
		}
	}
	if !isFind { // Либо ждём восстановления манёвра, либо сражение закончилось
		return
	}
	{ // Попытка манёвра
		lstLink := strings.Split(strOut, `<a href="`)
		strLink := lstLink[1]
		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
		strLink = "https://wartank.ru/" + lstLink[0]
		lstBattleOn, err := сам.Сеть().Get(strLink)
		if err != nil {
			logrus.WithError(err).Error("Manevr.Manevr(): при выполнении GET-команды маневра")
			сам.Отменить()
			return
		}
		if err = сам.СтрОбновить(lstBattleOn); err != nil {
			logrus.WithError(err).Error("Manevr.Manevr(): при обновлении lstBattle")
			сам.Отменить()
			return
		}
		// sound.Manevr()
	}
	сам.еслиМанёврНадо.Сброс()
}

// ЕслиГотов -- возвращает готовность манёвра
func (sf *Манёвр) ЕслиГотов() bool {
	return sf.времяЖдать.ЕслиМожно()
}

// УстНадо -- устанавливает признак необходимости манёвра
func (sf *Манёвр) УстНадо() {
	sf.еслиМанёврНадо.Set()
}
