// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package gndoc

import (
	"fmt"
	"io"
	"sort"
	"strings"
)

type ArgMap struct {
	argLookup map[string][]string // map of arg names to keys for lookup
	args      map[string][]Arg    // map of key names to relevant args
}

// NewArgMap returns a pointer to an
func NewArgMap() *ArgMap {
	return &ArgMap{
		argLookup: make(map[string][]string),
		args:      make(map[string][]Arg),
	}
}

// AddArgs creates args from GNArgs and adds them to the maps
func (a *ArgMap) AddArgs(gnArgs <-chan Arg) {
	for gnArg := range gnArgs {
		a.AddArg(gnArg)
	}
}

// AddArg adds Arg to the maps
func (a *ArgMap) AddArg(gnArg Arg) {
	a.args[gnArg.Key] = append(a.args[gnArg.Key], gnArg)
	a.argLookup[gnArg.Name] = append(a.argLookup[gnArg.Name], gnArg.Key)
}

// EmitMarkdown emits Markdown text for the map of arguments.
func (a *ArgMap) EmitMarkdown(out io.Writer) {
	type mappedArgs struct {
		m map[string][]Arg
		k []string
	}
	sortedArgs := struct {
		m map[string]*mappedArgs
		k []string
	}{
		m: make(map[string]*mappedArgs),
		k: make([]string, 0),
	}

	numKeys := len(a.args)
	for _, gnArgs := range a.args {
		for _, gnArg := range gnArgs {
			// Lookup the keys associated with this arg & sort & stringify.
			keys, _ := a.argLookup[gnArg.Name]
			if len(keys) == numKeys {
				// Incoming keys will always have an `=`, and so  this is an
				// okay value.
				keys = []string{"all"}
			}
			sort.Strings(keys)
			key := strings.Join(keys, ", ")
			if _, ok := sortedArgs.m[key]; !ok {
				sortedArgs.m[key] = &mappedArgs{
					m: make(map[string][]Arg),
					k: make([]string, 0)}
			}
			sortedArgs.m[key].m[gnArg.Name] = append(sortedArgs.m[key].m[gnArg.Name], gnArg)
		}
	}
	for k := range sortedArgs.m {
		for argName := range sortedArgs.m[k].m {
			sort.Slice(sortedArgs.m[k].m[argName], func(i, j int) bool {
				return sortedArgs.m[k].m[argName][i].Key < sortedArgs.m[k].m[argName][j].Key
			})
			sortedArgs.m[k].k = append(sortedArgs.m[k].k, argName)
		}
		sort.Strings(sortedArgs.m[k].k)
		sortedArgs.k = append(sortedArgs.k, k)
	}
	sort.Strings(sortedArgs.k)
	// Emit a header.
	fmt.Fprintf(out, "# %s\n\n", pageTitle)
	for _, name := range sortedArgs.k {
		if name == "all" {
			fmt.Fprintf(out, "## All builds\n\n")
		} else {
			fmt.Fprintf(out, "## `%s`\n\n", name)
		}
		for _, argsKey := range sortedArgs.m[name].k {
			gnArgs := sortedArgs.m[name].m[argsKey]
			writeArgs(gnArgs, out)
		}
	}
}
