package models

import (
	"bytes"
	"html/template"
	"strconv"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

type DocumentTree struct {
	DocumentId   int               `json:"id"`
	DocumentName string            `json:"text"`
	ParentId     interface{}       `json:"parent"`
	Identify     string            `json:"identify"`
	BookIdentify string            `json:"-"`
	Version      int64             `json:"version"`
	State        *DocumentSelected `json:"state,omitempty"`
}
type DocumentSelected struct {
	Selected bool `json:"selected"`
	Opened   bool `json:"opened"`
}

//获取项目的文档树状结构
func (m *Document) FindDocumentTree(book_id int, isEdit ...bool) ([]*DocumentTree, error) {
	o := orm.NewOrm()

	trees := make([]*DocumentTree, 0)

	var docs []*Document

	count, err := o.QueryTable(m).Filter("book_id", book_id).OrderBy("order_sort", "identify").Limit(5000).All(&docs, "document_id", "version", "document_name", "parent_id", "identify")
	if err != nil {
		return trees, err
	}
	book, _ := NewBook().Find(book_id)

	trees = make([]*DocumentTree, count)

	for index, item := range docs {
		tree := &DocumentTree{}
		if index == 0 {
			tree.State = &DocumentSelected{Selected: true, Opened: true}
		}
		tree.DocumentId = item.DocumentId
		tree.Identify = item.Identify
		tree.Version = item.Version
		tree.BookIdentify = book.Identify
		if item.ParentId > 0 {
			tree.ParentId = item.ParentId
		} else {
			tree.ParentId = "#"
		}
		idf := item.Identify
		if idf == "" {
			idf = strconv.Itoa(item.DocumentId)
		}
		if len(isEdit) > 0 && isEdit[0] == true {
			tree.DocumentName = item.DocumentName + "<small class='text-danger'>(" + idf + ")</small>"
		} else {
			tree.DocumentName = item.DocumentName
		}

		trees[index] = tree
	}

	return trees, nil
}

func (m *Document) CreateDocumentTreeForHtml(book_id, selected_id int) (string, error) {
	trees, err := m.FindDocumentTree(book_id)
	if err != nil {
		return "", err
	}
	parent_id := getSelectedNode(trees, selected_id)

	buf := bytes.NewBufferString("")

	getDocumentTree(trees, 0, selected_id, parent_id, buf)

	return buf.String(), nil

}

//使用递归的方式获取指定ID的顶级ID
func getSelectedNode(array []*DocumentTree, parent_id int) int {
	for _, item := range array {
		if _, ok := item.ParentId.(string); ok && item.DocumentId == parent_id {
			return item.DocumentId
		} else if pid, ok := item.ParentId.(int); ok && item.DocumentId == parent_id {
			if pid == parent_id {
				return 0
			}
			return getSelectedNode(array, pid)
		}
	}
	return 0
}

func getDocumentTree(array []*DocumentTree, parent_id int, selected_id int, selected_parent_id int, buf *bytes.Buffer) {
	buf.WriteString("<ul>")

	for _, item := range array {
		pid := 0

		if p, ok := item.ParentId.(int); ok {
			pid = p
		}
		if pid == parent_id {

			selected := ""
			if item.DocumentId == selected_id {
				selected = ` class="jstree-clicked"`
			}
			selected_li := ""
			if item.DocumentId == selected_parent_id {
				selected_li = ` class="jstree-open"`
			}
			buf.WriteString("<li id=\"")
			buf.WriteString(strconv.Itoa(item.DocumentId))
			buf.WriteString("\"")
			buf.WriteString(selected_li)
			buf.WriteString("><a href=\"")
			if item.Identify != "" {
				uri := beego.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.Identify)
				buf.WriteString(uri)
			} else {
				uri := beego.URLFor("DocumentController.Read", ":key", item.BookIdentify, ":id", item.DocumentId)
				buf.WriteString(uri)
			}
			buf.WriteString("\" title=\"")
			buf.WriteString(template.HTMLEscapeString(item.DocumentName) + "\"")
			buf.WriteString(selected + ">")
			buf.WriteString(template.HTMLEscapeString(item.DocumentName) + "</a>")

			for _, sub := range array {
				if p, ok := sub.ParentId.(int); ok && p == item.DocumentId {
					getDocumentTree(array, p, selected_id, selected_parent_id, buf)
					break
				}
			}
			buf.WriteString("</li>")

		}
	}
	buf.WriteString("</ul>")
}
