package curl2info

import (
	"container/heap"
	"log"
	"strings"

	"github.com/davecgh/go-spew/spew"
)

// trieWord Trie 需要的Word接口
type trieWord interface {
	GetWord() string
}

// TrieStrWord 最简单的TrieWord 结构
type trieStrWord string

// GetWord 获取单词
func (tsw *trieStrWord) GetWord() string {
	return (string)(*tsw)
}

// Trie 前缀树
type hTrie struct {
	isWord bool
	value  interface{}
	char   byte
	prev   *hTrie
	next   map[byte]*hTrie
}

// newTrie Initialize your data structure here.
func newTrie() *hTrie {
	return &hTrie{next: make(map[byte]*hTrie)}
}

// Insert a word into the trie.
func (trie *hTrie) Insert(iword trieWord) {
	cur := trie
	word := iword.GetWord()
	l := len(word)

	for i := 0; i < l; i++ {
		c := word[i]
		if next, ok := cur.next[c]; ok {
			cur = next
		} else {
			create := newTrie()
			cur.next[c] = create
			create.char = c
			create.prev = cur
			cur = create
		}
	}

	cur.isWord = true
	cur.value = iword
}

// AllWords 所有单词
func (trie *hTrie) AllWords() []string {
	var result []string
	for _, v := range trie.next {
		look(v, "", &result)
	}
	return result
}

func look(cur *hTrie, content string, result *[]string) {
	content += string(cur.char)
	if cur.isWord {
		*result = append(*result, content)
	}
	for _, v := range cur.next {
		look(v, content, result)
	}
}

// Remove 移除单词
func (trie *hTrie) Remove(word string) {
	cur := trie
	l := len(word)
	for i := 0; i < l; i++ {
		c := word[i]
		if next, ok := cur.next[c]; ok {
			cur = next
		} else {
			return
		}
	}

	if cur != nil {
		cur.isWord = false
		cur.value = nil

		lastchar := cur.char

		if len(cur.next) == 0 {
			for cur.isWord != true && cur.prev != nil {
				lastchar = cur.char
				cur = cur.prev
				if len(cur.next) > 1 {
					return
				}
			}
			delete(cur.next, lastchar)
		}
	}
}

// SearchMostPrefix Returns if the word is in the trie.
func (trie *hTrie) SearchDepth(iword trieWord) interface{} {
	cur := trie
	word := iword.GetWord()

	l := len(word)

	var result interface{}
	for i := 0; i < l; i++ {
		c := word[i]
		if next, ok := cur.next[c]; ok {
			cur = next
			if cur.isWord {
				result = cur.value
			} else {
				result = nil
			}
		} else {
			return result
		}
	}
	return result
}

// Match Returns if the word is in the trie.
func (trie *hTrie) Match(iword trieWord) interface{} {
	cur := trie
	word := iword.GetWord()

	l := len(word)
	for i := 0; i < l; i++ {
		c := word[i]
		if next, ok := cur.next[c]; ok {
			cur = next
		} else {
			return nil
		}
	}

	return cur.value
}

// StartsWith Returns if there is any word in the trie that starts with the given prefix. */
func (trie *hTrie) StartsWith(prefix string) bool {
	cur := trie
	l := len(prefix)
	for i := 0; i < l; i++ {
		c := prefix[i]
		if next, ok := cur.next[c]; ok {
			cur = next
		} else {
			return false
		}
	}
	return true
}

// 优先队列 所在的域

// parseQueue for Heap, Container List
type parseQueue []*parseFunction

// parseFunction 优先执行参数
type parseFunction struct {
	ExecuteFunction func(u *CURL, soption string)
	ParamCURL       *CURL
	ParamData       string
	Priority        int
}

// Execute 执行 函数
func (pf *parseFunction) Execute() {
	pf.ExecuteFunction(pf.ParamCURL, pf.ParamData)
}

// Swap 实现sort.Iterface
func (nodes *parseQueue) Swap(i, j int) {
	ns := *nodes
	ns[i], ns[j] = ns[j], ns[i]
}

// Less Priority Want Less
func (nodes *parseQueue) Less(i, j int) bool {
	ns := *nodes
	return ns[i].Priority < ns[j].Priority
}

// Push 实现heap.Interface接口定义的额外方法
func (nodes *parseQueue) Push(exec interface{}) {
	*nodes = append(*nodes, exec.(*parseFunction))
}

// Pop 堆顶
func (nodes *parseQueue) Pop() (exec interface{}) {
	nlen := nodes.Len()
	exec = (*nodes)[nlen-1]    // 返回删除的元素
	*nodes = (*nodes)[:nlen-1] // [n:m]不包括下标为m的元素
	return exec
}

// Len len(nodes)
func (nodes *parseQueue) Len() int {
	return len(*nodes)
}

// pQueueExecute 优先函数队列
type pQueueExecute struct {
	nodes parseQueue
}

// newPQueueExecute Create A pQueueExecute
func newPQueueExecute() *pQueueExecute {
	pe := &pQueueExecute{}
	pe.nodes = make(parseQueue, 0)
	heap.Init(&pe.nodes)
	return pe
}

// Push Create A pQueueExecute
func (pqe *pQueueExecute) Push(exec *parseFunction) {
	heap.Push(&pqe.nodes, exec)
}

// Pop Create A pQueueExecute
func (pqe *pQueueExecute) Pop() *parseFunction {
	return heap.Pop(&pqe.nodes).(*parseFunction)
}

// Len Create A pQueueExecute
func (pqe *pQueueExecute) Len() int {
	return pqe.nodes.Len()
}

// func (pqe *pQueueExecute) String() string {
// 	content := ""
// 	for _, node := range pqe.nodes {
// 		content += strconv.Itoa(node.Prioty)
// 		content += " "
// 	}
// 	return content
// }

// CNode 循环链表 三色标记 不确定是否会清除循环引用, 网上说会
type CNode struct {
	value interface{}
	prev  *CNode
	next  *CNode
}

// GetValue 获取到Node的值
func (node *CNode) GetValue() interface{} {
	return node.value
}

// SetValue 获取到Node的值
func (node *CNode) SetValue(value interface{}) {
	node.value = value
}

// CircularLinked 循环链表
type CircularLinked struct {
	cursor *CNode
	head   *CNode
	tail   *CNode
	size   uint64
}

// NewCircularLinked create a CircularLinked
func NewCircularLinked(values ...interface{}) *CircularLinked {
	list := &CircularLinked{}
	if len(values) > 0 {
		list.Append(values...)
	}
	return list
}

// Cursor get current Cursor
func (list *CircularLinked) Cursor() *CNode {
	if list.cursor == nil {
		list.cursor = list.head
	}
	return list.cursor
}

// MoveNext get next Cursor
func (list *CircularLinked) MoveNext() *CNode {
	if list.cursor == nil {
		list.cursor = list.head
	}
	list.cursor = list.cursor.next
	return list.cursor
}

// MovePrev get prev Cursor
func (list *CircularLinked) MovePrev() *CNode {
	if list.cursor == nil {
		list.cursor = list.head
	}
	list.cursor = list.cursor.prev
	return list.cursor
}

// CursorToHead cursor move to head
func (list *CircularLinked) CursorToHead() *CNode {
	list.cursor = list.head
	return list.cursor
}

// CursorToTail cursor move to tail
func (list *CircularLinked) CursorToTail() *CNode {
	list.cursor = list.tail
	return list.cursor
}

// GetLoopValues 获取从头到尾的值
func (list *CircularLinked) GetLoopValues() []*CNode {
	var result []*CNode

	if list.head != nil {
		result = append(result, list.head)
		for cur := list.head.next; cur != list.head; cur = cur.next {
			result = append(result, cur)
		}
	}
	return result
}

// Append a value (one or more) at the end of the list (same as Append())
func (list *CircularLinked) Append(values ...interface{}) {
	for _, value := range values {
		node := &CNode{value: value}
		if list.size == 0 {
			list.head = node
			list.tail = node
			node.next = node
			node.prev = node
		} else {
			list.tail.next = node
			node.next = list.head
			node.prev = list.tail
			list.tail = node
		}
		list.size++
	}
}

// Remove 移除一些节点
func (list *CircularLinked) Remove(node *CNode) {

	switch list.size {
	case 0:
		list.errorNotInList(node)
	case 1:
		if list.head == node {
			list.head = nil
			list.tail = nil
			node.next = nil
			node.prev = nil
			list.cursor = nil
			list.size--
		} else {
			list.errorNotInList(node)
		}
	case 2:

		node.prev = nil
		node.next = nil

		switch node {
		case list.head:
			list.head = list.tail
			list.tail.prev = list.head
			list.head.next = list.tail
			list.cursor = list.head
			list.size--
		case list.tail:
			list.tail = list.head
			list.tail.prev = list.head
			list.head.next = list.tail
			list.cursor = list.head
			list.size--
		default:
			list.errorNotInList(node)
		}

	default:
		switch node {
		case list.head:
			_, next := list.cutAndSplice(node)
			list.size--
			list.head = next
			if list.cursor == node {
				list.cursor = next
			}
		case list.tail:
			prev, _ := list.cutAndSplice(node)
			list.size--
			list.tail = prev
			if list.cursor == node {
				list.cursor = prev
			}
		default:
			_, next := list.cutAndSplice(node)
			list.size--
			if list.cursor == node {
				list.cursor = next
			}
		}
	}

}

// LookCursor for list show
func (list *CircularLinked) LookCursor() string {
	cursor := list.Cursor()

	content := "->["
	cur := list.head
	if list.size != 0 {
		for size := uint64(0); size < list.size; size++ {
			if cursor == cur {
				content += "(" + spew.Sprint(cur.value) + ")" + ", "
			} else {
				content += spew.Sprint(cur.value) + ", "
			}

			cur = cur.next
		}
	}
	content = strings.TrimRight(content, ", ")
	showlen := len(content)
	if showlen >= 64 {
		showlen = 64
	}
	content += "]" + content[0:showlen] + " ..."
	return content
}

// Clear for list show
func (list *CircularLinked) Clear() {
	if list.size != 0 {
		list.head.prev = nil
		list.tail.next = nil
		list.head = nil
		list.tail = nil
		list.cursor = nil
		list.size = 0
	}
}

// Size for list show
func (list *CircularLinked) Size() uint64 {
	return list.size
}

func (list *CircularLinked) errorNotInList(node *CNode) {
	log.Println("the node value ", spew.Sprint(node), " is not in list")
}

// cutAndSplice 不考虑边界情况 上层使用的是否判断
func (list *CircularLinked) cutAndSplice(node *CNode) (prev, next *CNode) {
	prev = node.prev
	next = node.next

	prev.next = next
	next.prev = prev

	node.prev = nil
	node.next = nil

	return prev, next
}
