// genconfig generates boilerplate configuration/registration code.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var (
	output = flag.String("o", "", "output file. Must be set")
)

const tmpl = `// DO NOT EDIT: This file was auto-generated by "go generate"
// To regenerate run:
//   go install github.com/coreos/dex/cmd/genconfig
//   go generate <<fully qualified package name>>

package __PKG__

import (
	"encoding/json"
	"errors"
	"fmt"
)

type New__OBJ__ConfigFunc func() __OBJ__Config

var (
	__obj__Types map[string]New__OBJ__ConfigFunc
)

func Register__OBJ__ConfigType(__obj__Type string, fn New__OBJ__ConfigFunc) {
	if __obj__Types == nil {
		__obj__Types = make(map[string]New__OBJ__ConfigFunc)
	}

	if _, ok := __obj__Types[__obj__Type]; ok {
		panic(fmt.Sprintf("__obj__ config type %q already registered", __obj__Type))
	}

	__obj__Types[__obj__Type] = fn
}

func New__OBJ__ConfigFromType(__obj__Type string) (__OBJ__Config, error) {
	fn, ok := __obj__Types[__obj__Type]
	if !ok {
		return nil, fmt.Errorf("unrecognized __obj__ config type %q", __obj__Type)
	}

	return fn(), nil
}

func new__OBJ__ConfigFromMap(m map[string]interface{}) (__OBJ__Config, error) {
	ityp, ok := m["type"]
	if !ok {
		return nil, errors.New("__obj__ config type not set")
	}
	typ, ok := ityp.(string)
	if !ok {
		return nil, errors.New("__obj__ config type not string")
	}
	cfg, err := New__OBJ__ConfigFromType(typ)
	if err != nil {
		return nil, err
	}
	b, err := json.Marshal(m)
	if err != nil {
		return nil, err
	}
	if err = json.Unmarshal(b, cfg); err != nil {
		return nil, err
	}
	return cfg, nil
}
`

// Usage is a replacement usage function for the flags package.
func Usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\tgenconfig  -o OutputFile PackageName ObjToConfigure \n")
	fmt.Fprintf(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
}

func main() {
	flag.Parse()
	flag.Usage = Usage
	args := flag.Args()
	if *output == "" || len(args) != 2 {
		flag.Usage()
		os.Exit(2)
	}

	pkg := args[0]
	objType := args[1]
	objTypeLower := strings.ToLower(objType[0:1]) + objType[1:]

	src := strings.Replace(tmpl, "__OBJ__", objType, -1)
	src = strings.Replace(src, "__obj__", objTypeLower, -1)
	src = strings.Replace(src, "__PKG__", pkg, -1)

	err := ioutil.WriteFile(*output, []byte(src), 0644)
	if err != nil {
		log.Fatalf("writing output: %s", err)
	}
}
