package ui

import "gioui.org/unit"

// Region defines a screen area in device-independent pixels (Dp).
type Region struct {
	X, Y unit.Dp
	W, H unit.Dp
}

// Element is the base interface for all UI elements.
type Element interface {
	Region() Region
	Visible() bool
}

// TextAlign specifies horizontal text alignment.
type TextAlign int

const (
	AlignStart TextAlign = iota
	AlignCenter
	AlignEnd
)

// InputType specifies the type of user input event.
type InputType int

const (
	Tap InputType = iota
	DoubleTap
	LongPress
	Scroll
	KeyDown
	KeyUp
)

// InputEvent represents a user input event routed to an element.
type InputEvent struct {
	ElementID string
	Type      InputType
	Data      any
}

// ConfigEvent represents a window configuration change (resize, orientation).
type ConfigEvent struct {
	Width  unit.Dp
	Height unit.Dp
}

// Label displays static text.
type Label struct {
	id       string
	region   Region
	visible  bool
	Text     string
	Align    TextAlign
	FontSize unit.Sp // 0 = theme default
	Color    Color   // 0 = theme default
	Bold     bool
}

func (l Label) Region() Region { return l.region }
func (l Label) Visible() bool  { return l.visible }
func (l Label) ID() string     { return l.id }

// NewLabel creates a visible Label element.
func NewLabel(text string, fontSize unit.Sp, region Region) Label {
	return Label{
		region:   region,
		visible:  true,
		Text:     text,
		FontSize: fontSize,
	}
}

// TextField accepts text input or displays multiline text.
type TextField struct {
	id           string
	region       Region
	visible      bool
	Value        string
	Placeholder  string
	Focused      bool
	Multiline    bool
	ScrollOffset unit.Dp
	VisibleLines []Line
	WordWrap     bool
	WrapWidth    unit.Dp
}

func (tf TextField) Region() Region { return tf.region }
func (tf TextField) Visible() bool  { return tf.visible }
func (tf TextField) ID() string     { return tf.id }

// Line represents a single line of text in a multiline TextField.
type Line struct {
	Text       string
	LineNumber int // 1-indexed, for display
}

// ListView displays a scrollable list of items.
type ListView struct {
	id           string
	region       Region
	visible      bool
	Items        []ListItem
	ScrollOffset int
	Selected     int
}

func (lv ListView) Region() Region { return lv.region }
func (lv ListView) Visible() bool  { return lv.visible }
func (lv ListView) ID() string     { return lv.id }

// ListItem is a single entry in a ListView.
type ListItem struct {
	Text     string
	Subtext  string
	Selected bool
}

// AlphaIndex displays an alphabetical index for quick navigation.
type AlphaIndex struct {
	id           string
	region       Region
	visible      bool
	Letters      []string
	ActiveLetter string
}

func (ai AlphaIndex) Region() Region { return ai.region }
func (ai AlphaIndex) Visible() bool  { return ai.visible }
func (ai AlphaIndex) ID() string     { return ai.id }

// NewAlphaIndex creates a visible AlphaIndex element.
func NewAlphaIndex(region Region, letters []string) AlphaIndex {
	return AlphaIndex{
		region:  region,
		visible: true,
		Letters: letters,
	}
}

// Button is an interactive button element.
type Button struct {
	id        string
	region    Region
	visible   bool
	Text      string
	Enabled   bool
	Primary   bool
}

func (b Button) Region() Region { return b.region }
func (b Button) Visible() bool  { return b.visible }
func (b Button) ID() string     { return b.id }

// NewButton creates a visible Button element.
func NewButton(text string, enabled bool, primary bool, region Region) Button {
	return Button{
		region:  region,
		visible: true,
		Text:    text,
		Enabled: enabled,
		Primary: primary,
	}
}

// SearchBar displays an in-editor search interface.
type SearchBar struct {
	id      string
	region  Region
	visible bool
	Query   string
	Match   int
	Total   int
	Forward bool
}

func (sb SearchBar) Region() Region { return sb.region }
func (sb SearchBar) Visible() bool  { return sb.visible }
func (sb SearchBar) ID() string     { return sb.id }

// NewSearchBar creates a visible SearchBar element.
func NewSearchBar(region Region, query string, match, total int, forward bool) SearchBar {
	return SearchBar{
		region:  region,
		visible: true,
		Query:   query,
		Match:   match,
		Total:   total,
		Forward: forward,
	}
}

// Cursor displays the text cursor and optional selection highlight.
type Cursor struct {
	id        string
	region    Region
	visible   bool
	Line      int
	Column    int
	Blinking  bool
	Selection *Selection
}

func (c Cursor) Region() Region { return c.region }
func (c Cursor) Visible() bool  { return c.visible }
func (c Cursor) ID() string     { return c.id }

// Selection represents a text selection range.
type Selection struct {
	StartLine, StartCol int
	EndLine, EndCol     int
}

// MergeHunk displays a conflict resolution hunk.
type MergeHunk struct {
	id           string
	region       Region
	visible      bool
	HunkNumber   int
	TotalHunks   int
	LineRange    string
	ContextLines []string
	OurLines     []string
	TheirLines   []string
	Resolution   HunkResolution
}

func (mh MergeHunk) Region() Region { return mh.region }
func (mh MergeHunk) Visible() bool  { return mh.visible }
func (mh MergeHunk) ID() string     { return mh.id }

// HunkResolution represents the resolution state of a merge hunk.
type HunkResolution int

const (
	Unresolved HunkResolution = iota
	KeepOurs
	KeepTheirs
	MergeBoth
)

// StatusBar displays the top bar with filename, action icons, and conflict indicator.
type StatusBar struct {
	id           string
	region       Region
	visible      bool
	Filename     string
	FilenameExp  bool
	CutCopy      bool
	Copy         bool
	Paste        bool
	ConflictIcon bool
	Search       bool
}

func (sb StatusBar) Region() Region { return sb.region }
func (sb StatusBar) Visible() bool  { return sb.visible }
func (sb StatusBar) ID() string     { return sb.id }

// NewStatusBar creates a visible StatusBar element.
func NewStatusBar(region Region, filename string, filenameExp bool, cutCopy, copy, paste, conflictIcon, search bool) StatusBar {
	return StatusBar{
		region:       region,
		visible:      true,
		Filename:     filename,
		FilenameExp:  filenameExp,
		CutCopy:      cutCopy,
		Copy:         copy,
		Paste:        paste,
		ConflictIcon: conflictIcon,
		Search:       search,
	}
}

// BottomBar displays the bottom bar with cursor position, byte position, and word wrap toggle.
type BottomBar struct {
	id        string
	region    Region
	visible   bool
	CursorPos string
	BytePos   string
	WordWrap  bool
}

func (bb BottomBar) Region() Region { return bb.region }
func (bb BottomBar) Visible() bool  { return bb.visible }
func (bb BottomBar) ID() string     { return bb.id }

// NewBottomBar creates a visible BottomBar element.
func NewBottomBar(region Region, cursorPos, bytePos string, wordWrap bool) BottomBar {
	return BottomBar{
		region:    region,
		visible:   true,
		CursorPos: cursorPos,
		BytePos:   bytePos,
		WordWrap:  wordWrap,
	}
}

// Toast displays a temporary notification.
type Toast struct {
	id      string
	region  Region
	visible bool
	Text    string
	Timeout int // milliseconds
}

func (t Toast) Region() Region { return t.region }
func (t Toast) Visible() bool  { return t.visible }
func (t Toast) ID() string     { return t.id }

// NewToast creates a visible Toast element.
func NewToast(region Region, text string, timeout int) Toast {
	return Toast{
		region:  region,
		visible: true,
		Text:    text,
		Timeout: timeout,
	}
}

// Spacer adds vertical or horizontal space.
type Spacer struct {
	id      string
	region  Region
	visible bool
}

func (s Spacer) Region() Region { return s.region }
func (s Spacer) Visible() bool  { return s.visible }
func (s Spacer) ID() string     { return s.id }

// NewSpacer creates a visible Spacer element.
func NewSpacer(height unit.Dp) Spacer {
	return Spacer{
		region:  Region{H: height},
		visible: true,
	}
}

// Color is an RGBA color.
type Color struct {
	R, G, B, A uint8
}

// Theme holds styling defaults for the UI.
type Theme struct {
	FontSize unit.Sp
}
