package ii

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"strings"
)

type Name struct {
	database   string
	collection string
	alias      string
}

func (n *Name) DbName() string {
	if n.alias != "" {
		return n.alias
	}
	return n.database
}

func (n *Name) Collection() string {
	return n.collection
}

func (n *Name) ItemName() string {
	return fmt.Sprintf("%s.%s", n.DbName(), n.collection)
}

func (n *Name) SetAlias(alias string) {
	n.alias = alias
}

func (n *Name) String() string {
	if n.alias != "" {
		return fmt.Sprintf("%s(%s).%s", n.alias, n.database, n.collection)
	}
	return fmt.Sprintf("%s.%s", n.database, n.collection)
}

func (n *Name) UnmarshalXMLAttr(attr xml.Attr) error {
	return n.resolve(attr.Value)
}

func (n *Name) MarshalJSON() ([]byte, error) {
	value := fmt.Sprintf(`"%s"`, n.ItemName())
	return []byte(value), nil
}

func (n *Name) UnmarshalJSON(v []byte) error {
	var temp string
	if err := json.Unmarshal(v, &temp); err != nil {
		return err
	}
	return n.resolve(temp)
}

func (n *Name) resolve(v string) error {
	name := strings.Split(v, ".")
	if len(name) != 2 {
		return fmt.Errorf("itemname error: %s", v)
	}
	if strings.TrimSpace(name[0]) == "" || strings.TrimSpace(name[1]) == "" {
		return fmt.Errorf("itemname error: %s", v)
	}
	n.database = name[0]
	n.collection = name[1]
	return nil
}

func NewNameErr(itemName string) (Name, error) {
	var n = Name{}
	return n, n.resolve(itemName)
}

func NewName(db, col string) Name {
	n, _ := NewNameErr(db + "." + col)
	return n
}

func NewNameMust(itemName string) Name {
	n, err := NewNameErr(itemName)
	if err != nil {
		panic(err)
	}
	return n
}
