package gen

import (
	"bytes"
	"io"
	"log"

	"text/template"

	"github.com/clipperhouse/typewriter"
)

func init() {
	registerLiveWriter("migrationproducer", "producer_",
		producerConstructor,
		producerStruct,
		producerPreCall,
		producerPostCall,
		producerMethodComment,
		"code.justin.tv/d8a/migration",
		"time",
		"golang.org/x/net/context")

	registerLiveWriter("migrationsecondary", "secondary_",
		secondaryConstructor,
		secondaryStruct,
		secondaryPreCall,
		secondaryPostCall,
		secondaryMethodComment,
		"code.justin.tv/d8a/migration",
		"code.justin.tv/d8a/migration/comparison",
		"golang.org/x/net/context")
}

func registerLiveWriter(writerName string, typePrefix string, constructorTemplate string, structTemplate string, preCallTemplate string, postCallTemplate string, methodCommentTemplate string, imports ...string) {
	template := typewriter.Template{
		Name: "root",
		Text: `{{define "constructor"}}` + constructorTemplate + `{{end}}
		{{define "struct"}}` + structTemplate + `{{end}}
		{{define "preCall"}}` + preCallTemplate + `{{end}}
		{{define "postCall"}}` + postCallTemplate + `{{end}}
		{{define "methodComment"}}` + methodCommentTemplate + `{{end}}` +
			rootTemplate,
		FuncMap: map[string]interface{}{
			"method": func(interfaceName string, backendName string, method methodModel) map[string]interface{} {
				return map[string]interface{}{
					"InterfaceName":   interfaceName,
					"Method":          method,
					"BackendTypeName": backendName,
				}
			},
			"add": func(left int, right int) int {
				return left + right
			},
		},
	}

	convertedImports := []typewriter.ImportSpec{}

	for _, imprt := range imports {
		convertedImports = append(convertedImports, typewriter.ImportSpec{Path: imprt})
	}

	parsedTemplate, err := template.Parse()
	if err != nil {
		log.Fatalln(err)
	}

	err = typewriter.Register(&wrapperWriter{
		writerName: writerName,
		typePrefix: typePrefix,
		imports:    convertedImports,
		template:   parsedTemplate,
	})
	if err != nil {
		log.Fatalln(err)
	}
}

type wrapperWriter struct {
	writerName string
	typePrefix string
	imports    []typewriter.ImportSpec
	template   *template.Template
}

func (self *wrapperWriter) Name() string {
	return self.writerName
}

func (self *wrapperWriter) Imports(t typewriter.Type) []typewriter.ImportSpec {
	return self.imports
}

func (self *wrapperWriter) Write(writer io.Writer, t typewriter.Type) error {
	if _, shouldWrite := t.FindTag(self); !shouldWrite {
		return nil
	}

	templModel, err := buildModel(t, self, self.typePrefix)
	if err != nil {
		return err
	}

	buf := bytes.NewBuffer([]byte{})

	err = self.template.Execute(buf, templModel)
	if err != nil {
		return err
	}

	//log.Println(string(buf.Bytes()))
	buf.WriteTo(writer)

	return nil
}
