package store

import (
	"bytes"
	"encoding/json"
	"html/template"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/gobuffalo/packr/v2/jam/parser"
)

var _ Store = &Legacy{}

type Legacy struct {
	*Disk
	boxes map[string][]legacyBox
}

func NewLegacy() *Legacy {
	return &Legacy{
		Disk:  NewDisk("", ""),
		boxes: map[string][]legacyBox{},
	}
}

func (l *Legacy) Pack(box *parser.Box) error {
	files, err := l.Files(box)
	if err != nil {
		return err
	}

	var fcs []legacyFile

	for _, f := range files {
		n := strings.TrimPrefix(f.Name(), box.AbsPath+string(filepath.Separator))
		c, err := l.prepFile(f)
		if err != nil {
			return err
		}
		fcs = append(fcs, legacyFile{Name: n, Contents: c})
	}

	sort.Slice(fcs, func(a, b int) bool {
		return fcs[a].Name < fcs[b].Name
	})

	lbs := l.boxes[box.PackageDir]
	lbs = append(lbs, legacyBox{
		Box:   box,
		Files: fcs,
	})
	l.boxes[box.PackageDir] = lbs
	return nil
}

func (l *Legacy) prepFile(r io.Reader) (string, error) {
	bb := &bytes.Buffer{}
	if _, err := io.Copy(bb, r); err != nil {
		return "", err
	}
	b, err := json.Marshal(bb.Bytes())
	if err != nil {
		return "", err
	}
	return strings.Replace(string(b), "\"", "\\\"", -1), nil
}

// Close ...
func (l *Legacy) Close() error {
	for _, b := range l.boxes {
		if len(b) == 0 {
			continue
		}
		bx := b[0].Box
		pkg := bx.Package
		opts := map[string]interface{}{
			"Package": pkg,
			"Boxes":   b,
		}
		p := filepath.Join(bx.PackageDir, "a_"+bx.Package+"-packr.go.tmpl")
		tmpl, err := template.New(p).Parse(legacyTmpl)

		if err != nil {
			return err
		}

		f, err := os.Create(p)
		if err != nil {
			return err
		}

		if err := tmpl.Execute(f, opts); err != nil {
			return err
		}

	}
	return nil
}

type legacyBox struct {
	Box   *parser.Box
	Files []legacyFile
}

type legacyFile struct {
	Name     string
	Contents string
}

var legacyTmpl = `// Code generated by github.com/gobuffalo/packr. DO NOT EDIT.

package {{.Package}}

import "github.com/gobuffalo/packr"

// You can use the "packr clean" command to clean up this,
// and any other packr generated files.
func init() {
	{{- range $box := .Boxes }}
	{{- range $box.Files }}
	_ = packr.PackJSONBytes("{{$box.Box.Name}}", "{{.Name}}", "{{.Contents}}")
	{{- end }}
	{{- end }}
}
`
