package autohost_grafana

import (
	"encoding/json"
	"fmt"
)

type PanelGroup struct {
	x     int
	y     int
	id    int
	lastH int

	panels        []Panel
	collapsedRows []*GrafanaRowPanel
}

func NewPanelGroup() PanelGroup {
	return PanelGroup{}
}

func (g *PanelGroup) AddPanel(panel Panel) {
	panel.SetDashboardProps(g.id, g.x, g.y)
	g.panels = append(g.panels, panel)

	w := panel.GetWidth()
	h := panel.GetHeight()
	g.advance(w, h)
}

func (g *PanelGroup) AddPanelToNextLine(panel Panel) {
	g.moveCursorToNextLine()
	g.AddPanel(panel)
}

func (g *PanelGroup) AddPanelToCollapsedRow(panel Panel, rowID int) error {
	panel.SetDashboardProps(g.id, g.x, g.y)

	var row *GrafanaRowPanel
	for _, r := range g.collapsedRows {
		if r.ID == rowID {
			row = r
			break
		}
	}
	if row == nil {
		return fmt.Errorf("row with id %d could not be found", rowID)
	}

	row.Panels = append(row.Panels, panel)

	w := panel.GetWidth()
	h := panel.GetHeight()
	g.advance(w, h)

	return nil
}

func (g *PanelGroup) AddPanelToNextLineInCollapsedRow(panel Panel, rowID int) {
	g.moveCursorToNextLine()
	g.AddPanelToCollapsedRow(panel, rowID)
}

func (g *PanelGroup) AddRow(title string, collapsed bool) int {
	g.moveCursorToNextLine()
	rowPanel := NewRowPanel(RowPanelArgs{
		Collapsed: collapsed,
		ID:        g.id,
		Title:     title,
		X:         g.x,
		Y:         g.y,
	})
	g.panels = append(g.panels, &rowPanel)

	if collapsed {
		g.collapsedRows = append(g.collapsedRows, &rowPanel)
	}

	g.moveCursorToNextLine()
	g.advance(rowPanel.GridPos.W, rowPanel.GridPos.H)

	return rowPanel.ID
}

func (g *PanelGroup) ToJson() (string, error) {
	panelsJsonBytes, err := json.MarshalIndent(g.panels, "", "  ")
	if err != nil {
		return "", err
	}
	return string(panelsJsonBytes), nil
}

func (g *PanelGroup) advance(w, h int) {
	g.id++

	x := g.x + w
	if x < DashboardWidth {
		g.x = x
	} else {
		g.x = 0
		g.y += h
	}

	g.lastH = h
}

func (g *PanelGroup) moveCursorToNextLine() {
	if g.x == 0 {
		return
	}

	g.x = 0
	g.y += g.lastH
}
