package emit

import (
	
	
	
	
)

// qualifier renders go/types types and symbols as Go source, deciding what is
// unqualified (the destination package) and what is imported and qualified.
//
// It runs in two modes. In recording mode (built with newRecording) it captures
// every package a render would reference, so the import block and aliases can be
// computed; the strings it returns in that mode are throwaway. In final mode
// (built with newFinal) it returns the chosen qualifier for each package.
type qualifier struct {
	destPath string
	record   map[string]*types.Package // path → package (recording mode)
	alias    map[string]string         // path → chosen qualifier (final mode)
}

// newRecording returns a qualifier that records every package referenced when
// rendering, for computing the import block.
func ( string) *qualifier {
	return &qualifier{destPath: , record: map[string]*types.Package{}}
}

// newFinal returns a qualifier that renders with the chosen per-package alias.
func ( string,  map[string]string) *qualifier {
	return &qualifier{destPath: , alias: }
}

// qualify is the go/types.Qualifier used with types.TypeString.
func ( *qualifier) ( *types.Package) string {
	if  == nil || .Path() == .destPath {
		return ""
	}
	if .record != nil {
		.record[.Path()] = 
	}
	if .alias != nil {
		// Every foreign package the render reaches must have been recorded by the
		// earlier import pass; a miss means that pass and this one drifted, which
		// would silently emit an unqualified, unimported name. Fail loud instead.
		,  := .alias[.Path()]
		if ! {
			panic(fmt.Sprintf("plumb: package %q referenced by the render but not recorded for import", .Path()))
		}
		return 
	}
	return .Name()
}

// typeString renders t as Go source under this qualifier.
func ( *qualifier) ( types.Type) string {
	return types.TypeString(, .qualify)
}

// recordedPackages returns the recorded packages sorted by import path.
func ( *qualifier) () []*types.Package {
	 := make([]*types.Package, 0, len(.record))
	for ,  := range .record {
		 = append(, )
	}
	slices.SortFunc(, func(,  *types.Package) int { return strings.Compare(.Path(), .Path()) })
	return 
}

// aliasNames returns the chosen import qualifiers (final mode), so a caller can
// reserve them as taken identifiers when allocating local names.
func ( *qualifier) () []string {
	 := make([]string, 0, len(.alias))
	for ,  := range .alias {
		 = append(, )
	}
	return 
}

// objQual renders a package-level object reference (function, variable,
// constant), qualified if it lives outside the destination.
func ( *qualifier) ( types.Object) string {
	 := .qualify(.Pkg())
	if  == "" {
		return .Name()
	}
	return  + "." + .Name()
}