// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package components

import (
	"fmt"
	"sort"
	"strings"

	"github.com/gdamore/tcell/v2"
	"github.com/rivo/tview"
	"github.com/siderolabs/gen/maps"
)

// Footer represents the top bar with host info.
type Footer struct {
	tview.TextView

	selectedNode string
	nodes        []string

	screenKeyToName map[string]string

	selectedScreen string
}

// NewFooter initializes Footer.
func NewFooter(screenKeyToName map[string]string) *Footer {
	var initialScreen string
	for _, name := range screenKeyToName {
		initialScreen = name

		break
	}

	widget := &Footer{
		TextView:        *tview.NewTextView(),
		screenKeyToName: screenKeyToName,
		selectedScreen:  initialScreen,
	}

	widget.SetDynamicColors(true)

	// set the background to be a horizontal line
	widget.SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
		for i := x; i < x+width; i++ {
			for j := y; j < y+height; j++ {
				screen.SetContent(
					i,
					j,
					tview.BoxDrawingsLightHorizontal,
					nil,
					tcell.StyleDefault.Foreground(tcell.ColorWhite),
				)
			}
		}

		return x, y, width, height
	})

	widget.refresh()

	return widget
}

// OnNodeSetChange implements the NodeSetListener interface.
func (widget *Footer) OnNodeSetChange(nodes []string) {
	widget.nodes = nodes

	widget.refresh()
}

// OnNodeSelect implements the NodeSelectListener interface.
func (widget *Footer) OnNodeSelect(node string) {
	widget.selectedNode = node

	widget.refresh()
}

// SelectScreen refreshes the footer with the tabs and screens data.
func (widget *Footer) SelectScreen(screen string) {
	widget.selectedScreen = screen

	widget.refresh()
}

func (widget *Footer) refresh() {
	widget.SetText(fmt.Sprintf(
		"[%s] --- %s",
		widget.nodesText(),
		widget.screensText(),
	))
}

func (widget *Footer) nodesText() string {
	nodesCopy := make([]string, 0, len(widget.nodes))

	for _, node := range widget.nodes {
		if node == widget.selectedNode {
			name := node
			if name == "" {
				name = "(local)"
			}

			nodesCopy = append(nodesCopy, fmt.Sprintf("[red]%s[-]", name))
		} else {
			nodesCopy = append(nodesCopy, node)
		}
	}

	return strings.Join(nodesCopy, " | ")
}

func (widget *Footer) screensText() string {
	screenKeys := maps.Keys(widget.screenKeyToName)
	sort.Strings(screenKeys)

	screenTexts := make([]string, 0, len(widget.screenKeyToName))

	for _, screenKey := range screenKeys {
		screen := widget.screenKeyToName[screenKey]

		if screen == widget.selectedScreen {
			screenTexts = append(screenTexts, fmt.Sprintf("[[red]%s[-]]", screen))
		} else {
			screenTexts = append(screenTexts, fmt.Sprintf("[%s: %s]", screenKey, screen))
		}
	}

	return strings.Join(screenTexts, " --- ")
}
