package tui

import (
	"image/color"
	"strings"

	"github.com/charmbracelet/lipgloss"
	"github.com/charmbracelet/x/ansi"
	"github.com/lucasb-eyer/go-colorful"
	"github.com/muesli/gamut"
)

func absInt(a int) int {
	if a >= 0 {
		return a
	}
	return -a
}

// StackLine 行堆叠，输出字符串的长度为down的长度，x表示up向右横移的字符数
func StackLine(up, down string, x int) string {
	lup, ldown := ansi.StringWidth(up), ansi.StringWidth(down)
	if x >= 0 {
		if x >= ldown {
			return down
		}
		result := ansi.Truncate(down, x, "")
		if x+lup >= ldown {
			result += ansi.Truncate(up, ldown-x, "")
		} else {
			result += up
			result += ansi.TruncateLeft(down, x+lup, "")
		}
		return result
	} else {
		if absInt(x) >= lup {
			return down
		}
		result := ansi.TruncateLeft(up, absInt(x), "")
		l := ansi.StringWidth(result)
		if l < ldown {
			result += ansi.TruncateLeft(down, lup+x, "")
		} else {
			result = ansi.Truncate(result, ldown, "")
		}
		return result
	}
}

// Stack 堆叠两个字符串，输出的字符串尺寸与down的尺寸一致
func Stack(up, down string, x, y int) string {
	downHeight := lipgloss.Height(down)
	downLines := strings.Split(strings.Trim(down, "\n"), "\n")
	upLines := strings.Split(strings.Trim(up, "\n"), "\n")
	result := make([]string, downHeight)
	if y >= 0 {
		if y >= downHeight {
			result = downLines
		} else {
			for k, v := range downLines {
				if k-y >= 0 && k-y < len(upLines) {
					result[k] = StackLine(upLines[k-y], v, x)
				} else {
					result[k] = downLines[k]
				}
			}
		}
	} else {
		if absInt(y) > len(upLines) {
			result = downLines
		} else {
			for k, v := range downLines {
				if k-y < len(upLines) {
					result[k] = StackLine(upLines[k-y], v, x)
				} else {
					result[k] = downLines[k]
				}
			}
		}
	}
	r := strings.Join(result, "\n")
	if down[len(down)-1] == '\n' {
		r += "\n"
	}
	return r
}

// StackPosition 按照位置堆叠
func StackPosition(up, down string, vPos, hPos lipgloss.Position) string {
	upW, upH := lipgloss.Size(up)
	downW, downH := lipgloss.Size(down)

	switch vPos {
	case lipgloss.Top:
		switch hPos {
		case lipgloss.Left:
			// 上左
			return Stack(up, down, 0, 0)
		case lipgloss.Center:
			// 上中
			return Stack(up, down, (downW-upW)/2, 0)
		case lipgloss.Right:
			// 上右
			return Stack(up, down, downW-upW, 0)
		}
	case lipgloss.Center:
		switch hPos {
		case lipgloss.Left:
			// 中左
			return Stack(up, down, 0, (downH-upH)/2)
		case lipgloss.Center:
			// 中中
			return Stack(up, down, (downW-upW)/2, (downH-upH)/2)
		case lipgloss.Right:
			// 中右
			return Stack(up, down, downW-upW, (downH-upH)/2)
		}
	case lipgloss.Bottom:
		switch hPos {
		case lipgloss.Left:
			// 下左
			return Stack(up, down, 0, downH-upH)
		case lipgloss.Center:
			// 下中
			return Stack(up, down, (downW-upW)/2, downH-upH)
		case lipgloss.Right:
			// 下右
			return Stack(up, down, downW-upW, downH-upH)
		}
	}

	return ""
}

// FormatStr 格式化字符串，输出的字符串可视长度为length，hPos表示是左对齐还是右对齐
// str必须为单行字符串，没有\n
func FormatStr(str string, length int, hPos lipgloss.Position) string {
	realLen := lipgloss.Width(str)
	if realLen < length {
		switch hPos {
		case lipgloss.Left:
			return str + strings.Repeat(" ", length-realLen)
		case lipgloss.Right:
			return strings.Repeat(" ", length-realLen) + str
		}
	} else if realLen > length {
		// 需要截断
		switch hPos {
		case lipgloss.Left: // 左对齐
			return ansi.Truncate(str, length, "")
		case lipgloss.Right: // 右对齐
			return ansi.TruncateLeft(str, realLen-length, "")
		}
	}
	return str
}

func ConvertColor(color []color.Color) []lipgloss.Color {
	if len(color) == 0 {
		return nil
	}
	result := make([]lipgloss.Color, len(color))
	for k, v := range color {
		c, _ := colorful.MakeColor(v)
		result[k] = lipgloss.Color(c.Hex())
	}
	return result
}

// GenGradientColor 生成渐变色
func GenGradientColor(from, to lipgloss.Color, num int) []lipgloss.Color {
	return ConvertColor(gamut.Blends(from, to, num))
}
