package ui

import (
	"errors"
	"fmt"
	"go_dreamfactory/cmd/v2/lib/common"
	os_storage "go_dreamfactory/cmd/v2/lib/storage"
	"go_dreamfactory/cmd/v2/service"
	"go_dreamfactory/cmd/v2/service/observer"
	"go_dreamfactory/utils"
	"io/ioutil"
	"os/exec"
	"runtime"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/layout"
	fyne_storage "fyne.io/fyne/v2/storage"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"github.com/sirupsen/logrus"
)

type appPbGen struct {
	appAdapter
	folderList *folderList
}

func (this *appPbGen) LazyInit(ptService service.PttService, obs observer.Observer) error {
	this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PB, theme.ContentAddIcon(), nil)
	this.folderList = NewFolderList()

	countLabel := widget.NewLabel("")

	//load
	storage, _ := os_storage.NewOSStorage()
	conf, err := storage.LoadConfig()
	if err != nil {
		return err
	}

	// 打开目录
	openFolder := func(entry *widget.Entry) {
		dConf := dialog.NewFolderOpen(func(lu fyne.ListableURI, err error) {
			if lu == nil {
				return
			}
			entry.Text = lu.Path()
			entry.Refresh()
		}, toolWin.w)
		luri, _ := fyne_storage.ListerForURI(fyne_storage.NewFileURI("."))
		dConf.SetLocation(luri)
		dConf.SetConfirmText("打开")
		dConf.SetDismissText("取消")
		dConf.Resize(fyne.NewSize(750, 500))
		dConf.Show()
	}

	content := container.NewMax()
	content.Objects = []fyne.CanvasObject{}

	protoDir := widget.NewEntry()
	protoDir.PlaceHolder = "proto目录"
	protoDir.OnChanged = func(s string) {
		this.folderList.initItem(protoDir.Text)
		countLabel.SetText(fmt.Sprintf("总数:%v", this.folderList.fileTotal))
	}

	outDir := widget.NewEntry()
	outDir.PlaceHolder = "go输出目录"

	form := widget.NewForm(
		widget.NewFormItem("proto目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
			openFolder(protoDir)
			this.folderList.initItem(protoDir.Text)
		}), protoDir)),
		widget.NewFormItem("输出目录", container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.FolderIcon(), func() {
			openFolder(outDir)
		}), outDir)),
	)

	if conf.PbConf != nil {
		protoDir.SetText(conf.PbConf.ProtoDir)
		outDir.SetText(conf.PbConf.OutputDir)
	}

	//打开资源管理器
	explorBtn := &widget.Button{Text: "资源管理器", Icon: theme.FolderIcon()}
	explorBtn.OnTapped = func() {
		OpenExplor(protoDir.Text)
	}

	genBtn := &widget.Button{Text: "生成", Icon: theme.ConfirmIcon()}

	genBtn.OnTapped = func() {
		genBtn.Disable()
		defer func() {
			genBtn.Enable()
		}()
		if runtime.GOOS != "windows" {
			dialog.ShowError(errors.New("no support "+runtime.GOOS), toolWin.w)
			return
		}
		dialog.ShowConfirm("确认",
			strings.Join(this.folderList.selItemIds, ","), func(b bool) {
				if !b {
					return
				}

				if outDir.Text == "" {
					dialog.ShowError(errors.New("请设置输出目录"), toolWin.w)
					return
				}

				if protoDir.Text == "" {
					dialog.ShowError(errors.New("请设置proto目录"), toolWin.w)
					return
				}

				commandStr1 := `protoc --proto_path=%s --go_out=%s --go_opt=paths=import %s\*.proto`
				commandStr2 := `protoc --proto_path=%s --go_out=%s --go_opt=paths=import %s\%s\*.proto`
				var arg1, arg2 string
				arg1 = fmt.Sprintf(commandStr1,
					protoDir.Text,
					outDir.Text,
					protoDir.Text,
				)
				for _, name := range this.folderList.selItemIds {
					arg2 = fmt.Sprintf(commandStr2,
						protoDir.Text,
						outDir.Text,
						protoDir.Text,
						name,
					)
				}
				logrus.Debug(arg1)
				logrus.Debug(arg2)
				c1 := exec.Command("cmd.exe", "/c", arg1)
				if err := c1.Run(); err != nil {
					dialog.ShowError(err, toolWin.w)
					return
				}
				c2 := exec.Command("cmd.exe", "/c", arg2)
				if err := c2.Run(); err != nil {
					dialog.ShowError(err, toolWin.w)
					return
				}

			}, toolWin.w)
	}

	refreshBtn := widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() {
		this.folderList.cachedList = common.NewList("")
		this.folderList.selItemIds = []string{}
		this.folderList.initItem(protoDir.Text)
		countLabel.SetText(fmt.Sprintf("总数:%v", this.folderList.fileTotal))
	})

	confBtn := &widget.Button{Text: "保存配置", Icon: theme.DocumentSaveIcon()}
	confBtn.OnTapped = func() {
		pbconf := &os_storage.ProtobufConfig{
			ProtoDir:  protoDir.Text,
			OutputDir: outDir.Text,
		}
		conf.PbConf = pbconf
		if err := storage.StoreConfig(conf); err != nil {
			logrus.WithField("err", err).Debug("保存配置")
			return
		}
		logrus.Debug("save pb conf")
	}

	this.folderList.itemList = this.folderList.createList()

	// layout
	c := container.NewBorder(
		form,
		container.NewHBox(confBtn, explorBtn, genBtn, refreshBtn, layout.NewSpacer(), countLabel), nil, nil,
		container.NewMax(
			container.NewVScroll(this.folderList.itemList),
		),
	)

	content.Objects = append(content.Objects, c)
	this.tabItem.Content = content
	return nil
}

func (a *appPbGen) GetAppName() string {
	return common.TOOLBAR_PB
}
func (a *appPbGen) Icon() fyne.Resource {
	return theme.ContentAddIcon()
}

type folderList struct {
	selItemIds []string //选择的ID
	cachedList common.List
	itemList   *widget.List
	fileTotal  int //文件总数
}

func NewFolderList() *folderList {
	return &folderList{
		cachedList: common.NewList(""),
	}
}

func (f *folderList) createList() *widget.List {
	return widget.NewList(
		func() int {
			return len(f.cachedList.Items)
		},
		func() fyne.CanvasObject {
			return widget.NewCheck("Template", func(b bool) {})
		},
		func(id widget.ListItemID, item fyne.CanvasObject) {
			c, _ := item.(*widget.Check)
			im := f.cachedList.Items[id]
			c.Text = im.Text
			c.Checked = im.Checked

			c.OnChanged = func(b bool) {
				if b {
					f.selItemIds = append(f.selItemIds, c.Text)
				} else {
					f.selItemIds = utils.DeleteString(f.selItemIds, c.Text)
				}
				f.cachedList.Items[id].Checked = b
				f.itemList.Refresh()
			}
			c.Refresh()
		},
	)
}

func (f *folderList) initItem(dir string) {
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		logrus.Error(err)
		return
	}

	for _, file := range files {
		if file.IsDir() {
			if file.Name() == ".vscode"||
			file.Name() == ".svn" {
				continue
			}
			fm := common.Item{
				Text:    file.Name(),
				Checked: false,
			}
			f.cachedList.Items = append(f.cachedList.Items, fm)
			// f.selItemIds = append(f.selItemIds, fm.Id)
			f.fileTotal++
			// logrus.Debugf("%v", fm.Id)
		}
	}

}
