package tui

import (
	"miasma-installer/tui/steps"

	tea "github.com/charmbracelet/bubbletea"
)

type State int

const (
	StateWelcome State = iota
	StateDiskSelection
	StateEncryption
	StateHostname
	StateUser
	StateConfirm
	StateInstalling
	StateFinished
)

type RootModel struct {
	State        State
	CurrentModel tea.Model
	Width        int
	Height       int
	SelectedDisk string
	EnableLUKS   bool
	Hostname     string
	Username     string
	UserPassword string
	RootPassword string
}

func NewModel() RootModel {
	return RootModel{
		State:        StateWelcome,
		CurrentModel: steps.NewWelcomeModel(),
	}
}

func (m RootModel) Init() tea.Cmd {
	return nil
}

func (m RootModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	var cmd tea.Cmd

	switch msg := msg.(type) {
	case tea.KeyMsg:
		if msg.String() == "ctrl+c" {
			return m, tea.Quit
		}
	case tea.WindowSizeMsg:
		m.Width = msg.Width
		m.Height = msg.Height
	}

	m.CurrentModel, cmd = m.CurrentModel.Update(msg)

	switch m.CurrentModel.(type) {
	case steps.WelcomeModel:
		if m.CurrentModel.(steps.WelcomeModel).Finished {
			m.State = StateDiskSelection
			m.CurrentModel = steps.NewDiskSelModel(m.Width, m.Height)
			return m, m.CurrentModel.Init()
		}

	case steps.DiskSelModel:
		if m.CurrentModel.(steps.DiskSelModel).Finished {
			m.SelectedDisk = m.CurrentModel.(steps.DiskSelModel).SelectedDisk
			m.State = StateEncryption
			m.CurrentModel = steps.NewEncryptionModel()
			return m, m.CurrentModel.Init()
		}

	case steps.EncryptionModel:
		if m.CurrentModel.(steps.EncryptionModel).Finished {
			m.EnableLUKS = m.CurrentModel.(steps.EncryptionModel).EnableEncryption
			if m.EnableLUKS {
				m.RootPassword = m.CurrentModel.(steps.EncryptionModel).Password
			}
			m.State = StateHostname
			m.CurrentModel = steps.NewHostnameModel()
			return m, m.CurrentModel.Init()
		}

	case steps.HostnameModel:
		if m.CurrentModel.(steps.HostnameModel).Finished {
			m.Hostname = m.CurrentModel.(steps.HostnameModel).Hostname
			m.State = StateUser
			m.CurrentModel = steps.NewUserModel()
			return m, m.CurrentModel.Init()
		}

	case steps.UserModel:
		if m.CurrentModel.(steps.UserModel).Finished {
			m.Username = m.CurrentModel.(steps.UserModel).Username
			m.UserPassword = m.CurrentModel.(steps.UserModel).Password
			m.State = StateConfirm
			m.CurrentModel = steps.NewConfirmModel(m.SelectedDisk, m.EnableLUKS, m.Hostname, m.Username)
			return m, m.CurrentModel.Init()
		}

	case steps.ConfirmModel:
		if m.CurrentModel.(steps.ConfirmModel).Finished {
			if m.CurrentModel.(steps.ConfirmModel).Confirmed {
				m.State = StateInstalling
				m.CurrentModel = steps.NewInstallModel(m.SelectedDisk, m.EnableLUKS, m.Hostname, m.Username, m.UserPassword, m.RootPassword)
				return m, m.CurrentModel.Init()
			} else {
				return m, tea.Quit
			}
		}

	case steps.InstallModel:
		if m.CurrentModel.(steps.InstallModel).Finished {
			m.State = StateFinished
			return m, tea.Quit
		}
	}
	return m, cmd
}

func (m RootModel) View() string {
	return m.CurrentModel.View()
}
