// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// +build ignore

package main

import (
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"text/template"
	"time"

	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/css"
	"github.com/tdewolff/minify/js"
)

const tpl = `// Code generated by go generate; DO NOT EDIT.
// {{ .Timestamp }}

package {{ .Package }}

var {{ .Map }} = map[string]string{
{{ range $constant, $content := .Files }}` + "\t" + `"{{ $constant }}": ` + "`{{ $content }}`" + `,
{{ end }}}

var {{ .Map }}Checksums = map[string]string{
{{ range $constant, $content := .Checksums }}` + "\t" + `"{{ $constant }}": "{{ $content }}",
{{ end }}}
`

var generatedTpl = template.Must(template.New("").Parse(tpl))

type GeneratedFile struct {
	Package, Map string
	Timestamp    time.Time
	Files        map[string]string
	Checksums    map[string]string
}

func normalizeBasename(filename string) string {
	filename = strings.TrimSuffix(filename, filepath.Ext(filename))
	return strings.Replace(filename, " ", "_", -1)
}

func generateFile(serializer, pkg, mapName, pattern, output string) {
	generatedFile := &GeneratedFile{
		Package:   pkg,
		Map:       mapName,
		Timestamp: time.Now(),
		Files:     make(map[string]string),
		Checksums: make(map[string]string),
	}

	files, _ := filepath.Glob(pattern)
	for _, file := range files {
		basename := path.Base(file)
		content, err := ioutil.ReadFile(file)
		if err != nil {
			panic(err)
		}

		switch serializer {
		case "css":
			m := minify.New()
			m.AddFunc("text/css", css.Minify)
			content, err = m.Bytes("text/css", content)
			if err != nil {
				panic(err)
			}

			basename = normalizeBasename(basename)
			generatedFile.Files[basename] = string(content)
		case "js":
			m := minify.New()
			m.AddFunc("text/javascript", js.Minify)
			content, err = m.Bytes("text/javascript", content)
			if err != nil {
				panic(err)
			}

			basename = normalizeBasename(basename)
			generatedFile.Files[basename] = string(content)
		case "base64":
			encodedContent := base64.StdEncoding.EncodeToString(content)
			generatedFile.Files[basename] = encodedContent
		default:
			basename = normalizeBasename(basename)
			generatedFile.Files[basename] = string(content)
		}

		generatedFile.Checksums[basename] = fmt.Sprintf("%x", sha256.Sum256(content))
	}

	f, err := os.Create(output)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	generatedTpl.Execute(f, generatedFile)
}

func main() {
	generateFile("none", "sql", "SqlMap", "sql/*.sql", "sql/sql.go")
	generateFile("base64", "static", "Binaries", "server/static/bin/*", "server/static/bin.go")
	generateFile("css", "static", "Stylesheets", "server/static/css/*.css", "server/static/css.go")
	generateFile("js", "static", "Javascript", "server/static/js/*.js", "server/static/js.go")
	generateFile("none", "template", "templateViewsMap", "server/template/html/*.html", "server/template/views.go")
	generateFile("none", "template", "templateCommonMap", "server/template/html/common/*.html", "server/template/common.go")
	generateFile("none", "locale", "Translations", "locale/translations/*.json", "locale/translations.go")
}
