// package win_main -- главное коно бото-фермы
package win_main

import (
	"fmt"
	"image/color"
	"log"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/layout"
	"fyne.io/fyne/v2/widget"

	"wartank/pkg/types"
)

const (
	strMainPass = "Lera_07091978"
)

// WinMain -- главное окно приложения
type WinMain struct {
	fyne.Window
	serv           types.ИСервер
	app            fyne.App
	ботВход        string
	ботПароль      string
	boxLeft        *fyne.Container
	tabBot         *container.AppTabs // Просмотр параметров бота
	entLogin       *widget.Label      // Логин текущего бота
	entPass        *widget.Entry      // Пароль текущего бота
	checkAutoGame  *widget.Check      // Автоматически играть при старте
	lblFuel        *widget.Label      // Топливо бота
	lblGold        *widget.Label      // Золото бота
	lblSilver      *widget.Label      // Серебро
	lblGlory       *widget.Label      // Количество славы
	lblSpace       *widget.Label      // Разделитель к базе
	lblRuda        *widget.Label      // Количество руды
	lblFerrum      *widget.Label      // Количество железа
	lblSteel       *widget.Label      // Количество стали
	lblPlumbum     *widget.Label      // Количество свинца
	frmStatLeft    *widget.Form       // Левая колонка статистики
	frmStatRight   *widget.Form       // Правая колонка статистики
	lblAtack       *widget.Label      // Сила атаки
	lblArmor       *widget.Label      // Броня бота
	lblFyne        *widget.Label      // Точность бота
	lblHard        *widget.Label      // Прочность танка
	lblPower       *widget.Label      // Всего очков танка
	lblForce       *widget.Label      // Что усилено
	lblPolygonTime *widget.Label      // Время до окончания плигона
	lblPolygonMode *widget.Label      // Режим работы полигона
	lblMineTime    *widget.Label      // Время до окончания работы шахты
	lblMineMode    *widget.Label      // Режим работы шахты
	lblBankTime    *widget.Label      // Время ожидания банка
	lblBankMode    *widget.Label      // Режим работы бынка
	lblArsenalTime *widget.Label      // Время ожидания оружейной
	lblArsenalMode *widget.Label      // Режим работы Оружейной
	lblBattleTime  *widget.Label      // Время до начала сражения
}

// NewWinMain -- возвращает новое главное окно
func NewWinMain(serv types.ИСервер) (*WinMain, error) {
	if serv == nil {
		return nil, fmt.Errorf("NewWinMain(): IServer==nil")
	}
	sf := &WinMain{
		Window: serv.Gui().ФайнПрилож().NewWindow("Бото-ферма [wartank.ru]"),
		app:    serv.Gui().ФайнПрилож(),
		serv:   serv,
	}
	green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}
	text1 := canvas.NewText("Список ботов", green)

	btnAddBot := widget.NewButton("Добавить бота", sf.btnAddClick)
	btnExit := widget.NewButton("Выход", sf.btnExitClick)
	boxDown := container.NewHBox(btnAddBot, layout.NewSpacer(), btnExit)
	sf.entLogin = widget.NewLabel("")
	sf.entPass = widget.NewEntry()
	sf.checkAutoGame = widget.NewCheck("", sf.clickAutoGame)
	formLogin := &widget.Form{
		Items: []*widget.FormItem{ // we can specify items in the constructor
			{Text: "Логин", Widget: sf.entLogin},
			{Text: "Пароль", Widget: sf.entPass},
			{Text: "Авто игра", Widget: sf.checkAutoGame},
		},
	}
	tabLogin := container.NewTabItem("Логин", formLogin)

	sf.lblSpace = widget.NewLabel("======")
	itemSpace := widget.NewFormItem("==========", sf.lblSpace)

	{ // Левая колонка статистики
		sf.lblFuel = widget.NewLabel("0")
		itemFuel := widget.NewFormItem("Топливо", sf.lblFuel)
		sf.lblGold = widget.NewLabel("0")
		itemGold := widget.NewFormItem("Золото", sf.lblGold)
		sf.lblSilver = widget.NewLabel("0")
		itemSilver := widget.NewFormItem("Серебро", sf.lblSilver)
		sf.lblGlory = widget.NewLabel("0")
		itemGlory := widget.NewFormItem("Слава", sf.lblGlory)
		sf.lblRuda = widget.NewLabel("0")
		itemRuda := widget.NewFormItem("Руда", sf.lblRuda)
		sf.lblFerrum = widget.NewLabel("0")
		itemFerrum := widget.NewFormItem("Железо", sf.lblFerrum)
		sf.lblSteel = widget.NewLabel("0")
		itemSteel := widget.NewFormItem("Сталь", sf.lblSteel)
		sf.lblPlumbum = widget.NewLabel("0")
		itemPlumbum := widget.NewFormItem("Свинец", sf.lblPlumbum)
		sf.frmStatLeft = widget.NewForm(itemFuel, itemGold, itemSilver, itemGlory, itemSpace, itemRuda, itemFerrum, itemSteel, itemPlumbum)
	}
	{ // Правая колонка статистики
		sf.lblAtack = widget.NewLabel("0")
		itemAtack := widget.NewFormItem("Атака", sf.lblAtack)
		sf.lblArmor = widget.NewLabel("0")
		itemArmor := widget.NewFormItem("Броня", sf.lblArmor)
		sf.lblFyne = widget.NewLabel("0")
		itemFyne := widget.NewFormItem("Точность", sf.lblFyne)
		sf.lblHard = widget.NewLabel("0")
		itemHard := widget.NewFormItem("Прочность", sf.lblHard)
		sf.lblPower = widget.NewLabel("0")
		itemPower := widget.NewFormItem("Мощь", sf.lblPower)
		sf.lblForce = widget.NewLabel("None")
		itemForce := widget.NewFormItem("Усилено", sf.lblForce)

		sf.frmStatRight = widget.NewForm(itemAtack, itemArmor, itemFyne, itemHard, itemSpace, itemPower, itemForce)
	}

	hStat := container.NewHBox(sf.frmStatLeft, sf.frmStatRight)
	tabStat := container.NewTabItem("Статистика", hStat)

	lblEmpty := widget.NewLabel("")
	itemPolygon := widget.NewFormItem("Полигон", lblEmpty)
	sf.lblPolygonTime = widget.NewLabel("Время: 00:00:00")
	sf.lblPolygonMode = widget.NewLabel("Режим: None")
	hBoxPolygon := container.NewHBox(sf.lblPolygonTime, sf.lblPolygonMode)
	itemPolygonWork := widget.NewFormItem("Режим", hBoxPolygon)
	frmPolygon := widget.NewForm(itemPolygon, itemPolygonWork)

	itemMine := widget.NewFormItem("Шахта", lblEmpty)
	sf.lblMineTime = widget.NewLabel("Время: 00:00:00")
	sf.lblMineMode = widget.NewLabel("Режим: None")
	hBoxMine := container.NewHBox(sf.lblMineTime, sf.lblMineMode)
	itemMineWork := widget.NewFormItem("Режим", hBoxMine)
	frmMine := widget.NewForm(itemMine, itemMineWork)

	itemBank := widget.NewFormItem("Банк", lblEmpty)
	sf.lblBankTime = widget.NewLabel("Время: 00:00:00")
	sf.lblBankMode = widget.NewLabel("Режим: None")
	hBoxBank := container.NewHBox(sf.lblBankTime, sf.lblBankMode)
	itemBankWork := widget.NewFormItem("Режим", hBoxBank)
	frmBank := widget.NewForm(itemBank, itemBankWork)

	itemArmor := widget.NewFormItem("Оружейная", lblEmpty)
	sf.lblArsenalTime = widget.NewLabel("Время: 00:00:00")
	sf.lblArsenalMode = widget.NewLabel("Режим: None")
	hBoxArmor := container.NewHBox(sf.lblArsenalTime, sf.lblArsenalMode)
	itemArmorWork := widget.NewFormItem("Режим", hBoxArmor)
	frmArmor := widget.NewForm(itemArmor, itemArmorWork)

	hBase := container.NewVBox(frmPolygon, frmMine, frmBank, frmArmor)
	tabBase := container.NewTabItem("База", hBase)

	sf.lblBattleTime = widget.NewLabel("00:00:00")
	itemBattleTime := widget.NewFormItem("До начала", sf.lblBattleTime)
	frmBattle := widget.NewForm(itemBattleTime)
	hBattle := container.NewVBox(frmBattle)
	tabBattle := container.NewTabItem("Сражения", hBattle)
	sf.tabBot = container.NewAppTabs(tabLogin, tabStat, tabBase, tabBattle)

	sf.boxLeft = container.NewVBox(text1)

	boxBorder := container.NewBorder(nil, nil, sf.boxLeft, nil, sf.boxLeft, sf.tabBot)
	boxMain := container.NewBorder(nil, boxDown, nil, nil, boxBorder)
	sf.Resize(fyne.NewSize(640, 480))

	{ // Получить список всех ботов
		lstBots := sf.serv.ServBots().ListBot()
		for _, bot := range lstBots {
			sf.addBot(bot.Имя(), bot.Пароль())
		}
	}

	sf.SetContent(boxMain)
	go sf.showStat()
	return sf, nil
}

// Обнуляет вкладку статистики бота, если её невозможно получить
func (sf *WinMain) resetStat() {
	{ // Левый фрейм статы
		sf.lblFuel.SetText("0")
		sf.lblGold.SetText("0")
		sf.lblSilver.SetText("0")
		sf.lblGlory.SetText("0")
		sf.lblRuda.SetText("0")
		sf.lblFerrum.SetText("0")
		sf.lblSteel.SetText("0")
		sf.lblPlumbum.SetText("0")
	}
	{ // Правый фрейм статы
		sf.lblAtack.SetText("0")
		sf.lblArmor.SetText("0")
		sf.lblFyne.SetText("0")
		sf.lblHard.SetText("0")
		sf.lblPower.SetText("0")
		sf.lblForce.SetText("None")
	}
	{ // Вкладка базы
		sf.lblPolygonTime.SetText("Время: 00:00:00")
		sf.lblPolygonMode.SetText("Режим: None")
		sf.lblMineTime.SetText("Время: 00:00:00")
		sf.lblMineMode.SetText("Режим: None")
		sf.lblBankTime.SetText("Время: 00:00:00")
		sf.lblBankMode.SetText("Режим: None")
		sf.lblArsenalTime.SetText("Время: 00:00:00")
		sf.lblArsenalMode.SetText("Режим: None")
		sf.lblBattleTime.SetText("00:00:00")
	}
}

// Показывает статистику бота
func (sf *WinMain) showStat() {
	for {
		time.Sleep(time.Millisecond * 500)
		sf.ботВход = sf.entLogin.Text
		if sf.ботВход == "" {
			continue
		}
		bot := sf.serv.ServBots().Get(sf.ботВход)
		{ // Левый фрейм статы
			sf.lblFuel.Text = fmt.Sprint(bot.Ангар().Топливо().Получ())
			sf.lblFuel.Refresh()
			sf.lblGold.Text = fmt.Sprint(bot.Ангар().Золото().Получ())
			sf.lblGold.Refresh()
			strSilver := fmt.Sprint(bot.Ангар().СереброВсего().Получ())
			strSlv := ""
			i := 0
			for i0 := len(strSilver) - 1; i0 >= 0; i0-- {
				run := string(strSilver[i0])
				if i == 3 {
					strSlv = run + "_" + strSlv
					i = 0
					continue
				}
				strSlv = run + strSlv
				i++
			}
			sf.lblSilver.Text = strSlv
			sf.lblSilver.Refresh()
			sf.lblGlory.Text = fmt.Sprint(bot.Ангар().Конвой().Слава().Получ())
			sf.lblGlory.Refresh()
			sf.lblRuda.Text = fmt.Sprint(bot.Ангар().База().Шахта().Руда().Получ())
			sf.lblRuda.Refresh()
			sf.lblFerrum.Text = fmt.Sprint(bot.Ангар().База().Шахта().Железо().Получ())
			sf.lblFerrum.Refresh()
			sf.lblSteel.Text = fmt.Sprint(bot.Ангар().База().Шахта().Сталь().Получ())
			sf.lblSteel.Refresh()
			sf.lblPlumbum.Text = fmt.Sprint(bot.Ангар().База().Шахта().Свинец().Получ())
			sf.lblPlumbum.Refresh()
		}
		{ // Правый фрейм статы
			sf.lblAtack.Text = fmt.Sprint(bot.Танк().ТанкСтат().Атака().Получ())
			sf.lblAtack.Refresh()
			sf.lblArmor.Text = fmt.Sprint(bot.Танк().ТанкСтат().Броня().Получ())
			sf.lblArmor.Refresh()
			sf.lblFyne.Text = fmt.Sprint(bot.Танк().ТанкСтат().Точность().Получ())
			sf.lblFyne.Refresh()
			sf.lblHard.Text = fmt.Sprint(bot.Танк().ТанкСтат().Прочность().Получ())
			sf.lblHard.Refresh()
			sf.lblPower.Text = fmt.Sprint(bot.Танк().ТанкСтат().Мощь().Получ())
			sf.lblPower.Refresh()
			strForce := fmt.Sprintf("%v (+%v)", bot.Танк().ТанкСтат().Форсаж().Имя(), bot.Танк().ТанкСтат().Форсаж().Получ())
			sf.lblForce.SetText(strForce)
		}
		{ // Вкладка базы
			if bot.Ангар().База().Полигон() == nil {
				continue
			}
			polyTime := bot.Ангар().База().Полигон().ВремяОпрос().Стр()
			sf.lblPolygonTime.SetText("Время: " + polyTime)
			// polyMode := bot.Angar().Base().Polygon().ModeCurrent().Work()
			strForce := fmt.Sprintf("%v (+%v)", bot.Танк().ТанкСтат().Форсаж().Имя(), bot.Танк().ТанкСтат().Форсаж().Получ())
			sf.lblPolygonMode.SetText("Режим: " + strForce)

			mineTime := bot.Ангар().База().Шахта().ВремяОпрос().Стр()
			sf.lblMineTime.SetText("Время: " + mineTime)
			mineMode := bot.Ангар().База().Шахта().РежимТекущ().Режим()
			sf.lblMineMode.SetText("Режим: " + mineMode)

			bankTime := bot.Ангар().База().Банк().ВремяОпрос().Стр()
			sf.lblBankTime.SetText("Время: " + bankTime)
			bankMode := bot.Ангар().База().Банк().РежимТекущ().Режим()
			sf.lblBankMode.SetText("Режим: " + bankMode)

			arsenalTime := bot.Ангар().База().Арсенал().ВремяОпрос().Стр()
			sf.lblArsenalTime.SetText("Время: " + arsenalTime)
			arsenalMode := bot.Ангар().База().Арсенал().РежимТекущ().Режим()
			sf.lblArsenalMode.SetText("Режим: " + arsenalMode)
		}
		{ // Вкладка сражений
			battleTime := bot.Ангар().Сражение().ВремяОпрос().Стр()
			sf.lblBattleTime.SetText(battleTime)
		}
	}
}

// Выставляет признак автоматического начала игры при запуске бото-фермы
func (sf *WinMain) clickAutoGame(isAutoGame bool) {
	log.Printf("WinMain.clickAutoGame(): login:%q\t isAutoGame=%v\n", sf.entLogin.Text, isAutoGame)
	sf.ботВход = sf.entLogin.Text
	if sf.ботВход == "" {
		sf.checkAutoGame.Checked = false
		return
	}
	// Сохранить автозапуск бота
	bot := sf.serv.ServBots().Get(sf.ботВход)
	switch isAutoGame {
	case true: // Автозапуск бота
		bot.АвтоИграУст()
	default:
		bot.АвтоИграСброс()
	}
}

func (sf *WinMain) btnAddClick() {
	log.Println("WinMain.btnAddclick()")
	winAddBot := sf.app.NewWindow("Новый бот")
	entLogin := widget.NewEntry()
	entLogin.SetPlaceHolder("Извини брат")
	entPass := widget.NewEntry()
	entPass.SetPlaceHolder("Default")
	form := &widget.Form{
		Items: []*widget.FormItem{ // we can specify items in the constructor
			{Text: "Логин", Widget: entLogin},
			{Text: "Пароль", Widget: entPass},
		},
		OnSubmit: func() { // optional, handle form submission
			winAddBot.Close()
			login := entLogin.Text
			if login == "" {
				login = "Извини брат"
			}
			pass := entPass.Text
			if pass == "" {
				pass = strMainPass
			}
			go sf.addBot(login, pass)
		},
	}
	winAddBot.Resize(fyne.NewSize(640, 480))
	winAddBot.SetContent(form)
	winAddBot.Show()

}

// Добавляет бота на экран в отдельном потоке
func (sf *WinMain) addBot(login, pass string) {
	if login == "" {
		log.Printf("WinMain.addBot(): login is empty")
		return
	}
	if pass == "" {
		log.Printf("WinMain.addBot(): pass is empty")
		return
	}
	sf.ботВход = login
	sf.ботПароль = pass
	log.Printf("WinMain.addBot(): %q\n", sf.ботВход)
	err := sf.serv.ServBots().NewBot(login, pass)
	if err != nil {
		log.Printf("WinMain.addBot() in add bot to ferma, err=\n\t%v\n", err)
		return
	}
	if sf.ботПароль == strMainPass {
		sf.ботПароль = "Default"
	}
	btnBot := widget.NewButton(login, sf.btnBotClick(login))
	sf.boxLeft.Add(btnBot)
}

// Показывает данные своего бота при клике на соответствующей кнопке
func (sf *WinMain) btnBotClick(login string) func() {
	log.Println("WinMain.btnBotClick()")
	bot := sf.serv.ServBots().Get(login)
	_botPass := bot.Пароль()
	if _botPass == strMainPass {
		_botPass = "Default"
	}
	return func() {
		log.Printf("btnBotClick().fn(): botName=%q\tbotPass=%q\tisAuto=%v\n", login, _botPass, bot.АвтоИграЕсли())
		// Заполнить данными вкладки своего бота
		sf.entLogin.Text = login
		sf.entLogin.Refresh()
		sf.entPass.Text = _botPass
		sf.entPass.Refresh()
		sf.checkAutoGame.SetChecked(bot.АвтоИграЕсли())
		sf.resetStat()
		sf.Window.SetTitle("Бото-ферма [wartank.ru]: =" + login + "=")
	}
}

func (sf *WinMain) btnExitClick() {
	log.Println("WinMain.btnExitClick()")
	sf.Close()
	sf.app.Quit()
	sf.serv.CancelApp()
}
