package exql

import (
	"strings"
)

// isBlankSymbol returns true if the given byte is either space, tab, carriage
// return or newline.
func isBlankSymbol(in byte) bool {
	return in == ' ' || in == '\t' || in == '\r' || in == '\n'
}

// trimString returns a slice of s with a leading and trailing blank symbols
// (as defined by isBlankSymbol) removed.
func trimString(s string) string {

	// This conversion is rather slow.
	// return string(trimBytes([]byte(s)))

	start, end := 0, len(s)-1

	if end < start {
		return ""
	}

	for isBlankSymbol(s[start]) {
		start++
		if start >= end {
			return ""
		}
	}

	for isBlankSymbol(s[end]) {
		end--
	}

	return s[start : end+1]
}

// trimBytes returns a slice of s with a leading and trailing blank symbols (as
// defined by isBlankSymbol) removed.
func trimBytes(s []byte) []byte {

	start, end := 0, len(s)-1

	if end < start {
		return []byte{}
	}

	for isBlankSymbol(s[start]) {
		start++
		if start >= end {
			return []byte{}
		}
	}

	for isBlankSymbol(s[end]) {
		end--
	}

	return s[start : end+1]
}

/*
// Separates by a comma, ignoring spaces too.
// This was slower than strings.Split.
func separateByComma(in string) (out []string) {

	out = []string{}

	start, lim := 0, len(in)-1

	for start < lim {
		var end int

		for end = start; end <= lim; end++ {
			// Is a comma?
			if in[end] == ',' {
				break
			}
		}

		out = append(out, trimString(in[start:end]))

		start = end + 1
	}

	return
}
*/

// Separates by a comma, ignoring spaces too.
func separateByComma(in string) (out []string) {
	out = strings.Split(in, ",")
	for i := range out {
		out[i] = trimString(out[i])
	}
	return
}

// Separates by spaces, ignoring spaces too.
func separateBySpace(in string) (out []string) {
	if len(in) == 0 {
		return []string{""}
	}

	pre := strings.Split(in, " ")
	out = make([]string, 0, len(pre))

	for i := range pre {
		pre[i] = trimString(pre[i])
		if pre[i] != "" {
			out = append(out, pre[i])
		}
	}

	return
}

func separateByAS(in string) (out []string) {
	out = []string{}

	if len(in) < 6 {
		// The minimum expression with the AS keyword is "x AS y", 6 chars.
		return []string{in}
	}

	start, lim := 0, len(in)-1

	for start <= lim {
		var end int

		for end = start; end <= lim; end++ {
			if end > 3 && isBlankSymbol(in[end]) && isBlankSymbol(in[end-3]) {
				if (in[end-1] == 's' || in[end-1] == 'S') && (in[end-2] == 'a' || in[end-2] == 'A') {
					break
				}
			}
		}

		if end < lim {
			out = append(out, trimString(in[start:end-3]))
		} else {
			out = append(out, trimString(in[start:end]))
		}

		start = end + 1
	}

	return
}
