package uuid

import (
	"database/sql/driver"
	"encoding/hex"
	"encoding/json"
	"errors"

	"code.google.com/p/go-uuid/uuid"
)

var InvalidIDError = errors.New("Invalid ID format.")

type ID uuid.UUID

func NewID() ID {
	return ID(uuid.NewRandom())
}

func (id ID) MarshalJSON() ([]byte, error) {
	return json.Marshal(id.String())
}

func (id ID) String() string {
	return hex.EncodeToString([]byte(id))
}

func (id ID) Value() (driver.Value, error) {
	return id.String(), nil
}

func (id *ID) Scan(src interface{}) error {
	if src == nil {
		id = nil
		return nil
	}
	switch src.(type) {
	case []byte:
		newID, err := Parse(string(src.([]byte)))
		*id = append((*id)[:0], newID...)
		return err
	case string:
		newID, err := Parse(src.(string))
		*id = append((*id)[:0], newID...)
		return err
	default:
		return InvalidIDError
	}
	return nil
}

func (id *ID) UnmarshalJSON(in []byte) error {
	var tmp string
	err := json.Unmarshal(in, &tmp)
	if err != nil {
		return err
	}
	newID, err := Parse(tmp)
	if err != nil {
		return err
	}
	*id = append((*id)[:0], newID...)
	return nil
}

func Parse(in string) (ID, error) {
	b, err := hex.DecodeString(in)
	if err != nil {
		return nil, err
	}
	return ID(b), nil
}

func (id ID) Equal(other ID) bool {
	return uuid.Equal(uuid.UUID(id), uuid.UUID(other))
}
