package domain

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

const PathSegment = ","

var (
	Catalog MenuType = "catalog" // 目录
	Menu_   MenuType = "menu"    // 菜单
	Button  MenuType = "button"  // 按钮
)

var (
	ErrorMenuType = errors.New(fmt.Sprintf("菜单类型有误 可选值 %v、%v、%v", Catalog, Menu_, Button))
)

// 菜单类型
type MenuType string

// 系统菜单
type Menu struct {
	// 菜单编号
	MenuId int64 `json:"menuId"`
	// 父级id
	ParentId int64 `json:"parentId"`
	// 菜单名称
	MenuName string `json:"menuName"`
	// 菜单编码 SYSTEM_USER_EDIT / 100101 (字符编码)
	Code string `json:"code"`
	// 权限编码 users:edit
	AccessCode string `json:"accessCode"`
	// 菜单类型 (目录catalog、菜单menu、按钮button)
	MenuType string `json:"menuType"`
	// 菜单图标
	Icon string `json:"icon"`
	// 排序
	Sort int `json:"sort"`
	// 菜单说明
	Remark string `json:"remark"`
	// 菜单类别 (web:1、app:2)
	Category string `json:"category"`
	// 路径节点路径("0,11,12,")
	ParentPath string `json:"parentPath"`
	// 菜单是否公开状态,[0:隐藏],[1:显示],默认显示
	IsPublish int `json:"isPublish"`
	// 菜单是否是系统级,[0:否],[1:是],默认否
	IsSystem int `json:"isSystem"`
}

type MenuRepository interface {
	Save(menu *Menu) (*Menu, error)
	Remove(menu *Menu) (*Menu, error)
	FindOne(queryOptions map[string]interface{}) (*Menu, error)
	Find(queryOptions map[string]interface{}) (int64, []*Menu, error)
}

func (menu *Menu) Identify() interface{} {
	if menu.MenuId == 0 {
		return nil
	}
	return menu.MenuId
}

func (menu *Menu) Update(data map[string]interface{}) error {
	if parentId, ok := data["parentId"]; ok {
		menu.ParentId = parentId.(int64)
	}
	if menuName, ok := data["menuName"]; ok {
		menu.MenuName = menuName.(string)
	}
	if code, ok := data["code"]; ok {
		menu.Code = code.(string)
	}
	if accessCode, ok := data["accessCode"]; ok {
		menu.AccessCode = accessCode.(string)
	}
	if menuType, ok := data["menuType"]; ok {
		menu.MenuType = menuType.(string)
	}
	if icon, ok := data["icon"]; ok {
		menu.Icon = icon.(string)
	}
	if sort, ok := data["sort"]; ok {
		menu.Sort = sort.(int)
	}
	if desc, ok := data["desc"]; ok {
		menu.Remark = desc.(string)
	}
	//if category, ok := data["category"]; ok {
	//	menu.Category = category.(string)
	//}
	//if fullPath, ok := data["fullPath"]; ok {
	//	menu.ParentPath = parentPath.(string)
	//}
	if isPublish, ok := data["isPublish"]; ok {
		menu.IsPublish = isPublish.(int)
	}
	if isSystem, ok := data["isSystem"]; ok {
		menu.IsSystem = isSystem.(int)
	}
	return nil
}

// GetParentPath 获取菜单路径
func (menu *Menu) GetParentPath() string {
	if menu.ParentId == 0 {
		return ""
	}
	if len(menu.ParentPath) > 0 {
		return fmt.Sprintf("%v%v%v", menu.ParentPath, PathSegment, menu.MenuId)
	}
	return fmt.Sprintf("%v", menu.MenuId)
}

// GetFullPath 获取菜单全路径
func (menu *Menu) GetFullPath() string {
	if menu.ParentId == 0 {
		return ""
	}
	if len(menu.ParentPath) > 0 {
		return fmt.Sprintf("%v%v%v", menu.ParentPath, PathSegment, menu.MenuId)
	}
	return fmt.Sprintf("%v", menu.MenuId)
}

// GetCategory 获取菜单类别 1.web 2.app
func (menu *Menu) GetCategory() string {
	if menu.Category == "" {
		return strconv.Itoa(int(menu.MenuId))
	}
	return menu.Category
}

func (menu *Menu) UpdateParentPath(old, new string) {
	if !strings.Contains(menu.ParentPath, old) {
		return
	}
	menu.ParentPath = strings.Replace(menu.ParentPath, old, new, 1)
}

func (menu *Menu) ValidMenuType() bool {
	mt := MenuType(menu.MenuType)
	if mt == Catalog || mt == Menu_ || mt == Button {
		return true
	}
	return false
}

// 实现 TreeNode
func (menu *Menu) PID() string {
	return menu.ParentPath
}
func (menu *Menu) ID() string {
	return menu.GetFullPath()
}