package base

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"wartank/pkg/components/section"
	"wartank/pkg/components/sound"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/base/arsenal"
	"wartank/server/serv_bots/warbot/angar/base/bank"
	"wartank/server/serv_bots/warbot/angar/base/basenet"
	"wartank/server/serv_bots/warbot/angar/base/market"
	"wartank/server/serv_bots/warbot/angar/base/mine"
	"wartank/server/serv_bots/warbot/angar/base/polygon"
	"wartank/server/serv_bots/warbot/angar/battle"
)

/*
	Объект базы в игре.
*/

const (
	forceTimePay  = 60   // Время ожидания платного ускорения
	forceTimeFree = 1810 // Время ожидания бесплатного ускорения

)

// Base -- объект базы
type Base struct {
	*section.Section
	net       *basenet.BaseNet
	server    types.IServer
	bot       types.IServBot
	arsenal   *arsenal.Arsenal
	bank      *bank.Bank
	polygon   *polygon.Polygon
	mine      *mine.Mine
	battle    types.IBattle
	market    *market.Market
	timeSleep int // Сколько времени спать до опроса базы
	block     sync.Mutex
}

// NewBase -- возвращает новый *Base
func NewBase(server types.IServer, bot types.IServBot) (*Base, error) {
	log.Printf("NewBase()\n")
	{ // Предусловия
		if server == nil {
			return nil, fmt.Errorf("NewBase(): IApp is nil")
		}
		if bot == nil {
			return nil, fmt.Errorf("NewBase(): client is nil")
		}
	}
	sf := &Base{
		server: server,
		bot:    bot,
	}
	return sf, nil
}

func (sf *Base) make() error {
	log.Printf("Base.make()\n")
	sf.block.Lock()
	defer sf.block.Unlock()
	var err error
	{ // Arsenal
		sf.arsenal, err = arsenal.NewArsenal(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): in create IArsenal, err=\n\t%w", err)
		}
	}
	{ // Bank
		sf.bank, err = bank.NewBank(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): in create IBank, err=\n\t%w", err)
		}
	}
	{ // Mine
		sf.mine, err = mine.NewMine(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): in create IMine, err=\n\t%w", err)
		}
	}
	{ // Battle
		sf.battle, err = battle.NewBattle(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): in create IBattle, err=\n\t%w", err)
		}
	}
	{ // Market
		sf.market, err = market.NewMarket(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): при создании IMarket, err=\n\t%w", err)
		}
	}
	{ // Polygon
		sf.polygon, err = polygon.NewPolygon(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): in create IPolygon, err=\n\t%w", err)
		}
	}
	{ // Section
		sf.Section, err = section.NewSection(sf.server, `<title>База</title>`)
		if err != nil {
			return fmt.Errorf("Base.make(): in create *Section, err=\n\t%w", err)
		}
	}
	{ // База в сети
		sf.net, err = basenet.NewBaseNet(sf.server, sf.bot)
		if err != nil {
			return fmt.Errorf("Base.make(): in create NetBase, err=\n\t%w", err)
		}
	}
	return nil
}

// Запускает компоненты
func (sf *Base) run() error {
	log.Printf("Base.run()\n")
	sf.block.Lock()
	defer sf.block.Unlock()
	if err := sf.arsenal.Run(); err != nil {
		return fmt.Errorf("Base.run(): in run IArsenal, err=\n\t%w", err)
	}
	if err := sf.bank.Run(); err != nil {
		return fmt.Errorf("Base.run(): in run IBank, err=\n\t%w", err)
	}
	if err := sf.mine.Run(); err != nil {
		return fmt.Errorf("Base.run(): in run IMine, err=\n\t%w", err)
	}
	if err := sf.market.Run(); err != nil {
		return fmt.Errorf("Base.run(): in run IMarket, err=\n\t%w", err)
	}
	if err := sf.polygon.Run(); err != nil {
		return fmt.Errorf("Base.run(): in run IPolygon, err=\n\t%w", err)
	}
	return nil
}

// Запускает базу в обработку
func (sf *Base) Run() error {
	log.Printf("Base.Run()\n")
	if err := sf.make(); err != nil {
		return fmt.Errorf("Base.Run(): make, err=\n\t%w", err)
	}
	if err := sf.run(); err != nil {
		return fmt.Errorf("Base.Run(): run, err=\n\t%w", err)
	}
	go func() {
		for {
			select {
			case <-sf.server.Done():
				sf.CountDown().Stop()
			case <-sf.CountDown().ChanSig():
				if err := sf.net.UpdateLst("Base.run()"); err != nil { // Обновить состояние базы
					log.Printf("ERRO Base.Run(): при обновлении базы, err=\n\t%v\n", err)
				}
				sf.checkPolygonForce()
				if err := sf.checkBank(); err != nil { // Проверка режимов банка
					log.Printf("ERRO Base.Run(): при проверке банка, err=\n\t%v\n", err)
				}
				sf.checkArsenal()
				sf.checkMine() // Проверка шахты
				sf.setCountDown()
				time.Sleep(time.Second * time.Duration(sf.timeSleep))
				// sf.CountDown().Set(45)
			}
		}
	}()
	return nil
}

func (sf *Base) setCountDown() {
	timeBase := sf.bank.CountDown().Get()
	timeCount := timeBase
	timeArsenal := sf.arsenal.CountDown().Get()
	timeMine := sf.mine.CountDown().Get()
	if timeArsenal < timeCount {
		timeCount = timeArsenal
	}
	if timeMine < timeCount {
		timeCount = timeMine
	}
	if timeCount <= 1 {
		sf.timeSleep = 5
		return
	}
	if timeCount > (600) {
		sf.timeSleep = 600
	}
}

// Arsenal -- возвращает объект арсенала
func (sf *Base) Arsenal() types.IArsenal {
	return sf.arsenal
}

// Bank -- возвращает объект банка
func (sf *Base) Bank() types.IBank {
	sf.block.Lock()
	defer sf.block.Unlock()
	return sf.bank
}

// Polygon -- возвращает объект полигона
func (sf *Base) Polygon() types.IPolygon {
	return sf.polygon
}

// Mine -- возвращает объект шахты
func (sf *Base) Mine() types.IMine {
	return sf.mine
}

// Battle -- возвращает объект сражения
func (sf *Base) Battle() types.IBattle {
	return sf.battle
}

// Market -- возвращает объект рынка
func (sf *Base) Market() types.IMarket {
	return sf.market
}

// Проверяет на забрать шахту
func (sf *Base) checkMine() {
	countTime := sf.mine.CountDown().Get()
	if countTime > 3 {
		return
	}
	if sf.mine.Ruda().Get() == 0 {
		sf.checkMineStat()
	}
	sf.checkMineForce() // Нужно ли ускорить апгрейд шахты
	if sf.mine.ModeCurrent().Get() == "upgrade" {
		return
	}
	sf.checkMineStat()
	sf.checkMineGet()     // Нужно ли забрать из шахты
	sf.checkMineProduct() // Нужно ли производство в шахте

	sf.checkMineTime()
}

// Проверяет время ожидания шахты
func (sf *Base) checkMineTime() {
	var (
		lstBase = sf.GetLst()
		strOut  string
		isFind  bool
		ind     int
	)
	for ind, strOut = range lstBase {
		if !strings.Contains(strOut, `<span class="green2">Шахта - `) {
			continue
		}
		ind += 11
		strOut = lstBase[ind]
		isFind = true
		break
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `<td><div class="value-block lh1"><span><span>`) {
		return
	}
	lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
	strTime := lstTime[1]
	lstTime = strings.Split(strTime, `</span></span></div></td>`)
	strTime = lstTime[0]
	if err := sf.mine.CountDown().Parse(strTime); err != nil {
		log.Printf("ERRO Base.checkMineTime(): при установке обратного отсчёта(%v), err=\n\t%v\n", strTime, err)
	}
}

// Проверяет на забор из шахты
func (sf *Base) checkMineGet() {
	var (
		strOut  string
		ind     int
		isFind  bool
		lstBase = sf.GetLst()
	)
	for ind, strOut = range lstBase {
		if strings.Contains(strOut, `<span class="green2">Шахта -`) {
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	ind += 18
	strOut = lstBase[ind]
	if !strings.Contains(strOut, `"><span><span>Забрать</span></span></a>`) {
		return
	}
	lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Забрать</span></span></a>`)
	strLink = "http://wartank.ru/" + lstLink[0]
	lstBase1, err := sf.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Base.checkMineGet(): при выполнении Get-запроса 'забрать', err=\n\t%v\n", err)
		return
	}
	if err = sf.mine.Update(lstBase1); err != nil {
		// log._rintf("ERRO Base.checkMineGet(): при обновлении lstMine, err=\n\t%v\n", err)
		return
	}
	sf.mine.CountDown().Set(1)
}

// Проверка статистики шахты
func (sf *Base) checkMineStat() {
	var (
		lstMine = sf.GetLst()
		strOut  string
		isFind  bool
		ind     int
	)
	{ // Ищем руду
		for _, strOut = range lstMine {
			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/ore.png?2" alt="Руда" title="Руда"/>`) {
				isFind = true
				break
			}
		}
		if isFind && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/ore.png?2" alt="Руда" title="Руда"/> `) {
			lstRuda := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/ore.png?2" alt="Руда" title="Руда"/> `)
			strRuda := lstRuda[1]
			lstRuda = strings.Split(strRuda, ` &nbsp;&nbsp;</span>`)
			strRuda = lstRuda[0]
			iRuda, err := strconv.Atoi(strRuda)
			if err != nil {
				log.Printf("ERRO Base.checkMineStat(): руда(%v) не число, err=\n\t%v\n", strRuda, err)
				return
			}
			sf.mine.Ruda().Set(iRuda)
		}
	}
	{ // Ищем железо
		for _, strOut = range lstMine {
			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/iron.png?2" alt="Железо" title="Железо"/> `) {
				isFind = true
				break
			}
		}
		if isFind && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/iron.png?2" alt="Железо" title="Железо"/> `) {
			lstFerrum := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/iron.png?2" alt="Железо" title="Железо"/> `)
			strFerrum := lstFerrum[1]
			lstFerrum = strings.Split(strFerrum, ` &nbsp;&nbsp;</span>`)
			strFerrum = lstFerrum[0]
			iFerrum, err := strconv.Atoi(strFerrum)
			if err != nil {
				log.Printf("ERRO Base.checkMineStat(): железо(%v) не число, err=\n\t%v\n", strFerrum, err)
				return
			}
			sf.mine.Ferrum().Set(iFerrum)
		}
	}
	{ // Ищем сталь
		for _, strOut = range lstMine {
			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/steel.png?2" alt="Сталь" title="Сталь"/> `) {
				isFind = true
				break
			}
		}
		if isFind && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/steel.png?2" alt="Сталь" title="Сталь"/> `) {
			lstSteel := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/steel.png?2" alt="Сталь" title="Сталь"/> `)
			strSteel := lstSteel[1]
			lstSteel = strings.Split(strSteel, ` &nbsp;&nbsp;</span>`)
			strSteel = lstSteel[0]
			iSteel, err := strconv.Atoi(strSteel)
			if err != nil {
				log.Printf("ERRO Base.checkMineStat(): сталь(%v) не число, err=\n\t%v\n", strSteel, err)
				return
			}
			sf.mine.Steel().Set(iSteel)
		}
	}
	{ // Ищем свинец
		for _, strOut = range lstMine {
			if strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/plumbum.png?2" alt="Свинец" title="Свинец"/> `) {
				isFind = true
				break
			}
		}
		if isFind && strings.Contains(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/plumbum.png?2" alt="Свинец" title="Свинец"/> `) {
			lstPlumbum := strings.Split(strOut, `<span class="nwr"><img class="rico vm" src="/images/icons/plumbum.png?2" alt="Свинец" title="Свинец"/> `)
			strPlumbum := lstPlumbum[1]
			lstPlumbum = strings.Split(strPlumbum, ` &nbsp;&nbsp;</span>`)
			strPlumbum = lstPlumbum[0]
			iPlumbum, err := strconv.Atoi(strPlumbum)
			if err != nil {
				log.Printf("ERRO Base.checkMineStat(): свинец(%v) не число, err=\n\t%v\n", strPlumbum, err)
				return
			}
			sf.mine.Plumbum().Set(iPlumbum)
		}
	}
	{ // Ищем время обработки и режим
		lstBase := sf.GetLst()
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `<span class="green2">Шахта - `) {
				isFind = true
				ind += 11
				strOut = lstBase[ind]
				break
			}
		}
		if isFind && strings.Contains(strOut, `<td><div class="value-block lh1"><span><span>`) {
			lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
			strTime := lstTime[1]
			lstTime = strings.Split(strTime, `</span></span></div></td>`)
			strTime = lstTime[0]
			if err := sf.mine.CountDown().Parse(strTime); err != nil {
				log.Printf("ERRO Base.checkMineStat(): при установке времени ожидания шахты(%v)\n\terr=%v\n", strTime, err)
			}
		}

		ind -= 3
		if ind < 0 {
			log.Printf("Base.checkMineStat(): отрицательный индекс(%v)!\n", ind)
			return
		}
		strOut = lstBase[ind]
		switch {
		case strings.Contains(strOut, `/images/icons/iron.png`): // Железо
			lstNum := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/iron.png?2" alt="iron"/>&nbsp;`)
			strNum := lstNum[1]
			lstNum = strings.Split(strNum, `</div></td>`)
			strNum = lstNum[0]
			sf.mine.ModeCurrent().WorkSet("Железо-" + strNum)
		case strings.Contains(strOut, `/images/icons/ore.png`): // Руда
			lstNum := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/ore.png?2" alt="ore"/>&nbsp;`)
			strNum := lstNum[1]
			lstNum = strings.Split(strNum, `</div></td>`)
			strNum = lstNum[0]
			sf.mine.ModeCurrent().WorkSet("Руда-" + strNum)
		case strings.Contains(strOut, `/images/icons/steel.png`): // Руда
			lstNum := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/steel.png?2" alt="steel"/>&nbsp;`)
			strNum := lstNum[1]
			lstNum = strings.Split(strNum, `</div></td>`)
			strNum = lstNum[0]
			sf.mine.ModeCurrent().WorkSet("Сталь-" + strNum)
		}
	}
}

// Проверяет на необходимость производства
func (sf *Base) checkMineProduct() {
	var (
		strOut  string
		ind     int
		isFind  bool
		lstBase = sf.GetLst()
	)
	for ind, strOut = range lstBase {
		if strings.Contains(strOut, `<span class="green2">Шахта -`) {
			isFind = true
			ind += 12
			strOut = lstBase[ind]
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `"><span><span>Производство</span></span></a>`) {
		return
	}
	sf.mine.NumProduct().Set(0)
	sf.mine.CountDown().Set(1)
}

// Проверяет режимы арсенала
func (sf *Base) checkArsenal() {
	countTime := sf.arsenal.CountDown().Get()
	if countTime > 3 {
		return
	}
	if err := sf.arsenal.UpdateArsenal(); err != nil {
		// log._rintf("ERRO Base.checkArsenal(): при обновлении арсенала, err=\n\t%v\n", err)
		return
	}
	if mode := sf.arsenal.ModeCurrent().Work(); mode == "" {
		sf.checkArsenalMode()
	}
	sf.checkArsenalForce() // Нужно ли ускорить апгрейд арсенала
	if sf.arsenal.ModeCurrent().Get() == "upgrade" {
		return
	}
	sf.checkArsenalGet() // Нужно ли забрать оружие
	sf.checkArsenalTime()
	sf.checkArsenalMode()
}

// Проверяет время готовности арсенала
func (sf *Base) checkArsenalTime() {
	var (
		lstBase = sf.GetLst()
		ind     int
		strOut  string
		isFind  bool
	)
	for ind, strOut = range lstBase {
		if !strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
			continue
		}
		ind += 10
		strOut = lstBase[ind]
		isFind = true
		break
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, ":") {
		return
	}
	lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
	if len(lstTime) != 2 { // Возможно, производство
		return
	}
	strTime := lstTime[1]
	lstTime = strings.Split(strTime, `</span></span></div></td>`)
	strTime = lstTime[0]
	if err := sf.arsenal.CountDown().Parse(strTime); err != nil {
		log.Printf("ERRO Base.checkArsenalTime(): при установке времени ожидания арсенала(%v)\n\terr=%v\n", strTime, err)
	}
}

// Проверяет на забрать оружейную
func (sf *Base) checkArsenalGet() {
	var (
		strOut  string
		ind     int
		isFind  bool
		lstBase = sf.GetLst()
	)
	for ind, strOut = range lstBase {
		if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
			isFind = true
			ind += 17
			strOut = lstBase[ind]
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `"><span><span>Забрать</span></span></a>`) {
		return
	}
	lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Забрать</span></span></a>`)
	// http://wartank.ru/buildings?80-1.ILinkListener-buildings-0-building-rootBlock-actionPanel-takeProductionLink
	strLink = "http://wartank.ru/" + lstLink[0]
	lstBase, err := sf.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Base.checkArsenalGet(): при выполнении Get-запроса 'забрать', err=\n\t%v\n", err)
		return
	}
	if len(lstBase) == 0 {
		// log._rintf("ERRO Base.checkArsenalGet(): len lstBase(%v)==0", len(lstBase))
		return
	}
	isFind = false
	for _, strOut = range lstBase {
		if strings.Contains(strOut, `<title>Производство</title>`) {
			isFind = true
			break
		}
	}
	sf.arsenal.CountDown().Set(1)
	if isFind {
		if err = sf.arsenal.Update(lstBase); err != nil {
			log.Printf("ERRO Base.checkArsenalGet(): при обновлении lstArsenal, err=\n\t%v\n", err)
		}
		return
	}
	if err = sf.Update(lstBase); err != nil {
		log.Printf("ERRO Base.checkArsenalGet(): при обновлении lstBase, err=\n\t%v\n", err)
	}
}

// Проверяетрежим производства арсенала
func (sf *Base) checkArsenalMode() {
	var (
		strOut  string
		lstBase = sf.GetLst()
	)
	for _, strOut = range lstBase {
		if strings.Contains(strOut, `HollowCharge.png`) {
			sf.arsenal.ModeCurrent().WorkSet("кумулятивы")
			return
		}
		if strings.Contains(strOut, `ArmorPiercing.png`) {
			sf.arsenal.ModeCurrent().WorkSet("бронебойки")
			return
		}
		if strings.Contains(strOut, `HighExplosive.png`) {
			sf.arsenal.ModeCurrent().WorkSet("фугасы")
			return
		}
		if strings.Contains(strOut, `repairkit.gif`) {
			sf.arsenal.ModeCurrent().WorkSet("ремка")
			return
		}
	}
}

// Проверяет на ускорение апгрейда арсенала
func (sf *Base) checkArsenalForce() {
	var (
		ind     int
		strOut  = ""
		isFind  bool
		lstBase = sf.GetLst()
	)
	{ // Проверка на платное ускорение апгрейда + время
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
				// Убедиться что есть строка платного ускорения
				isFind = true
				ind += 29
				strOut = lstBase[ind]
				break
			}
		}
		if !isFind {
			return
		}
		{ // Платное ускорение
			if strings.Contains(strOut, `Ускорить за`) {
				if err := sf.arsenal.CountDown().Set(forceTimePay); err != nil {
					log.Printf("WARN Base.checkArsenalForce(): при установке платного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", forceTimePay, err)
				}
				sf.arsenal.ModeCurrent().Set("upgrade")
				sf.arsenal.ModeCurrent().WorkSet("апгрейд")
				return
			}
		}
	}
	{ // Проверка на бесплатное ускорение апгрейда
		isFind = false
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит снаряды, ремкомплекты<br/>`) {
				// Убедиться что есть строка платного ускорения
				isFind = true
				ind += 26
				strOut = lstBase[ind]
				break
			}
		}
		if !isFind {
			return
		}
		if !strings.Contains(strOut, `>Ускорение<`) {
			return
		}
		sf.arsenal.ModeCurrent().Set("upgrade")
		lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
		strLink := lstLink[1]
		lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
		strLink = "http://wartank.ru/" + lstLink[0]
		lstBase, err := sf.net.Get(strLink)
		if err != nil {
			// log._rintf("ERRO NetBank.checkArsenalForce(): при GET-запросе на бесплатном ускорении апгрейда арсенала, err=\n\t%v\n", err)
			return
		}
		// sound.ArsenalForce()
		if err := sf.Update(lstBase); err != nil {
			// log._rintf("ERRO NetBank.checkArsenalForce(): при обновлении lstBase, err=\n\t%v\n", err)
			return
		}
		sf.arsenal.ModeCurrent().Set("upgrade")
		sf.arsenal.ModeCurrent().WorkSet("апгрейд")
		if err := sf.arsenal.CountDown().Set(forceTimeFree); err != nil {
			log.Printf("WARN Base.checkArsenalForce(): при установке бесплатного времени ускорения апгрейда арсенала(%v)\n\terr=%v\n", forceTimeFree, err)
		}
	}
	// Все проверки прошли -- это просто работа
	sf.arsenal.ModeCurrent().Set("work")
}

// Проверяет режим банка
func (sf *Base) checkBank() error {
	if sf.bank.ModeCurrent().Work() == "" {
		sf.checkBankMode()
	}
	sf.checkBankTime() // Проверка времени ожидания
	countTime := sf.bank.CountDown().Get()
	if countTime > 5 {
		return nil
	}
	sf.checkBankForce() // Нужно ли ускорить апгрейд банка
	if sf.bank.ModeCurrent().Get() == "upgrade" {
		return nil
	}
	sf.checkBankTake()    // Нужно ли забрать банк
	sf.checkBankProduct() // Запуск производства в  банке
	return nil
}

// Проверяет режим работы банка
func (sf *Base) checkBankMode() {
	var (
		strOut  string
		isFind  bool
		lstBase = sf.GetLst()
	)
	for _, strOut = range lstBase {
		if strings.Contains(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/silver.png?2" alt="silver"/>&nbsp;`) {
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	lstSilver := strings.Split(strOut, `<td class="vam"><div class="nwr pr5 gray1"><img class="rico vm" src="/images/icons/silver.png?2" alt="silver"/>&nbsp;`)
	strSilver := lstSilver[1]
	lstSilver = strings.Split(strSilver, `</div></td>`)
	strSilver = "Серебро-" + lstSilver[0]
	sf.bank.ModeCurrent().WorkSet(strSilver)

}

// Проверяет на время ожидания банка
func (sf *Base) checkBankTime() {
	var (
		strOut  string
		ind     int
		isFind  bool
		lstBase = sf.GetLst()
	)
	for ind, strOut = range lstBase {
		if strings.Contains(strOut, `Производит серебро<br/>`) {
			isFind = true
			ind += 10
			strOut = lstBase[ind]
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `<td><div class="value-block lh1"><span><span>`) {
		return
	}
	lstTime := strings.Split(strOut, `<td><div class="value-block lh1"><span><span>`)
	strTime := lstTime[1]
	lstTime = strings.Split(strTime, `</span></span></div></td>`)
	strTime = lstTime[0]
	if err := sf.bank.CountDown().Parse(strTime); err != nil {
		log.Printf("ERRO Base.checkBankTime(): при установке времени ожидания банка(%v)\n\terr=%v\n", strTime, err)
	}
}

// Проверяет на произвести в банке
func (sf *Base) checkBankProduct() {
	var (
		strOut  string
		ind     int
		isFind  bool
		lstBase = sf.GetLst()
	)
	for ind, strOut = range lstBase {
		if strings.Contains(strOut, `Производит серебро<br/>`) {
			isFind = true
			ind += 11
			strOut = lstBase[ind]
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strOut, `>Производство</span>`) {
		return
	}
	sf.bank.UpdateLst()
	sf.bank.CountDown().Set(1)
}

// Проверка получения серебра из банка
func (sf *Base) checkBankTake() {
	var (
		ind     int
		strOut  string
		isFind  bool
		lstBank = sf.GetLst()
		strLink string
	)
	for ind, strOut = range lstBank {
		if strings.Contains(strOut, `<span class="green2">Банк - `) {
			ind += 18
			strLink = lstBank[ind]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strLink, `"><span><span>Забрать</span></span></a>`) {
		return
	}
	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
	strLink = lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Забрать</span></span></a>`)
	strLink = "http://wartank.ru/" + lstLink[0]
	lstBank, err := sf.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Base.checkBankTake(): при выполнении GET-запроса 'забрать серебро', err=\n\t%v\n", err)
		return
	}
	sound.BankTake()
	isFind = false
	for _, strOut = range lstBank { // Проверка на производство в банке
		if strings.Contains(strOut, `<title>Производство</title>`) {
			isFind = true
			break
		}
	}
	if isFind {
		if err := sf.bank.Update(lstBank); err != nil {
			log.Printf("ERRO Base.checkBankTake(): при установке lstBank, err=\n\t%v'n", err)
		}
		sf.bank.CountDown().Set(1)
		return
	}
	if err := sf.Update(lstBank); err != nil {
		log.Printf("ERRO Base.checkBankTake(): при установке lstBase, err=\n\t%v'n", err)
	}
	sf.bank.CountDown().Set(1)
}

// Проверяет на ускорение апгрейда банка
func (sf *Base) checkBankForce() {
	var (
		ind     int
		strOut  = ""
		isOut   bool
		lstBase = sf.GetLst()
	)
	{ // Проверка на платное ускорение апгрейда
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит серебро<br/>`) {
				// Убедиться что есть строка платного ускорения
				isOut = true
				ind += 29
				strOut = lstBase[ind]
				break
			}
		}
		if isOut && strings.Contains(strOut, `Ускорить за`) {
			if err := sf.bank.CountDown().Set(forceTimePay); err != nil {
				log.Printf("WARN Base.checkBankForce(): при установке времени ожидания платного ускорения апгрейда банка(%v)\n\terr=%v\n", forceTimePay, err)
			}
			sf.bank.ModeCurrent().Set("upgrade")
			sf.bank.ModeCurrent().WorkSet("апгрейд")
			return
		}
	}
	{ // Проверка на бесплатное ускорение апгрейда
		isOut = false
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит серебро<br/>`) {
				// Убедиться что есть строка платного ускорения
				isOut = true
				ind += 26
				strOut = lstBase[ind]
				break
			}
		}
		if isOut && strings.Contains(strOut, `>Ускорение<`) {

			lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
			strLink := lstLink[1]
			lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
			strLink = "http://wartank.ru/" + lstLink[0]
			lstBase, err := sf.net.Get(strLink)
			if err != nil {
				// log._rintf("ERRO NetBank.checkBankForce(): при GET-запросе на бесплатном ускорении апгрейда банка, err=\n\t%v\n", err)
				return
			}
			if err := sf.Update(lstBase); err != nil {
				// log._rintf("ERRO NetBank.checkBankForce(): при обновлении lstBase, err=\n\t%v\n", err)
				return
			}
			sf.bank.ModeCurrent().Set("upgrade")
			sf.bank.ModeCurrent().WorkSet("апгрейд")
			if err := sf.bank.CountDown().Set(forceTimeFree); err != nil {
				log.Printf("WARN Base.checkBankForce(): при установке времени бесплатного ускорения агрейда банка(%v)\n\terr=%v\n", forceTimeFree, err)
			}
		}
	}
}

// Проверяет на ускорение апгрейда шахты
func (sf *Base) checkMineForce() {
	var (
		ind     int
		strOut  = ""
		isOut   bool
		lstBase = sf.GetLst()
	)
	{ // Проверка на платное ускорение апгрейда
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит ресурсы<br/>`) {
				// Убедиться что есть строка платного ускорения
				isOut = true
				ind += 29
				strOut = lstBase[ind]
				break
			}
		}
		if isOut && strings.Contains(strOut, `Ускорить за`) {
			sf.mine.ModeCurrent().Set("upgrade")
			sf.mine.ModeCurrent().WorkSet("апгрейд")
			if err := sf.mine.CountDown().Set(forceTimePay); err != nil {
				log.Printf("WARN Base.checkMineForce(): при установке времени платного апгрейда шахты(%v)\n\terr=%v\n", forceTimePay, err)
			}
			return
		}
	}
	{ // Проверка на время бесплатного ускорение апгрейда
		isOut = false
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит ресурсы<br/>`) {
				// Убедиться что есть строка платного ускорения
				isOut = true
				ind += 26
				strOut = lstBase[ind]
				break
			}
		}
		if isOut && strings.Contains(strOut, `>Ускорение<`) {
			lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
			strLink := lstLink[1]
			lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
			strLink = "http://wartank.ru/" + lstLink[0]
			lstBase, err := sf.net.Get(strLink)
			if err != nil {
				// log._rintf("ERRO NetBank.checkMineForce(): при GET-запросе на бесплатном ускорении апгрейда шахты, err=\n\t%v\n", err)
				return
			}
			if err := sf.Update(lstBase); err != nil {
				// log._rintf("ERRO NetBank.checkMineForce(): при обновлении lstBase, err=\n\t%v\n", err)
				return
			}
			if err := sf.mine.CountDown().Set(forceTimeFree); err != nil {
				log.Printf("WARN Base.checkMineForce(): при установке времени апгрейда шахты(%v)\n\terr=%v\n", forceTimeFree, err)
			}
			// sound.MineForce()
			sf.mine.ModeCurrent().Set("upgrade")
			sf.mine.ModeCurrent().WorkSet("апгрейд")
			return
		}
	}
	// Все проверки прошли -- это просто работа
	sf.mine.ModeCurrent().Set("work")
}

// Проверяет на ускорение апгрейда полигона
func (sf *Base) checkPolygonForce() {
	var (
		ind     int
		strOut  = ""
		isOut   bool
		lstBase = sf.GetLst()
	)
	countTime := sf.polygon.CountDown().Get()
	if countTime > 3 {
		return
	}
	{ // Проверка на платное ускорение апгрейда
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит усиление танка<br/>`) {
				// Убедиться что есть строка платного ускорения
				isOut = true
				ind += 29
				strOut = lstBase[ind]
				break
			}
		}
		if isOut && strings.Contains(strOut, `Ускорить за`) {
			// strTime := lstBase[ind-21]
			// lstTime := strings.Split(strTime, `<td><div class="value-block lh1"><span><span>`)
			// strTime = lstTime[1]
			// lstTime = strings.Split(strTime, `</span></span></div></td>`)
			// strTime = lstTime[0]
			// if err := sf.polygon.CountDown().Set(strTime); err != nil {
			// 	// log._rintf("WARN Base.checkMineForce(): при установке времени апгрейда полигона(%v)\n\terr=%v\n", strTime, err)
			// }
			sf.polygon.ModeCurrent().Set("upgrade")
			sf.polygon.ModeCurrent().WorkSet("апгрейд")
			if err := sf.polygon.CountDown().Set(forceTimePay); err != nil {
				log.Printf("WARN Base.checkPolygonForce(): при установке платного времени апгрейда полигона(%v)\n\terr=%v\n", forceTimePay, err)
			}
			return
		}
	}
	{ // Проверка на бесплатное ускорение апгрейда
		isOut = false
		for ind, strOut = range lstBase {
			if strings.Contains(strOut, `Производит усиление танка<br/>`) {
				// Убедиться что есть строка платного ускорения
				isOut = true
				ind += 26
				strOut = lstBase[ind]
				break
			}
		}
		if isOut && strings.Contains(strOut, `>Ускорение<`) {
			lstLink := strings.Split(strOut, `<td style="width:50%;padding-left:1px;"><a class="simple-but border" href="`)
			strLink := lstLink[1]
			lstLink = strings.Split(strLink, `"><span><span>Ускорение</span></span></a>`)
			strLink = "http://wartank.ru/" + lstLink[0]
			lstBase, err := sf.net.Get(strLink)
			if err != nil {
				// log._rintf("ERRO NetBank.checkPolygonForce(): при GET-запросе на бесплатном ускорении апгрейда полигона, err=\n\t%v\n", err)
				return
			}
			if err := sf.Update(lstBase); err != nil {
				// log._rintf("ERRO NetBank.checkPolygonForce(): при обновлении lstBase, err=\n\t%v\n", err)
				return
			}
			// sound.MineForce()
			sf.polygon.ModeCurrent().Set("upgrade")
			sf.polygon.ModeCurrent().WorkSet("апгрейд")
			// Установить время ожидания для обновления
			if err := sf.polygon.CountDown().Set(forceTimeFree); err != nil {
				log.Printf("WARN Base.checkPolygonForce(): при установке времени бесплатного апгрейда полигона(%v)\n\terr=%v\n", forceTimeFree, err)
			}
			// log._rintf("INFO NetBank.checkPolygonForce(): ускорено строительство полигона\n")
			return
		}
	}
	// Все проверки прошли -- это просто работа
	sf.polygon.ModeCurrent().Set("work")
}
