package fat32

import (
	"errors"
	"fmt"
	"math"
	"regexp"
	"strings"
)

// By default, DOS names would be encoded as what Microsoft calls the OEM
// code page. This is however dependant on the code page settings of the
// OS reading the file name as it's not mentioned in FAT32 metadata.
// To get maximum compatibility and make it easy to read in hex editors
// this only encodes ASCII characters and not any specific code page.
// This can still result in garbled data when using a non-latin code page,
// but this is unavoidable.
// This is legal as there is no specific requirements for generating these
// DOS names and any semi-modern system should use the unicode filenames
// anyways.

var invalidDOSNameChar = regexp.MustCompile("^[^A-Z0-9!#$%&'()@^_\x60{}~-]$")

// validDOSName matches names which are valid and unique DOS 8.3 file names as
// well as valid ASCII
var validDOSName = regexp.MustCompile(`^^([A-Z0-9!#$%&'()@^_\x60{}~-]{0,8})(\.[A-Z0-9!#$%&'()-@^_\x60{}~-]{1,3})?$`)

func makeUniqueDOSNames(inodes []*Inode) error {
	taken := make(map[[11]byte]bool)
	var lossyNameInodes []*Inode
	// Make two passes to ensure that names can always be passed through even
	// if they would conflict with a generated name.
	for _, i := range inodes {
		for j := range i.dosName {
			i.dosName[j] = ' '
		}
		nameUpper := strings.ToUpper(i.Name)
		dosParts := validDOSName.FindStringSubmatch(nameUpper)
		if dosParts != nil {
			// Name is pass-through
			copy(i.dosName[:8], dosParts[1])
			if len(dosParts[2]) > 0 {
				// Skip the dot, it is implicit
				copy(i.dosName[8:], dosParts[2][1:])
			}
			if taken[i.dosName] {
				// Mapping is unique, complain about the actual file name, not
				// the 8.3 one
				return fmt.Errorf("name %q occurs more than once in the same directory", i.Name)
			}
			taken[i.dosName] = true
			continue
		}
		lossyNameInodes = append(lossyNameInodes, i)
	}
	// Willfully ignore the recommended short name generation algorithm as it
	// requires tons of bookkeeping and doesn't result in stable names so
	// cannot be relied on anyway.
	// A FAT32 directory is limited to 2^16 entries (in practice less than half
	// of that because of long file name entries), so 4 hex characters
	// guarantee uniqueness, regardless of the rest of name.
	var nameIdx int
	for _, i := range lossyNameInodes {
		nameUpper := strings.ToUpper(i.Name)
		dotParts := strings.Split(nameUpper, ".")
		for j := range dotParts {
			// Remove all invalid chars
			dotParts[j] = invalidDOSNameChar.ReplaceAllString(dotParts[j], "")
		}
		var fileName string
		lastDotPart := dotParts[len(dotParts)-1]
		if len(dotParts) > 1 && len(dotParts[0]) > 0 && len(lastDotPart) > 0 {
			// We have a valid 8.3 extension
			copy(i.dosName[8:], lastDotPart)
			fileName = strings.Join(dotParts[:len(dotParts)-1], "")
		} else {
			fileName = strings.Join(dotParts[:], "")
		}
		copy(i.dosName[:4], fileName)

		for {
			copy(i.dosName[4:], fmt.Sprintf("%04X", nameIdx))
			nameIdx++
			if nameIdx >= math.MaxUint16 {
				return errors.New("invariant violated: unable to find unique name with 16 bit counter in 16 bit space")
			}
			if !taken[i.dosName] {
				break
			}
		}
	}
	return nil
}
