/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 newtutil

import (
	"fmt"
	"math"
	"sort"
	"strconv"
	"strings"

	"mynewt.apache.org/newt/util"
)

const (
	VERSION_STABILITY_NONE   = ""
	VERSION_STABILITY_STABLE = "stable"
	VERSION_STABILITY_DEV    = "dev"
	VERSION_STABILITY_LATEST = "latest"

	// "commit" is not actually a stability, but it takes the place of one in
	// the repo version notation.  The "commit" string indicates a commit hash,
	// tag, or branch, rather than a version specifier.
	VERSION_STABILITY_COMMIT = "commit"
)

// Represents an unspecified part in a version.  For example, in "1-latest",
// the minor and revision parts are floating.
const VERSION_FLOATING = -1

type RepoVersion struct {
	Major     int64
	Minor     int64
	Revision  int64
	Stability string
	Commit    string
	Rc        bool
}

func (v *RepoVersion) IsNormalized() bool {
	return v.Stability == VERSION_STABILITY_NONE
}

func (v *RepoVersion) toComparable() RepoVersion {
	clone := *v

	// 0.0.0 means "latest develop"; it is greater than all over version
	// numbers.
	if v.Major == 0 && v.Minor == 0 && v.Revision == 0 {
		clone.Major = math.MaxInt64
		clone.Minor = math.MaxInt64
		clone.Revision = math.MaxInt64
	}

	return clone
}

func CompareRepoVersions(v1 RepoVersion, v2 RepoVersion) int {
	v1 = v1.toComparable()
	v2 = v2.toComparable()

	toInt := func(i64 int64) int {
		if i64 < 0 {
			return -1
		} else if i64 > 0 {
			return 1
		} else {
			return 0
		}
	}

	if r := v1.Major - v2.Major; r != 0 {
		return toInt(r)
	}

	if r := v1.Minor - v2.Minor; r != 0 {
		return toInt(r)
	}

	if r := v1.Revision - v2.Revision; r != 0 {
		return toInt(r)
	}

	return 0
}

func (ver *RepoVersion) String() string {
	if ver.Commit != "" {
		return ver.Commit
	}

	s := fmt.Sprintf("%d", ver.Major)
	if ver.Minor != VERSION_FLOATING {
		s += fmt.Sprintf(".%d", ver.Minor)
	}
	if ver.Revision != VERSION_FLOATING {
		s += fmt.Sprintf(".%d", ver.Revision)
	}

	if ver.Stability != VERSION_STABILITY_NONE {
		s += fmt.Sprintf("-%s", ver.Stability)
	}

	if ver.Rc {
		s += fmt.Sprintf(" (rc)")
	}

	return s
}

func (ver *RepoVersion) ToNuVersion() Version {
	return Version{
		Major:    ver.Major,
		Minor:    ver.Minor,
		Revision: ver.Revision,
	}
}

func ParseRepoVersion(verStr string) (RepoVersion, error) {
	var err error

	stability := VERSION_STABILITY_NONE
	base := verStr

	dashIdx := strings.LastIndex(verStr, "-")
	if dashIdx != -1 {
		stability = strings.TrimSpace(verStr[dashIdx+1:])
		base = strings.TrimSpace(verStr[:dashIdx])

		switch stability {
		case VERSION_STABILITY_COMMIT:
			return RepoVersion{Commit: strings.TrimSpace(base)}, nil

		case VERSION_STABILITY_STABLE:
		case VERSION_STABILITY_DEV:
		case VERSION_STABILITY_LATEST:

		default:
			return RepoVersion{}, util.FmtNewtError(
				"Unknown stability (%s) in version %s", stability, verStr)
		}
	}

	parts := strings.Split(base, ".")
	if len(parts) > 3 {
		return RepoVersion{},
			util.FmtNewtError("Invalid version string: \"%s\"; "+
				"must be fixed (X.X.X) or floating (X[.X]-stability)", verStr)
	}

	if len(parts) != 3 && stability == VERSION_STABILITY_NONE {
		return RepoVersion{},
			util.FmtNewtError("Invalid version string: \"%s\"; "+
				"must be fixed (X.X.X) or floating (X[.X]-stability)", verStr)
	}

	// Assume no parts of the version are specified.
	ver := RepoVersion{
		Major:     VERSION_FLOATING,
		Minor:     VERSION_FLOATING,
		Revision:  VERSION_FLOATING,
		Stability: stability,
	}

	// Convert each dot-delimited part to an integer.
	if ver.Major, err = strconv.ParseInt(parts[0], 10, 64); err != nil {
		return RepoVersion{}, util.NewNewtError(err.Error())
	}
	if len(parts) >= 2 {
		if ver.Minor, err = strconv.ParseInt(parts[1], 10, 64); err != nil {
			return RepoVersion{}, util.NewNewtError(err.Error())
		}
	}
	if len(parts) == 3 {
		if ver.Revision, err = strconv.ParseInt(parts[2], 10, 64); err != nil {
			return RepoVersion{}, util.NewNewtError(err.Error())
		}
	}

	return ver, nil
}

type verSorter struct {
	vers []RepoVersion
}

func (v verSorter) Len() int {
	return len(v.vers)
}
func (v verSorter) Swap(i, j int) {
	v.vers[i], v.vers[j] = v.vers[j], v.vers[i]
}
func (v verSorter) Less(i, j int) bool {
	a := v.vers[i]
	b := v.vers[j]

	return CompareRepoVersions(a, b) < 0
}

func SortVersions(vers []RepoVersion) {
	sorter := verSorter{
		vers: vers,
	}

	sort.Sort(sorter)
}

func SortedVersions(vers []RepoVersion) []RepoVersion {
	clone := make([]RepoVersion, len(vers))
	copy(clone, vers)

	SortVersions(clone)
	return clone
}

func SortedVersionsDesc(vers []RepoVersion) []RepoVersion {
	slice := SortedVersions(vers)
	size := len(slice)
	for i := 0; i < size/2; i++ {
		j := size - 1 - i
		slice[i], slice[j] = slice[j], slice[i]
	}

	return slice
}
