func (v *visualizer) uniqueExternalUIName(dir string, others map[string]string) string {
	base := filepath.Base(dir)
	if base == "assets" {
		base = filepath.Base(filepath.Dir(dir))
	}
	cnt := 0
	name := base
	for {
		if cnt > 0 {
			name = base + fmt.Sprintf("-%d", cnt)
		}
		if _, ok := others[name]; !ok {
			return name
		}
		cnt++
	}
}
uniqueExternalUIName generates a unique name for the external visualizer.
package visualizer
import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"strings"
	xhttp "github.com/intel/cri-resource-manager/pkg/instrumentation/http"
	logger "github.com/intel/cri-resource-manager/pkg/log"
)
const (
	visualizerPrefix = "/ui"
)
var log = logger.NewLogger("visualizer")
type visualizer struct {
	builtin map[string]http.FileSystem
}
var visualizers = &visualizer{
	builtin: map[string]http.FileSystem{},
}
func Register(name string, dir http.FileSystem) {
	visualizers.register(name, dir)
}
func Setup(mux *xhttp.ServeMux) error {
	log.Info("activating visualization interface...")
	mux.Handle("/", http.RedirectHandler("/ui/index.html", http.StatusFound))
	mux.Handle("/ui", http.RedirectHandler("/ui/index.html", http.StatusFound))
	mux.Handle("/ui/builtin/", http.FileServer(visualizers))
	mux.Handle("/ui/external/", http.FileServer(visualizers))
	mux.HandleFunc("/ui/index.html", visualizers.generateIndexHTML)
	return nil
}
func (v *visualizer) Open(path string) (http.File, error) {
	log.Debug("HTTP request %q", path)
	relative, err := filepath.Rel(visualizerPrefix+"/", path)
	if err != nil {
		return nil, visualizerError("failed to resolve path %q: %v", err)
	}
	log.Debug("%s => %s", path, relative)
	split := strings.Split(relative, "/")
	if len(split) < 2 {
		return nil, visualizerError("failed to resolve relative path %q", relative)
	}
	kind, name := split[0], split[1]
	fs, err := v.getVisualizerFileSystem(kind, name)
	if err != nil {
		return nil, err
	}
	return fs.Open(filepath.Join(split[2:]...))
}
func (v *visualizer) getVisualizerFileSystem(kind, name string) (http.FileSystem, error) {
	switch kind {
	case "builtin":
		if dir, ok := v.builtin[name]; ok {
			return dir, nil
		}
		return nil, visualizerError("unknown builtin visualization UI %q", name)
	case "external":
		external := v.discoverExternalUIs()
		if path, ok := external[name]; ok {
			return http.FileSystem(http.Dir(path)), nil
		}
		return nil, visualizerError("unkown external visualization UI %q", name)
	}
	return nil, visualizerError("unknown visualization UI type %q", kind)
}
const (
	uiPageHTMLHeader = `
<html>
  <head>
    <title>CRI Resource Manager - Workload Placement Visualization</title>
  </head>
  <body>
    <ul>
`
	uiPageHTMLFooter = `
    </ul>
  </body>
</html>
`
)
func (v *visualizer) generateIndexHTML(w http.ResponseWriter, req *http.Request) {
	builtinUIs := []string{}
	for name := range v.builtin {
		builtinUIs = append(builtinUIs, name)
	}
	sort.Strings(builtinUIs)
	externalUIs := []string{}
	for name := range v.discoverExternalUIs() {
		externalUIs = append(externalUIs, name)
	}
	sort.Strings(externalUIs)
	fmt.Fprintf(w, "%s", uiPageHTMLHeader)
	if len(builtinUIs)+len(externalUIs) == 0 {
		fmt.Fprintf(w, "No builtin or external visualization UIs found.")
	} else {
		for _, name := range builtinUIs {
			fmt.Fprintf(w, "<li><a href=\"/ui/builtin/%s\">%s</a>\n", name, name)
		}
		for _, name := range externalUIs {
			fmt.Fprintf(w, "<li><a href=\"/ui/external/%s\">external %s</a>\n", name, name)
		}
	}
	fmt.Fprintf(w, "%s\r\n", uiPageHTMLFooter)
}
func (v *visualizer) register(name string, dir http.FileSystem) {
	if _, ok := v.builtin[name]; ok {
		log.Error("builtin visualizer '%s' already registered", name)
		return
	}
	v.builtin[name] = dir
	log.Info("registered %s builtin visualizer...", name)
}
func (v *visualizer) discoverExternalUIs() map[string]string {
	external := make(map[string]string)
	for _, root := range strings.Split(externalDirs, ",") {
		filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
			if err != nil || info.IsDir() || info.Name() != "index.html" {
				return nil
			}
			dir, err := filepath.Abs(filepath.Dir(path))
			if err != nil {
				log.Error("failed to determine absolute directory for '%s': %v", path, err)
				return nil
			}
			name := v.uniqueExternalUIName(dir, external)
			external[name] = dir
			log.Debug("found external visualizer '%s' (%s)", name, dir)
			return nil
		})
	}
	return external
}