package motion

import (
	tea "github.com/charmbracelet/bubbletea"
	"git.gophernest.net/azpect/TextEditor/internal/action"
)

// MoveDown implements Motion (j) - linewise
type MoveDown struct {
	Count int
}

func (a MoveDown) Execute(m action.Model) tea.Cmd {
	for i := 0; i < a.Count && m.CursorY() < m.LineCount()-1; i++ {
		m.SetCursorY(m.CursorY() + 1)
	}
	m.ClampCursorX()
	return nil
}

func (a MoveDown) Type() action.MotionType { return action.Linewise }

func (a MoveDown) WithCount(n int) action.Action {
	return MoveDown{Count: n}
}

// MoveUp implements Motion (k) - linewise
type MoveUp struct {
	Count int
}

func (a MoveUp) Execute(m action.Model) tea.Cmd {
	for i := 0; i < a.Count && m.CursorY() > 0; i++ {
		m.SetCursorY(m.CursorY() - 1)
	}
	m.ClampCursorX()
	return nil
}

func (a MoveUp) Type() action.MotionType { return action.Linewise }

func (a MoveUp) WithCount(n int) action.Action {
	return MoveUp{Count: n}
}

// MoveLeft implements Motion (h) - charwise
type MoveLeft struct {
	Count int
}

func (a MoveLeft) Execute(m action.Model) tea.Cmd {
	for i := 0; i < a.Count && m.CursorX() > 0; i++ {
		m.SetCursorX(m.CursorX() - 1)
	}
	m.ClampCursorX()
	return nil
}

func (a MoveLeft) Type() action.MotionType { return action.CharwiseExclusive }

func (a MoveLeft) WithCount(n int) action.Action {
	return MoveLeft{Count: n}
}

// MoveRight implements Motion (l) - charwise
type MoveRight struct {
	Count int
}

func (a MoveRight) Execute(m action.Model) tea.Cmd {
	lineLen := len(m.Line(m.CursorY()))
	for i := 0; i < a.Count && m.CursorX() <= lineLen; i++ {
		m.SetCursorX(m.CursorX() + 1)
	}
	m.ClampCursorX()
	return nil
}

func (a MoveRight) Type() action.MotionType { return action.CharwiseExclusive }

func (a MoveRight) WithCount(n int) action.Action {
	return MoveRight{Count: n}
}
