// Copyright 2020 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 checklicenses

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"io/ioutil"
	"sort"
	"strings"
	"text/template"

	"go.fuchsia.dev/fuchsia/tools/check-licenses/templates"
)

// saveToOutputFile writes to output the serialized licenses.
//
// It writes an uncompressed version too if a compressed version is requested.
func saveToOutputFile(path string, licenses *Licenses) error {
	// Sort the licenses in alphabetical order for consistency.
	sort.Slice(licenses.licenses, func(i, j int) bool { return licenses.licenses[i].Category < licenses.licenses[j].Category })
	data := struct {
		Used   []*License
		Unused []*License
	}{}
	for _, l := range licenses.licenses {
		if len(l.matches) == 0 {
			data.Unused = append(data.Unused, l)
		} else {
			data.Used = append(data.Used, l)
		}
	}

	templateStr := ""
	switch {
	case strings.HasSuffix(path, ".txt"):
		templateStr = templates.TemplateTxt
	case strings.HasSuffix(path, ".html") || strings.HasSuffix(path, ".html.gz"):
		// TODO(omerlevran): Use html/template instead of text/template.
		// text/template is inherently unsafe to generate HTML.
		templateStr = templates.TemplateHtml
	case strings.HasSuffix(path, ".json"):
		// TODO(omerlevran): Use encoding/json instead of hand-rolling out json.
		templateStr = templates.TemplateJson
	default:
		return fmt.Errorf("no template found for %s", path)
	}
	buf := bytes.Buffer{}
	tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(templateStr))
	if err := tmpl.Execute(&buf, data); err != nil {
		return err
	}

	// Special handling for compressed file.
	const gz = ".gz"
	if strings.HasSuffix(path, gz) {
		// First write uncompressed, then compressed.
		if err := ioutil.WriteFile(path[:len(path)-len(gz)], buf.Bytes(), 0666); err != nil {
			return err
		}
		d, err := compressGZ(buf.Bytes())
		if err != nil {
			return err
		}
		return ioutil.WriteFile(path, d, 0666)
	}

	return ioutil.WriteFile(path, buf.Bytes(), 0666)
}

// compressGZ returns the compressed buffer with gzip format.
func compressGZ(d []byte) ([]byte, error) {
	buf := bytes.Buffer{}
	zw := gzip.NewWriter(&buf)
	if _, err := zw.Write(d); err != nil {
		return nil, err
	}
	if err := zw.Close(); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

var funcMap = template.FuncMap{
	"getPattern": func(l *License) string {
		return l.pattern.String()
	},
	"getText": func(l *License, author string) string {
		return l.matches[author].value
	},
	"getHTMLText": func(l *License, author string) string {
		return strings.Replace(l.matches[author].value, "\n", "<br />", -1)
	},
	"getEscapedText": func(l *License, author string) string {
		return strings.Replace(l.matches[author].value, "\"", "\\\"", -1)
	},
	"getCategory": func(l *License) string {
		return strings.TrimSuffix(l.Category, ".lic")
	},
	"getFiles": func(l *License, author string) []string {
		var files []string
		for _, file := range l.matches[author].files {
			files = append(files, file)
		}
		sort.Strings(files)
		return files
	},
	"getAuthors": func(l *License) []string {
		var authors []string
		for author := range l.matches {
			authors = append(authors, author)
		}
		sort.Strings(authors)
		return authors
	},
}
