// Copyright 2021 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package uuid defines functionality for creating UUIDs as defined in RFC 4122.
//
// Currently only Version 5 (SHA1) and Version 3 (MD5) are supported.
package uuid

import (
	"fmt"
	"math/big"
	"regexp"

	"github.com/google/uuid"
)

var valid = regexp.MustCompile(
	"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")

// Valid can be used to define a valid Valid.
func Valid(s string) error {
	if !valid.MatchString(string(s)) {
		return fmt.Errorf("invalid UUID %q", s)
	}
	return nil
}

// Parse decodes s into a UUID or returns an error. Both the standard UUID forms
// of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
func Parse(s string) (string, error) {
	x, err := uuid.Parse(s)
	return string(x.String()), err
}

// String represents a 128-bit UUID value as a string.
func ToString(x string) string {
	return string(x)
}

// URN reports the canonical URN of a UUID.
func URN(x string) (string, error) {
	u, err := uuid.Parse(string(x))
	if err != nil {
		return "", err
	}
	return u.URN(), nil
}

// FromInt creates a UUID from an integer.
//
//    DNS:  uuid.FromInt(0x6ba7b810_9dad_11d1_80b4_00c04fd430c8)
//
func FromInt(i *big.Int) (string, error) {
	// must be uint128
	var buf [16]byte
	b := i.Bytes()
	if len(b) < 16 {
		copy(buf[16-len(b):], b)
		b = buf[:]
	}
	u, err := uuid.FromBytes(b)
	return string(u.String()), err
}

// ToInt represents a UUID string as a 128-bit value.
func ToInt(x string) *big.Int {
	var i big.Int
	i.SetBytes([]byte(x[:]))
	return &i
}

// Variant reports the UUID variant.
func Variant(x string) (int, error) {
	u, err := uuid.Parse(string(x))
	if err != nil {
		return 0, err
	}
	return int(u.Variant()), nil
}

// Version reports the UUID version.
func Version(x string) (int, error) {
	u, err := uuid.Parse(string(x))
	if err != nil {
		return 0, err
	}
	return int(u.Version()), nil
}

// SHA1 generates a version 5 UUID based on the supplied name space and data.
func SHA1(space string, data []byte) (string, error) {
	u, err := uuid.Parse(string(space))
	if err != nil {
		return "", err
	}
	return string(uuid.NewSHA1(u, data).String()), nil
}

// MD5 generates a version 3 UUID based on the supplied name space and data.
// Use SHA1 instead if you can.
func MD5(space string, data []byte) (string, error) {
	u, err := uuid.Parse(string(space))
	if err != nil {
		return "", err
	}
	return string(uuid.NewMD5(u, data).String()), nil
}
