package arsenal

import (
	"fmt"
	"strconv"
	"strings"

	"wartank/pkg/components/section"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/base/arsenal/arsenalnet"
	"wartank/server/serv_bots/warbot/tank/tankstat/static_param"
)

/*
	Объект арсенала на базе
*/

// Arsenal -- объект арсенала на базе
type Arsenal struct {
	*section.Section
	server types.IServer
	bot    types.IServBot
	base   types.IBase
	net    *arsenalnet.ArsenalNet
	fugas  types.IStatParam
	armor  types.IStatParam
	kumul  types.IStatParam
	remka  types.IStatParam
}

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

	sf := &Arsenal{
		server: server,
		bot:    bot,
		base:   bot.Angar().Base(),
		fugas:  static_param.NewStaticParam("fugas"),
		armor:  static_param.NewStaticParam("armor"),
		kumul:  static_param.NewStaticParam("kumul"),
		remka:  static_param.NewStaticParam("remka"),
	}

	return sf, nil
}

func (sf *Arsenal) Run() error {
	var err error
	{ // ISection
		sf.Section, err = section.NewSection(sf.server, `<span class="green2">Ремкомплект</span><br/>`)
		if err != nil {
			return fmt.Errorf("Arsenal.Run(): in create *Section, err=\n\t%w", err)
		}
	}
	{ // ArsenalNet
		sf.net, err = arsenalnet.NewArsenalNet(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Arsenal.Run(): in create NetArsenal, err=\n\t%w", err)
		}
	}
	go sf.run()
	return nil
}

// запускает обработку арсенала
func (sf *Arsenal) run() {
	// sf.getTime()
	for {
		select {
		case <-sf.server.Done():
			sf.CountDown().Stop()
			return
		case <-sf.CountDown().ChanSig():
			if sf.ModeCurrent().Get() == "upgrade" {
				continue
			}
			// if err := sf.updateArsenal(); err != nil {
			// 	return fmt.Errorf("ArsenalNet.Run(): in update arsenal, err=\n\t%w", err)
			// }
			sf.makeArsenal()
		}
		// time.Sleep(time.Second * 30)
	}
}

// Fugas -- возвращает объект числа фугасов
func (sf *Arsenal) Fugas() types.IStatParam {
	return sf.fugas
}

// Armor -- возвращает объект бронебойных снарядов
func (sf *Arsenal) Armor() types.IStatParam {
	return sf.armor
}

// Kumul -- возвращает объект бронебойных снарядов
func (sf *Arsenal) Kumul() types.IStatParam {
	return sf.kumul
}

// Remka -- возвращает объект ремкомплектов
func (sf *Arsenal) Remka() types.IStatParam {
	return sf.remka
}

// Обновляет состояние арсенала по требованию
func (sf *Arsenal) UpdateArsenal() (err error) {
	// _mt.Println("\tArsenalNet.updateArsenal()")
	if err := sf.net.UpdateLst("арсенал"); err != nil {
		return fmt.Errorf("Arsenal.UpdateArsenal(): при обновлении lstArsenal, err=%w", err)
	}
	var (
		strOut     string
		lstArsenal = sf.GetLst()
	)
	{ // Найти маркер фугасного снаряда
		for _, strFugas := range lstArsenal {
			if strings.Contains(strFugas, `<span class="nwr"><img class="rico vm" src="/images/shells/HighExplosive.png" alt="Фугасный снаряд" title="Фугасный снаряд"/> `) {
				strOut = strFugas
				break
			}
		}
		lstFugas := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/shells/HighExplosive.png" alt="Фугасный снаряд" title="Фугасный снаряд"/> `)
		strFugas := lstFugas[1]
		lstFugas = strings.Split(strFugas, ` &nbsp;&nbsp;</span>`)
		strFugas = lstFugas[0]
		iFugas, err := strconv.Atoi(strFugas)
		if err != nil {
			return fmt.Errorf("ArsenalNet.updateArsenal(): fugas(%v) not number, err=\n\t%w", strFugas, err)
		}
		sf.Fugas().Set(iFugas)
	}
	{ // Найти маркер бронебойного снаряда
		for _, strArmor := range lstArsenal {
			if strings.Contains(strArmor, `alt="Бронебойный снаряд"`) {
				strOut = strArmor
				break
			}
		}
		lstArmor := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/shells/ArmorPiercing.png" alt="Бронебойный снаряд" title="Бронебойный снаряд"/> `)
		strArmor := lstArmor[1]
		lstArmor = strings.Split(strArmor, ` &nbsp;&nbsp;</span>`)
		strArmor = lstArmor[0]
		iArmor, err := strconv.Atoi(strArmor)
		if err != nil {
			return fmt.Errorf("ArsenalNet.updateArsenal(): armor(%v) not number, err=\n\t%w", strArmor, err)
		}
		sf.Armor().Set(iArmor)
	}
	{ // Найти маркер кумулятивного снаряда
		for _, strKumul := range lstArsenal {
			if strings.Contains(strKumul, `<span class="nwr"><img class="rico vm" src="/images/shells/HollowCharge.png" alt="Кумулятивный снаряд" title="Кумулятивный снаряд"/> `) {
				strOut = strKumul
				break
			}
		}
		lstKumul := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/shells/HollowCharge.png" alt="Кумулятивный снаряд" title="Кумулятивный снаряд"/> `)
		strKumul := lstKumul[1]
		lstKumul = strings.Split(strKumul, ` &nbsp;&nbsp;</span>`)
		strKumul = lstKumul[0]
		iKumul, err := strconv.Atoi(strKumul)
		if err != nil {
			return fmt.Errorf("ArsenalNet.updateArsenal(): kumul(%v) not number, err=\n\t%w", strKumul, err)
		}
		sf.Kumul().Set(iKumul)
	}
	{ // Найти маркер ремкомплекта
		for ind, strRemka := range lstArsenal {
			if strings.Contains(strRemka, `<span class="nwr"><img class="rico vm" src="/images/shells/repairkit.gif"/> `) {
				strOut = lstArsenal[ind]
				break
			}
		}
		lstRemka := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/shells/repairkit.gif"/> `)
		strRemka := lstRemka[1]
		lstRemka = strings.Split(strRemka, `</span>`)
		strRemka = lstRemka[0]
		iRemka, err := strconv.Atoi(strRemka)
		if err != nil {
			return fmt.Errorf("ArsenalNet.updateArsenal(): remka(%v) not number, err=\n\t%w", strRemka, err)
		}
		sf.Remka().Set(iRemka)
	}
	return nil
}

// Выбирает что надо делать, запускает процесс изготовления
func (sf *Arsenal) makeArsenal() {
	err := sf.net.UpdateLst("арсенал")
	if err != nil {
		// log._rintf("ERRO Arsenal.Run(): при обновлении lstArsenal, err=\n\t%v\n", err)
		return
	}
	fnMakeRemka := func() {
		if err = sf.makeRemka(); err != nil {
			// log._rintf("ERRO ArsenalNet.makeArsenal(): in make remka, err=\n\t%v\n", err)
			return
		}
	}
	// _mt.Println("\tArsenalNet.makeArsenal()")
	{ // Контроль ремки по времени суток и минимальному количеству
		iRemka := sf.Remka().Get()
		if iRemka < 70 {
			fnMakeRemka()
			return
		}
	}
	{ // Контроль по числу снарядов. В равных долях без приоритетов
		iFugas := sf.Fugas().Get()
		iKumul := sf.Kumul().Get()
		iArmor := sf.Armor().Get()

		typeArmor := "fugas"
		typeVal := iFugas

		if iKumul < typeVal {
			typeArmor = "kumul"
			typeVal = iKumul
		}

		if iArmor < typeVal {
			typeArmor = "armor"
		}
		switch typeArmor {
		case "fugas": // Мало фугасов
			sf.makeFugas()
		case "kumul": // Мало кумулятивов
			sf.makeKumul()
		case "armor": // Мало бронебойных
			sf.makeArmor()
		default:
			// log._rintf("ERRO ArsenalNet.makeArsenal(): неизвестный тип арсенала(%v)", typeArmor)
		}
	}
}

// Создать бронебойные
func (sf *Arsenal) makeArmor() {
	var (
		strOut     string
		lstArsenal = sf.GetLst()
		isFind     bool
	)
	for ind, strArmor := range lstArsenal {
		if strings.Contains(strArmor, `<span class="green2">Бронебойный снаряд</span><br/>`) {
			strOut = lstArsenal[ind+10]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if strOut == `<div class="clrb"></div>` { // Уже запущено производство
		return
	}
	if strOut == `</div></div></div></div></div></div></div></div>` { // Уже запущено производство
		return
	}
	// Получить ссылку на бронебойные
	lstArmor := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstArmor[1]
	lstArmor = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "http://wartank.ru/production/" + lstArmor[0]
	if _, err := sf.net.Get(strLink); err != nil {
		// log._rintf("ERRO ArsenalNet.makeArmor(): in update lstArsenal,  err=\n\t%v\n", err)
		return
	}
	sf.ModeCurrent().WorkSet("бронебойные")
}

// Создать кумулятивные
func (sf *Arsenal) makeKumul() {
	var (
		strOut     string
		lstArsenal = sf.GetLst()
		isFind     bool
		ind        int
	)
	for ind, strOut = range lstArsenal {
		if strings.Contains(strOut, `<span class="green2">Кумулятивный снаряд</span><br/>`) {
			ind += 10
			strOut = lstArsenal[ind]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `>Начать производство<`) {
		return
	}
	// Получить ссылку на кумулятив
	lstKumul := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstKumul[1]
	lstKumul = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "http://wartank.ru/production/" + lstKumul[0]
	if _, err := sf.net.Get(strLink); err != nil {
		// log._rintf("ERRO ArsenalNet.makeKumul(): in make product arsenal kumul , err=\n\t%v\n", err)
		return
	}
	sf.ModeCurrent().WorkSet("кумулятивы")
}

// Создать фугасы
func (sf *Arsenal) makeFugas() {
	var (
		lstArsenal = sf.GetLst()
		strOut     = ""
		isFind     bool
		ind        int
	)

	for ind, strOut = range lstArsenal {
		if strings.Contains(strOut, `<span class="green2">Фугасный снаряд</span><br/>`) {
			strOut = lstArsenal[ind+10]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `"><span><span>Начать производство</span></span></a>`) {
		return
	}
	// Получить ссылку на ремку
	lstKumul := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstKumul[1]
	lstKumul = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "http://wartank.ru/production/" + lstKumul[0]
	if _, err := sf.net.Get(strLink); err != nil {
		// log._rintf("ERRO ArsenalNet.makeFugas(): in make request arsenal product, err=\n\t%v\n", err)
		return
	}
	sf.ModeCurrent().WorkSet("фугасы")
	// log._rintf("INFO Arsenal.makeFugas()\n")
}

// Создать ремку. Выполняется если подходят условия
func (sf *Arsenal) makeRemka() (err error) {
	// _mt.Println("\tArsenalNet.makeRemka()")
	var (
		strOut     = ""
		isFind     bool
		lstArsenal = sf.GetLst()
	)

	for ind, strRemka := range lstArsenal {
		if strings.Contains(strRemka, `<span class="green2">Ремкомплект</span><br/>`) {
			ind += 10
			strOut = lstArsenal[ind]
			isFind = true
			break
		}
	}
	if !isFind {
		return nil
	}
	// Получить ссылку на ремку
	lstRemka := strings.Split(strOut, `<a class="simple-but border" href="`)
	if len(lstRemka) < 2 { // Значит уже запущено в производство
		return
	}
	strLink := lstRemka[1]
	lstRemka = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "http://wartank.ru/production/Armory" + lstRemka[0]
	if _, err = sf.net.Get(strLink); err != nil {
		return fmt.Errorf("ArsenalNet.makeRemka(): in getpagebank product, err=\n\t%w", err)
	}
	sf.ModeCurrent().WorkSet("ремка")
	return nil
}
