package market

import (
	"fmt"
	"strings"

	"wartank/pkg/components/section"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/base/market/marketnet"
)

/*
	Объект рынка
*/

// Market -- объект рынка
type Market struct {
	*section.Section
	server types.IServer
	bot    types.IServBot
	net    *marketnet.MarketNet
}

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

func (sf *Market) Run() error {
	var err error
	{ // Секция
		sf.Section, err = section.NewSection(sf.server, `<title>Рынок</title>`)
		if err != nil {
			return fmt.Errorf("Market.Run(): in create *Section, err=\n\t%w", err)
		}
	}
	{ // Маркет
		sf.net, err = marketnet.NewMarketNet(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Market.Run(): in create NetMarket, err=\n\t%w", err)
		}
	}
	go sf.run()
	return nil
}

// выполняет опрос рынка базы, должен работать как горутина
func (sf *Market) run() {
	sf.CountDown().Set(25)
	for {
		select {
		case <-sf.server.Done():
			sf.CountDown().Stop()
			return
		case <-sf.CountDown().ChanSig():
			_ = sf.buyGold()
			// Если золото не куплено -- обновить время ожидания
			sf.checkTime()
		}
	}
}

// Проверяет  время ожидания рынка
func (sf *Market) checkTime() {
	var (
		strOut string
		isFind bool
	)
	// countDown := sf.CountDown().Get()
	fnIsSilver := func() bool { // Найти счётчик цены серебра
		if err := sf.net.UpdateLst("Рынок"); err != nil { // Принудительное ПЕРВОЕ обновление рынка
			// log._rintf("ERRO Market.checkTime(): при обновлении lstMarket, err=\n\t%v\n", err)
			return false
		}
		isFind := false
		lstMarket := sf.GetLst()
		for _, strOut = range lstMarket {
			if strings.Contains(strOut, `alt="Серебро" title="Серебро"> `) {
				isFind = true
				break
			}
		}
		if isFind {
			lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
			strSilver := lstSilver[1]
			switch strSilver {
			case "10", "50", "100", "500":
				return true
			default:
				return false
			}
		}
		return false
	}
	fnGetCountDown := func() { // Искать счётчик времени
		lstMarket := sf.GetLst()
		// Найти счётчик времени
		for _, strOut = range lstMarket {
			if strings.Contains(strOut, `Минимальная цена через `) {
				isFind = true
				break
			}
		}
		if !isFind {
			return // Минимальная цена
		}
		lstTime := strings.Split(strOut, `Минимальная цена через `)
		strTime := lstTime[1]
		if err := sf.CountDown().Parse(strTime); err != nil {
			// log._rintf("ERRO Market.checkTime(): при установке времени ожидания рынка(%v)\n\terr=%v\n", strTime, err)
			return // Возможно минимальная цена
		}
	}
	if fnIsSilver() {
		return
	}
	fnGetCountDown()
}

// Проверяет рынок на режим покупки
func (sf *Market) buyGold() bool {
	var (
		ind       int
		isFind    bool
		strOut    string
		lstMarket = sf.GetLst()
		strSilver string
	)
	for ind, strOut = range lstMarket {
		if strings.Contains(strOut, `alt="Серебро" title="Серебро"> `) {
			isFind = true
			break
		}
	}
	if isFind { // Найдена продажа золота за серебро
		lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
		strSilver = lstSilver[1]
		switch strSilver {
		case "10", "50", "100", "500": // Допустимые суммы трат
			ind -= 15
			strOut = lstMarket[ind]
			lstLink := strings.Split(strOut, `<a class="simple-but border mb5" href="`)
			if len(lstLink) < 2 {
				return false
			}
			strLink := lstLink[1]
			lstLink = strings.Split(strLink, `"><span><span>Получить `)
			strLink = "http://wartank.ru/" + lstLink[0]
			lstMarket, err := sf.net.Get(strLink)
			if err != nil {
				// log._rintf("ERRO Market.buyGold(): при выполнении GET-команды на покупку золота, err=\n\t%v\n", err)
				return true
			}
			for _, strOut = range lstMarket {
				if strings.Contains(strOut, `Ошибка на сервере. Сообщение админу уже отправлено.`) {
					// log._rintf("ERRO Market.buyGold(): при получении lstMarket, strHTML=%v, err=\nt%v\n", strOut, err)
					return false
				}
			}
			if err = sf.Update(lstMarket); err != nil {
				// log._rintf("Market.buyGold(): при обновлении lstMarket, err=\n\t%v\n", err)
				return true
			}
		default: // Недопустимая сумма, либо больше чем надо
			return false
		}
	}
	return true
}
