package ocilayout

import (
	"strings"

	"github.com/distribution/reference"
	digest "github.com/opencontainers/go-digest"
)

type Ref struct {
	Path   string
	Tag    string
	Digest digest.Digest
}

const prefix = "oci-layout://"

func Parse(s string) (Ref, bool, error) {
	if !strings.HasPrefix(s, prefix) {
		return Ref{}, false, nil
	}

	localPath := strings.TrimPrefix(s, prefix)
	var out Ref

	if i := strings.LastIndex(localPath, "@"); i >= 0 {
		after := localPath[i+1:]
		if reference.DigestRegexp.MatchString(after) {
			dgst, err := digest.Parse(after)
			if err != nil {
				return Ref{}, true, err
			}
			localPath, out.Digest = localPath[:i], dgst
		}
	}

	if i := strings.LastIndex(localPath, ":"); i >= 0 && !isWindowsDrivePath(localPath, i) {
		after := localPath[i+1:]
		if reference.TagRegexp.MatchString(after) {
			localPath, out.Tag = localPath[:i], after
		}
	}

	out.Path = localPath
	if out.Tag == "" && out.Digest == "" {
		out.Tag = "latest"
	}
	return out, true, nil
}

func (r Ref) String() string {
	s := prefix + r.Path
	if r.Tag != "" {
		s += ":" + r.Tag
	}
	if r.Digest != "" {
		s += "@" + r.Digest.String()
	}
	return s
}

func isWindowsDrivePath(path string, colon int) bool {
	if colon != 1 || len(path) < 3 {
		return false
	}
	if path[2] != '/' && path[2] != '\\' {
		return false
	}
	c := path[0]
	return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
}
