package paths

import (
	"strconv"
	"strings"
)

// RootPath is the canonical path which represents the root of a
// transaction.
var RootPath = make([]uint32, 0)

// PathMatches returns true if p1 and p2 represent the same path
func PathMatches(p1, p2 []uint32) bool {
	if len(p1) != len(p2) {
		return false
	}
	for i, val1 := range p1 {
		if p2[i] != val1 {
			return false
		}
	}
	return true
}

// Find the minimum of the two paths' lengths.
func minLength(p1, p2 []uint32) int {
	var pathlength int
	if len(p1) < len(p2) {
		pathlength = len(p1)
	} else {
		pathlength = len(p2)
	}
	return pathlength
}

// IsChildPath returns true if p1 is a child of p2
func IsChildPath(p1, p2 []uint32) bool {
	if len(p1) <= len(p2) {
		return false
	}
	return PathMatches(p1[:len(p2)], p2)
}

// returns -1 if p1 is a prior path to p2, 1 if it is later, and 0 if
// they are the same
func PathCompare(p1, p2 []uint32) int {
	// compare the common prefix of the two paths - if a path has a
	// lower value in the common prefix, it comes first
	prefixLen := minLength(p1, p2)
	for idx := 0; idx < prefixLen; idx++ {
		if p1[idx] < p2[idx] {
			return -1
		} else if p1[idx] > p2[idx] {
			return 1
		}
	}

	// else, shallowest path is before
	if len(p1) < len(p2) {
		return -1
	} else if len(p2) < len(p1) {
		return 1
	}
	return 0
}

// PathToString returns a string version of the path: dot-delimited
// base10 integers.
func PathToString(p []uint32) string {
	parts := make([]string, len(p))
	for i, part := range p {
		parts[i] = strconv.Itoa(int(part))
	}
	return strings.Join(parts, ".")
}
