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"
)

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

// Manevr -- маневрирует после выстрела
type Manevr struct {
	types.IBattleOn                        // FIXME:
	isNeedManevr    *ismanevr.IsManevr     // Требование выполнить манёвр
	manevrTime      *repairtime.RepairTime // Время до востановления манёвра
	chTick          chan int               // Тики для поиска маневра
}

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

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

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

// Ищет время для манёвра
func (sf *Manevr) findManevrTime() {
	var (
		isFind      bool
		ind         int
		lstBattleOn = sf.GetLst()
		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>`) {
			_ = sf.manevrTime.Set("0")
			time.Sleep(time.Second * 1)
			return
		}
		logrus.WithField("strOut", strOut).Warn("Manevr.findManevrTime(): ошибка в поиске времени манёвра")
		time.Sleep(time.Second * 1)
		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(): нет двух полей во времени ожидания")
			time.Sleep(time.Second * 1)
			return
		}
		strTime := lstTime[1]
		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
		strTime = lstTime[0]
		if err := sf.manevrTime.Set(strTime); err != nil {
			logrus.WithError(err).Error("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
			time.Sleep(time.Second * 1)
			return
		}
	}
	logrus.WithField("время", sf.manevrTime.Get()).Info("Manevr.findManevrTime(): до манёвра")
}

// Манёвр по возможности
func (sf *Manevr) manevr() {
	var (
		isFind      = false
		lstBattleOn = sf.GetLst()
		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 { // Либо ждём восстановления манёвра, либо сражение закончилось
		time.Sleep(time.Second * 1)
		return
	}
	{ // Попытка манёвра
		lstLink := strings.Split(strOut, `<a href="`)
		strLink := lstLink[1]
		lstLink = strings.Split(strLink, `" class="simple-but blue"><span><span>Маневр</span></span></a>`)
		strLink = "http://wartank.ru/" + lstLink[0]
		lstBattleOn, err := sf.Net().Get(strLink)
		if err != nil {
			logrus.WithError(err).Error("Manevr.Manevr(): при выполнении GET-команды маневра")
			time.Sleep(time.Second * 1)
			return
		}
		if err = sf.Update(lstBattleOn); err != nil {
			logrus.WithError(err).Error("Manevr.Manevr(): при обновлении lstBattle")
			time.Sleep(time.Second * 1)
			return
		}
		// sound.Manevr()
	}
	sf.isNeedManevr.Reset()
}

// IsReady -- возвращает готовность манёвра
func (sf *Manevr) IsReady() bool {
	return sf.manevrTime.IsReady()
}

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