package ui

import (
	"go_dreamfactory/cmd/v2/service"
	"go_dreamfactory/cmd/v2/service/observer"

	"fyne.io/fyne/v2/container"
)

type appContainer struct {
	appStatusMap map[string]appStatus
	container.DocTabs
	obs     observer.Observer
	ai      []appInterface
	service service.PttService
}

func newAppContainer(ai []appInterface, service service.PttService, obs observer.Observer) *appContainer {
	at := &appContainer{ai: ai, service: service, obs: obs}

	at.appStatusMap = make(map[string]appStatus)
	at.CloseIntercept = at.closeHandle
	at.SetTabLocation(container.TabLocationTop)
	at.ExtendBaseWidget(at)
	at.OnSelected = func(item *container.TabItem) {
		item.Content.Refresh()
	}
	return at
}

type appStatus struct {
	lazyInit bool
}

func (at *appContainer) closeHandle(tab *container.TabItem) {
	for _, app := range at.ai {
		if app.GetAppName() == tab.Text {
			if app.OnClose() {
				at.Remove(tab)
			}
		}
	}
}

func (at *appContainer) openApp(app appInterface) error {
	for _, appItem := range at.Items {
		if appItem.Text == app.GetAppName() {
			at.Select(appItem)
			return nil
		}
	}
	err := at.initApp(app)
	if err != nil {
		return err
	}

	tab := app.GetTabItem()
	at.Append(tab)
	at.Select(tab)
	return nil
}

func (at *appContainer) openWelcome() (string, error) {
	var firstTab *container.TabItem
	app := &appWelcome{}
	if err := at.initApp(app); err != nil {
		return app.GetAppName(), err
	}
	tab := app.GetTabItem()
	at.Append(tab)
	if firstTab == nil {
		firstTab = tab
	}
	if firstTab != nil {
		at.Select(firstTab)
	}
	return "", nil
}

// open default app
func (at *appContainer) openDefaultApp(appName string) (string, error) {
	var firstTab *container.TabItem
	for _, app := range at.ai {
		if app.OpenDefault() == appName {
			if err := at.initApp(app); err != nil {
				return app.GetAppName(), err
			}
			tab := app.GetTabItem()
			at.Append(tab)
			if firstTab == nil {
				firstTab = tab
			}
		}
	}

	if firstTab != nil {
		at.Select(firstTab)
	}
	return "", nil
}

func (at *appContainer) initApp(app appInterface) error {
	st, ok := at.appStatusMap[app.GetAppName()]
	if !ok || !st.lazyInit {
		err := app.LazyInit(at.service, at.obs)
		if err != nil {
			return err
		}
		at.appStatusMap[app.GetAppName()] = appStatus{lazyInit: true}
	}
	return nil
}
