package console

import (
	"bytes"
	"fmt"
	"strings"
	"unicode/utf8"
)

type Options struct {
	Bordered bool
	Header   bool
}

func printBorder(w *bytes.Buffer, ws []int) {
	for _, l := range ws {
		w.WriteString("+")
		w.WriteString(strings.Repeat("-", l+2))
	}
	w.WriteString("+\n")
}

func calcCharsetWidth(s string) int {
	bl := len(s)
	ul := utf8.RuneCountInString(s)
	if bl == ul {
		return bl
	} else {
		var wc int
		//计算中文词语数量，并且替换为2个长度显示
		for wc = ((bl - ul) / 3); wc < ul; wc++ {
			if wc*3-wc == bl-ul {
				break
			}
		}
		wv := wc*2 + (ul - wc)
		return wv
	}
}

func Pretty(values [][]interface{}, opts *Options) []byte {
	columns := make([][]string, 0)
	var widths []int
	var width int
	var maxLength int
	if opts == nil {
		opts = &Options{}
	}
	calcWidth := calcCharsetWidth
	for _, value := range values {
		if len(value) > maxLength {
			maxLength = len(value)
		}
	}
	widths = make([]int, maxLength)
	for _, vs := range values {
		vl := len(vs)
		column := make([]string, vl)
		for i, val := range vs {
			str := fmt.Sprint(val)
			if vl > 1 {
				width = calcWidth(str)
				if width > widths[i] {
					widths[i] = width
				}
			}
			column[i] = str
		}
		columns = append(columns, column)
	}
	buffer := &bytes.Buffer{}
	if opts.Bordered {
		printBorder(buffer, widths)
	}
	for index, column := range columns {
		cl := len(column)
		for i, w := range widths {
			if opts.Bordered {
				buffer.WriteString("|")
			}
			var str string
			if cl > i {
				str = column[i]
			}
			if opts.Bordered {
				buffer.WriteString(" ")
			}
			buffer.WriteString(str)
			cl := calcWidth(str)
			if widths[i] >= cl {
				buffer.WriteString(strings.Repeat(" ", w-cl))
			}
			buffer.WriteString(" ")
			//key value options
			if len(widths) == 2 && i == 0 && len(column) == 2 && !opts.Bordered && !opts.Header {
				buffer.WriteString("\t")
			}
		}
		if opts.Bordered {
			buffer.WriteString("|\n")
		} else {
			buffer.WriteString("\n")
		}
		if opts.Header && index == 0 {
			printBorder(buffer, widths)
		}
	}
	if opts.Bordered {
		printBorder(buffer, widths)
	}
	return buffer.Bytes()
}
