package util

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

// Mang cac ky tu goc co dau
var SOURCE_CHARACTERS, LL_LENGTH = StringToRune(`ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯưẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐốỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰự`)

// Mang cac ky tu thay the khong dau var
var DESTINATION_CHARACTERS, _ = StringToRune(`AAAAEEEIIOOOOUUYaaaaeeeiioooouuyAaDdIiUuOoUuAaAaAaAaAaAaAaAaAaAaAaAaEeEeEeEeEeEeEeEeIiIiOoOoOoOoOoOoOoOoOoOoOoOoUuUuUuUuUuUuUu`)

func StringToRune(s string) ([]string, int) {
	ll := utf8.RuneCountInString(s)
	var texts = make([]string, ll+1)
	var index = 0
	for _, runeValue := range s {
		texts[index] = string(runeValue)
		index++
	}
	return texts, ll
}

func BinarySearch(sortedArray []string, key string, low int, high int) int {
	var middle int = (low + high) / 2
	if high < low {
		return -1
	}

	if key == sortedArray[middle] {
		return middle
	} else if key < sortedArray[middle] {
		return BinarySearch(sortedArray, key, low, middle-1)
	} else {
		return BinarySearch(sortedArray, key, middle+1, high)
	}
}

/** * Bo dau 1 ky tu * * @param ch * @return */
func RemoveAccentChar(ch string) string {
	var index int = BinarySearch(SOURCE_CHARACTERS, ch, 0, LL_LENGTH)
	if index >= 0 {
		ch = DESTINATION_CHARACTERS[index]
	}
	return ch
}

/** * Bo dau 1 chuoi * * @param s * @return */
func RemoveAccent(s string) string {
	var buffer bytes.Buffer
	for _, runeValue := range s {
		buffer.WriteString(RemoveAccentChar(string(runeValue)))
	}
	return buffer.String()
}

func RemoveMultiSpace(str string) string {
	reLeadCloseSpace := regexp.MustCompile(`^[\s\p{Zs}]+|[\s\p{Zs}]+$`)
	reInsideSpace := regexp.MustCompile(`[\s\p{Zs}]{2,}`)
	final := reLeadCloseSpace.ReplaceAllString(str, "")
	final = reInsideSpace.ReplaceAllString(final, " ")
	return final
}

func RemoveDuplicateInt(intSlice []int) []int {
	allKeys := make(map[int]bool)
	var list []int
	for _, item := range intSlice {
		if _, value := allKeys[item]; !value {
			allKeys[item] = true
			list = append(list, item)
		}
	}
	return list
}

func RemoveDuplicateString(str string) string {
	words := strings.Fields(str)
	removedDuplicateWords := RemoveDuplicate(words)
	return strings.Join(removedDuplicateWords, " ")
}

func RemoveDuplicate(strSlice []string) []string {
	allKeys := make(map[string]bool)
	var list []string
	for _, item := range strSlice {
		if _, value := allKeys[item]; !value {
			allKeys[item] = true
			list = append(list, item)
		}
	}
	return list
}

func StripRegex(in string) string {
	reg, _ := regexp.Compile("[^a-zA-Z0-9 ]+")
	return reg.ReplaceAllString(in, " ")
}

func StripKeywords(str string) string {
	str = RemoveAccent(str)
	str = StripRegex(str)
	str = RemoveDuplicateString(str)
	str = strings.ToLower(str)
	return str
}
