// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gerritfmt

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
)

// Formatter is a definition of a formatting engine
type Formatter interface {
	// Format returns the files but formatted. All files are
	// assumed to have the same language.
	Format(in []File, outSink io.Writer) (out []FormattedFile, err error)
}

// FormatterConfig defines the mapping configurable
type FormatterConfig struct {
	// Regex is the typical filename regexp to use
	Regex *regexp.Regexp

	// Query is used to filter inside Gerrit
	Query string

	// The formatter
	Formatter Formatter
}

// Formatters holds all the formatters supported
var Formatters = map[string]*FormatterConfig{
	"commitmsg": {
		Regex:     regexp.MustCompile(`^/COMMIT_MSG$`),
		Formatter: &commitMsgFormatter{},
	},
}

func init() {
	gjf, err := exec.LookPath("google-java-format")
	if err == nil {
		Formatters["java"] = &FormatterConfig{
			Regex: regexp.MustCompile(`\.java$`),
			Query: "ext:java",
			Formatter: &toolFormatter{
				bin:  "java",
				args: []string{"-jar", gjf, "-i"},
			},
		}
	}

	bzl, err := exec.LookPath("buildifier")
	if err == nil {
		Formatters["bzl"] = &FormatterConfig{
			Regex: regexp.MustCompile(`(\.bzl|/BUILD|^BUILD)$`),
			Query: "(ext:bzl OR file:BUILD OR file:WORKSPACE)",
			Formatter: &toolFormatter{
				bin:  bzl,
				args: []string{"-mode=fix"},
			},
		}
	}

	gofmt, err := exec.LookPath("gofmt")
	if err == nil {
		Formatters["go"] = &FormatterConfig{
			Regex: regexp.MustCompile(`\.go$`),
			Query: "ext:go",
			Formatter: &toolFormatter{
				bin:  gofmt,
				args: []string{"-w"},
			},
		}
	}
}

// IsSupported returns if the given language is supported.
func IsSupported(lang string) bool {
	_, ok := Formatters[lang]
	return ok
}

// SupportedLanguages returns a list of languages.
func SupportedLanguages() []string {
	var r []string
	for l := range Formatters {
		r = append(r, l)
	}
	sort.Strings(r)
	return r
}

func splitByLang(in []File) map[string][]File {
	res := map[string][]File{}
	for _, f := range in {
		res[f.Language] = append(res[f.Language], f)
	}
	return res
}

// Format formats all the files in the request for which a formatter exists.
func Format(req *FormatRequest, rep *FormatReply) error {
	for _, f := range req.Files {
		if f.Language == "" {
			return fmt.Errorf("file %q has empty language", f.Name)
		}
	}

	for language, fs := range splitByLang(req.Files) {
		var buf bytes.Buffer
		entry := Formatters[language]
		log.Println("init", Formatters)

		out, err := entry.Formatter.Format(fs, &buf)
		if err != nil {
			return err
		}

		if len(out) > 0 && out[0].Message == "" {
			out[0].Message = buf.String()
		}
		rep.Files = append(rep.Files, out...)
	}
	return nil
}

type commitMsgFormatter struct{}

func (f *commitMsgFormatter) Format(in []File, outSink io.Writer) (out []FormattedFile, err error) {
	complaint := checkCommitMessage(string(in[0].Content))
	ff := FormattedFile{}
	ff.Name = in[0].Name
	if complaint != "" {
		ff.Message = complaint
	} else {
		ff.Content = in[0].Content
	}
	out = append(out, ff)
	return out, nil
}

func checkCommitMessage(msg string) (complaint string) {
	lines := strings.Split(msg, "\n")
	if len(lines) < 2 {
		return "must have multiple lines"
	}

	if len(lines[1]) > 1 {
		return "subject and body must be separated by blank line"
	}

	if len(lines[0]) > 70 {
		return "subject must be less than 70 chars"
	}

	if strings.HasSuffix(lines[0], ".") {
		return "subject must not end in '.'"
	}

	return ""
}

type toolFormatter struct {
	bin  string
	args []string
}

func (f *toolFormatter) Format(in []File, outSink io.Writer) (out []FormattedFile, err error) {
	cmd := exec.Command(f.bin, f.args...)

	tmpDir, err := ioutil.TempDir("", "gerritfmt")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(tmpDir)

	for _, f := range in {
		dir, base := filepath.Split(f.Name)
		dir = filepath.Join(tmpDir, dir)
		if err := os.MkdirAll(dir, 0755); err != nil {
			return nil, err
		}

		if err := ioutil.WriteFile(filepath.Join(dir, base), f.Content, 0644); err != nil {
			return nil, err
		}

		cmd.Args = append(cmd.Args, f.Name)
	}
	cmd.Dir = tmpDir

	var errBuf, outBuf bytes.Buffer
	cmd.Stdout = &outBuf
	cmd.Stderr = &errBuf
	log.Println("running", cmd.Args, "in", tmpDir)
	if err := cmd.Run(); err != nil {
		log.Printf("error %v, stderr %s, stdout %s", err, errBuf.String(),
			outBuf.String())
		return nil, err
	}

	for _, f := range in {
		c, err := ioutil.ReadFile(filepath.Join(tmpDir, f.Name))
		if err != nil {
			return nil, err
		}

		out = append(out, FormattedFile{
			File: File{
				Name:    f.Name,
				Content: c,
			},
		})
	}

	return out, nil
}
