package manevr

import (
	"context"
	"fmt"

	// "log"
	"strings"
	"time"

	"github.com/sirupsen/logrus"

	"wartank/server/serv_bots/warbot/angar/division/div_war/div_war_on/health/repair_time"
	"wartank/server/serv_bots/warbot/angar/division/div_war/div_war_on/manevr/ismanevr"

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

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

// Manevr -- маневрирует после выстрела
type Manevr struct {
	types.ИДивизияВойнаДействие // FIXME:
	isEnd                       *safe_bool.БезопБул
	ctxEnd                      context.Context
	isManevr                    *ismanevr.IsManevr      // Возможность выполнить манёвр
	manevrTime                  *repair_time.RepairTime // Время до востановления манёвра
	chTick                      chan int                // Тики для поиска маневра
}

// NewManevr -- возвращает новый *Manevr
func NewManevr(divwar types.ИДивизияВойнаДействие, isDivWar *safe_bool.БезопБул) (*Manevr, error) {
	{ // Предусловия
		if divwar == nil {
			return nil, fmt.Errorf("NewManevr(): battle is nil")
		}
	}
	if isDivWar == nil {
		return nil, fmt.Errorf("NewManevr(): isBattle is nil")
	}
	сам := &Manevr{
		ИДивизияВойнаДействие: divwar,
		ctxEnd:     divwar.Ctx(),
		isEnd:      isDivWar,
		isManevr:   ismanevr.NewIsManevr(),
		manevrTime: repair_time.NewRepairTime(),
		chTick:     make(chan int, 1),
	}
	_ = сам.manevrTime.Set("0") // При запуске боя есть возможность маневрировать
	go сам.makeTick()
	go сам.run()
	return сам, nil
}

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

			сам.manevrTime.Dec()
			time.Sleep(time.Second * 1)
		}
	}
}

// Рабочий цикл поиска маневра (~)
func (сам *Manevr) run() {
	for range сам.chTick {
		if !сам.isManevr.Get() {
			continue
		}
		сам.findManevrTime()
	}
}

// Ищет время для манёвра
func (сам *Manevr) findManevrTime() {
	var (
		еслиНайдено 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`) {
			еслиНайдено = true
			break
		}
	}
	if !еслиНайдено { // Или манёвр успел восстановиться, или конец сражения
		if strings.Contains(strOut, `<span>Маневр</span>`) {
			_ = сам.manevrTime.Set("0")
			time.Sleep(time.Second * 1)
			return
		}
		if сам.isEnd.Получ() {
			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(): нет двух полей во времени ожидания")
			сам.isManevr.Reset()
			time.Sleep(time.Second * 1)
			return
		}
		strTime := lstTime[1]
		lstTime = strings.Split(strTime, ` секунд</span></span></a>`)
		strTime = lstTime[0]
		if err := сам.manevrTime.Set(strTime); err != nil {
			logrus.WithError(err).Error("Manevr.findManevrTime(): при обновлении времени ожидания манёвра")
			сам.isManevr.Reset()
			time.Sleep(time.Second * 1)
			return
		}
	}
	сам.isManevr.Set()
	logrus.WithField("время", сам.manevrTime.Get()).Info("Manevr.findManevrTime(): до манёвра")
}

// Manevr -- принудительный манёвр по требованию
func (сам *Manevr) Manevr() {
	var (
		еслиНайдено = false
		lstBattleOn = сам.СписПолучить()
		strOut      = ""
	)
	if !сам.isManevr.Get() {
		time.Sleep(time.Second * 1)
		return
	}
	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>`) {
			еслиНайдено = true
			break
		}
	}
	if !еслиНайдено { // Либо ждём восстановления манёвра, либо сражение закончилось
		сам.isManevr.Reset()
		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 = "https://wartank.ru/" + lstLink[0]
		lstBattleOn, err := сам.Сеть().Get(strLink)
		if err != nil {
			logrus.WithError(err).Error("Manevr.Manevr(): при выполнении GET-команды маневра")
			сам.isManevr.Reset()
			time.Sleep(time.Second * 1)
			return
		}
		if err = сам.СтрОбновить(lstBattleOn); err != nil {
			logrus.WithError(err).Error("Manevr.Manevr(): при обновлении lstBattle")
			сам.isManevr.Reset()
			time.Sleep(time.Second * 1)
			return
		}
		// sound.Manevr()
	}
}

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