// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package version handles version types.
package version

import (
	"fmt"
	"regexp"
	"strings"

	"golang.org/x/mod/semver"
)

// Type defines the version types a module can have.
// This must be kept in sync with the 'version_type' database enum.
type Type string

const (
	// TypeRelease is a normal release.
	TypeRelease = Type("release")

	// TypePrerelease is a version with a prerelease.
	TypePrerelease = Type("prerelease")

	// TypePseudo appears to have a prerelease of the
	// form <commit date>-<commit hash>.
	TypePseudo = Type("pseudo")
)

func (t Type) String() string {
	return string(t)
}

var pseudoVersionRE = regexp.MustCompile(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+incompatible)?$`)

// IsPseudo reports whether a valid version v is a pseudo-version.
// Modified from src/cmd/go/internal/modfetch.
func IsPseudo(v string) bool {
	return strings.Count(v, "-") >= 2 && pseudoVersionRE.MatchString(v)
}

// IsIncompatible reports whether a valid version v is an incompatible version.
func IsIncompatible(v string) bool {
	return strings.HasSuffix(v, "+incompatible")
}

// ParseType returns the Type of a given a version.
func ParseType(version string) (Type, error) {
	if !semver.IsValid(version) {
		return "", fmt.Errorf("ParseType(%q): invalid semver", version)
	}

	switch {
	case IsPseudo(version):
		return TypePseudo, nil
	case semver.Prerelease(version) != "":
		return TypePrerelease, nil
	default:
		return TypeRelease, nil
	}
}

// ForSorting returns a string that encodes version, so that comparing two such
// strings follows SemVer precedence, https://semver.org clause 11. It assumes
// version is valid. The returned string ends in '~' if and only if the version
// does not have a prerelease.
//
// For examples, see TestForSorting.
func ForSorting(version string) string {
	bytes := make([]byte, 0, len(version))
	prerelease := false // we are in the prerelease part
	nondigit := false   // this part has a non-digit character
	start := 1          // skip 'v'
	last := len(version)

	// Add the semver component version[start:end] to the result.
	addPart := func(end int) {
		if len(bytes) > 0 {
			// ',' comes before '-' and all letters and digits, so it correctly
			// imposes lexicographic ordering on the parts of the version.
			bytes = append(bytes, ',')
		}
		if nondigit {
			// Prepending the largest printable character '~' to a non-numeric
			// part, along with the fact that encoded numbers never begin with a
			// '~', (see appendNumericPrefix), ensures the semver requirement
			// that numeric identifiers always have lower precedence than
			// non-numeric ones.
			bytes = append(bytes, '~')
		} else {
			bytes = appendNumericPrefix(bytes, end-start)
		}
		bytes = append(bytes, version[start:end]...)
		start = end + 1 // skip over separator character
		nondigit = false
	}

loop:
	for i, c := range version[start:] {
		p := i + 1
		switch {
		case c == '.': // end of a part
			addPart(p)
		case c == '-': // first one is start of prerelease
			if !prerelease {
				prerelease = true
				addPart(p)
			} else {
				nondigit = true
			}
		case c == '+': // start of build; nothing after this matters
			last = p
			break loop

		case c < '0' || c > '9':
			nondigit = true
		}
	}
	if start < last {
		addPart(last)
	}
	if !prerelease {
		// Make sure prereleases appear first.
		bytes = append(bytes, '~')
	}
	return string(bytes)
}

// appendNumericPrefix appends a string representing n to dst.
// n is the length of a digit string; the value we append is a prefix for the
// digit string s such that
//   prefix1 + s1 < prefix2 + s2
// if and only if the integer denoted by s1 is less than the one denoted by s2.
// In other words, prefix + s is a string that can be compared with other such
// strings while preserving the ordering of the numbers.
//
// If n==1, there is no prefix. (Single-digit numbers are unchanged.)
// Otherwise, the prefix is a sequence of lower-case letters encoding n.
// Examples:
//   n    prefix
//   1    <none>
//   2    a
//   27   z
//   28   za
//   53   zz
//   54   zza
// This encoding depends on the ASCII properties that:
// - digits are ordered numerically
// - letters are ordered alphabetically
// - digits order before letters (so "1" < "a10")
func appendNumericPrefix(dst []byte, n int) []byte {
	n--
	for i := 0; i < n/26; i++ {
		dst = append(dst, 'z')
	}
	if rem := n % 26; rem > 0 {
		dst = append(dst, byte('a'+rem-1))
	}
	return dst
}

// Later reports whether v1 is later than v2, using semver but preferring
// release versions to pre-release versions, and both to pseudo-versions.
func Later(v1, v2 string) bool {
	rel1 := semver.Prerelease(v1) == ""
	rel2 := semver.Prerelease(v2) == ""
	if rel1 && rel2 {
		return semver.Compare(v1, v2) > 0
	}
	if rel1 != rel2 {
		return rel1
	}
	// Both are pre-release.
	pseudo1 := IsPseudo(v1)
	pseudo2 := IsPseudo(v2)
	if pseudo1 == pseudo2 {
		return semver.Compare(v1, v2) > 0
	}
	return !pseudo1
}

// Latest finds the latest version of a module using the same algorithm as the
// Go command. It prefers tagged release versions to tagged pre-release
// versions, and both of those to pseudo-versions. If versions is empty, Latest
// returns the empty string.
//
// hasGoMod should report whether the version it is given has a go.mod file.
// Latest returns the latest incompatible version only if the latest compatible
// version does not have a go.mod file.
//
// The meaning of latest is defined at
// https://golang.org/ref/mod#version-queries. That definition does not deal
// with retractions, or with a subtlety involving incompatible versions. The
// actual definition is embodied in the go command's queryMatcher.filterVersions
// method. This function is a re-implementation and specialization of that
// method at Go version 1.16
// (https://go.googlesource.com/go/+/refs/tags/go1.16/src/cmd/go/internal/modload/query.go#441).
func Latest(versions []string, hasGoMod func(v string) (bool, error)) (v string, err error) {
	latest := LatestOf(versions)
	if latest == "" {
		return "", nil
	}

	// If the latest is a compatible version, use it.
	if !IsIncompatible(latest) {
		return latest, nil
	}
	// The latest version is incompatible. If there is a go.mod file at the
	// latest compatible tagged version, assume the module author has adopted
	// proper versioning, and use that latest compatible version. Otherwise, use
	// this incompatible version.
	latestCompat := LatestOf(RemoveIf(versions, func(v string) bool { return IsIncompatible(v) || IsPseudo(v) }))
	if latestCompat == "" {
		// No compatible versions; use the latest (incompatible) version.
		return latest, nil
	}
	latestCompatHasGoMod, err := hasGoMod(latestCompat)
	if err != nil {
		return "", err
	}
	if latestCompatHasGoMod {
		return latestCompat, nil
	}
	return latest, nil
}

// LatestOf returns the latest version of a module from a list of versions, using
// the go command's definition of latest: semver is observed, except that
// release versions are preferred to prerelease, and both are preferred to pseudo-versions.
// If versions is empty, the empty string is returned.
func LatestOf(versions []string) string {
	if len(versions) == 0 {
		return ""
	}
	latest := versions[0]
	for _, v := range versions[1:] {
		if Later(v, latest) {
			latest = v
		}
	}
	return latest
}

// RemoveIf returns a copy of s that omits all values for which f returns true.
func RemoveIf(s []string, f func(string) bool) []string {
	var r []string
	for _, x := range s {
		if !f(x) {
			r = append(r, x)
		}
	}
	return r
}
