// package angar_attack
package angar_attack

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"wartank/pkg/components/sectionnet"
	"wartank/pkg/types"
)

/*
	Объект боя на топливе
*/

// AngarAttack -- объект боя на топливе
type AngarAttack struct {
	*sectionnet.SectionNet
	server types.IServer
	angar  types.IAngar
	bot    types.IServBot
}

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

	sf := &AngarAttack{
		server: server,
		angar:  bot.Angar(),
		bot:    bot,
	}
	return sf, nil
}

func (sf *AngarAttack) Run() error {
	sf.SectionNet = sectionnet.NewSectionNet(sf.server, sf.bot, sf.angar, "http://wartank.ru/battle")
	go sf.run()
	return nil
}

func (sf *AngarAttack) run() {
	for {
		time.Sleep(time.Second * 15) // Минимальный интервал ожттдания прибавки топлива
		fuel := sf.angar.Fuel().Get()
		if fuel < 314 { // Минимальная ёмкость бака -- 315
			continue
		}
		log.Printf("Fuel.Run: val=%v\n", fuel)
		lstBattle, err := sf.makeAtack()
		if err != nil {
			// log._rintf("ERRO AngarAttack.findFuel(): in get page battle, err=\n\t%v\n", err)
			continue
		}
		lstShoot2, err := sf.makeSelectBattle(lstBattle)
		if err != nil {
			// log._rintf("ERRO AngarAttack.findFuel(): in get page shooting, err=\n\t%v\n", err)
			continue
		}
		if err := sf.makeShooting(lstShoot2); err != nil {
			log.Printf("ERRO AngarAttack.findFuel(): in make shooting, err=\n\t%v\n", err)
		}
	}

}

// Идёт в атаку, если топлива больше 90
func (sf *AngarAttack) makeAtack() (lstBattle []string, err error) {
	// Получить ссылку на атаку
	// _mt.Println("\t AngarAttack.makeAtack()")
	lstAngar := sf.angar.GetLst()
	var strOut string
	for _, strAtack := range lstAngar {
		if strings.Contains(strAtack, `<span>В бой!</span>`) {
			strOut = strAtack
			break
		}
	}
	// Вырезать ссылку на атаку
	lstAngar = strings.Split(strOut, `<a class="simple-but border mb1" href="`)
	linkBatle := lstAngar[1]
	lstAngar = strings.Split(linkBatle, `"><span><span>В бой!</span></span></a>`)
	linkBatle = "http://wartank.ru/" + lstAngar[0]
	lstBattle, err = sf.Get(linkBatle)
	if err != nil {
		return nil, fmt.Errorf("AngarAttack.makeAtack(): in make GET-request to battle, err=\n\t%w", err)
	}
	fuel := sf.angar.Fuel().Get()
	fuel -= 30
	sf.angar.Fuel().Set(fuel)
	return lstBattle, nil
}

// Выбирает первого более слабого противника и делает первый выстрел
func (sf *AngarAttack) makeSelectBattle(lstBattle []string) (lstShoot2 []string, err error) {
	// _mt.Println("\tAngarNet.makeSelectBattle()")
	var strOut string
	defer func() {
		if _panic := recover(); _panic != nil {
			msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot1\n"
			msg += "\tNetClient.makeSelectBattle().fnShoot1()\n"
			msg0 := fmt.Sprintf("%v\n", _panic)
			msg1 := ""
			for _, _msg := range strings.Split(msg0, "\n") {
				if _msg == "" {
					continue
				}
				msg1 += "\t" + _msg + "\n"
			}
			msg += msg1
			// _mt.Println(msg)
			err = fmt.Errorf("%v", msg)
			msg1 = "" // Сброс накопленной ошибки
			for _, _msg := range lstBattle {
				if _msg == "" {
					continue
				}
				msg1 += "\t" + _msg + "\n"
			}
			msg += msg1
			// Выкинуть ошибку в файл
			_ = os.MkdirAll("./errors", 0700)
			err = os.WriteFile("./errors/attack_shoot1.html", []byte(msg), 0600)
		}
	}()
	// Выдернуть строку с первой ссылкой на противника
	for _, strBattle := range lstBattle {
		if strings.Contains(strBattle, `opponents-opponents-0`) {
			strOut = strBattle
			break
		}
	}
	var linkBattle string
	switch strOut == "" {
	case true: // Такая ситуация возможна, если уже были какие-то выстрелы
		return lstBattle, nil
	default: // Успешный выстрел
		// Вырезать ссылку из строки
		lstBattle = strings.Split(strOut, `<td class="cntr"><a href="`)
		linkBattle = lstBattle[1]
		lstBattle = strings.Split(linkBattle, `"><img class="tank-img" alt="tank" src="/tankimg?`)
		linkBattle = "http://wartank.ru/" + lstBattle[0]
	}
	lstShoot2, err = sf.Get(linkBattle)
	if err != nil {
		return nil, fmt.Errorf("AngarAttack.makeSelectBattle(): in GET-response select battle tank, err=\n\t%w", err)
	}
	return lstShoot2, nil
}

// Ведёт бой в 2 выстрела (2 и 3 выстрел)
func (sf *AngarAttack) makeShooting(lstShoot2 []string) error {
	// _mt.Println("\tAngarNet.makeShooting()")
	var lstShoot3 []string           // Тело страницы для третьего выстрела
	fnShoot2 := func() (err error) { // Второй выстрел
		// _mt.Println("\tAngarNet.makeShooting().fnShoot2()")
		defer func() {
			if _panic := recover(); _panic != nil {
				msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot2\n"
				msg += "\tNetClient.makeShooting().fnShoot2()\n"
				msg0 := fmt.Sprintf("%v\n", _panic)
				msg1 := ""
				for _, _msg := range strings.Split(msg0, "\n") {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// _mt.Println(msg)
				err = fmt.Errorf("%v", msg)
				msg1 = "" // Сброс накопленной ошибки
				for _, _msg := range lstShoot2 {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// Выкинуть ошибку в файл
				_ = os.MkdirAll("./errors", 0700)
				err = os.WriteFile("./errors/attack_shoot2.html", []byte(msg), 0600)
			}
		}()
		// Получить ссылку на второй выстрел
		var strOut string
		for _, strShoot := range lstShoot2 {
			if strings.Contains(strShoot, `<span>Добить</span>`) {
				strOut = strShoot
				break
			}
		}
		var linkShoot2 string
		switch strOut == "" {
		case true: // Первый выстрел был неудачным
			for _, strShoot := range lstShoot2 {
				if strings.Contains(strShoot, `<span>Взять реванш</span>`) {
					strOut = strShoot
					break
				}
			}
			if strOut == "" { // Это ситуация для третьего выстрела
				lstShoot3 = lstShoot2
				return nil
			}
			// Вырезать ссылку из строки
			lstShoot2 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot2 = lstShoot2[1]
			lstShoot2 = strings.Split(linkShoot2, `"><span><span>Взять реванш</span></span></a>`)
			linkShoot2 = "http://wartank.ru/" + lstShoot2[0]
		default: // Первый выстрел был удачным
			// Вырезать ссылку из строки
			lstShoot2 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot2 = lstShoot2[1]
			lstShoot2 = strings.Split(linkShoot2, `"><span><span>Добить</span></span></a>`)
			linkShoot2 = "http://wartank.ru/" + lstShoot2[0]
		}
		lstShoot3, err = sf.Get(linkShoot2)
		if err != nil {
			return fmt.Errorf("AngarAttack.makeShooting(): in Get-response shoot2, err=\n\t%w", err)
		}
		fuel := sf.angar.Fuel().Get()
		fuel -= 30
		sf.angar.Fuel().Set(fuel)
		return nil
	}
	if err := fnShoot2(); err != nil {
		return err
	}
	fnShoot3 := func() (err error) { // Третий выстрел
		// _mt.Println("\tAngarNet.makeShooting().fnShoot3()")
		defer func() {
			if _panic := recover(); _panic != nil {
				msg := time.Now().Local().Format("2006-01-02 15:04:05.000 fnShoot3\n")
				msg += "\tNetClient.makeShooting().fnShoot3()\n"
				msg0 := fmt.Sprintf("%v\n", _panic)
				msg1 := ""
				for _, _msg := range strings.Split(msg0, "\n") {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// _mt.Println(msg)
				err = fmt.Errorf("%v", msg)
				msg1 = "" // Сброс накопленной ошибки
				for _, _msg := range lstShoot3 {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// Выкинуть ошибку в файл
				_ = os.MkdirAll("./errors", 0700)
				err = os.WriteFile("./errors/attack_shoot3.html", []byte(msg), 0600)
			}
		}()
		// Получить ссылку на третий выстрел
		var strOut string
		for _, strShoot3 := range lstShoot3 {
			if strings.Contains(strShoot3, `<span>Уничтожить</span>`) {
				strOut = strShoot3
				break
			}
		}
		linkShoot3 := ""
		switch strOut == "" {
		case true: // Если не найдена ссылка -- значит было поражение в выстреле
			if strOut == "" {
				for _, strShoot3 := range lstShoot3 {
					if strings.Contains(strShoot3, `<span>Взять реванш</span>`) {
						strOut = strShoot3
						break
					}
				}
			}
			// Вырезать ссылку из строки
			lstShoot3 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot3 = lstShoot3[1]
			lstShoot3 = strings.Split(linkShoot3, `"><span><span>Взять реванш</span></span></a>`)
			linkShoot3 = "http://wartank.ru/" + lstShoot3[0]
		default: // Успешный выстрел
			// Вырезать ссылку из строки
			lstShoot3 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot3 = lstShoot3[1]
			lstShoot3 = strings.Split(linkShoot3, `"><span><span>Уничтожить</span></span></a>`)
			linkShoot3 = "http://wartank.ru/" + lstShoot3[0]
		}

		if _, err = sf.Get(linkShoot3); err != nil {
			return fmt.Errorf("AngarAttack.makeShooting(): in Get-response shoot3, err=\n\t%w", err)
		}
		fuel := sf.angar.Fuel().Get()
		fuel -= 30
		sf.angar.Fuel().Set(fuel)
		return nil
	}
	if err := fnShoot3(); err != nil {
		return err
	}
	return nil
}
