// 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 fmtserver

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

type Server struct {
	JavaJar       string
	Buildifier    string
	Gofmt         string
	languageRegex map[string]*regexp.Regexp
	formatterMap  map[string]formatterFunc
}

type formatterFunc func(in []File, out io.Writer) ([]FormattedFile, error)

func NewServer() *Server {
	type formatter struct {
		lang  string
		regex *regexp.Regexp
		fun   formatterFunc
	}

	s := &Server{
		languageRegex: map[string]*regexp.Regexp{},
		formatterMap:  map[string]formatterFunc{},
	}

	formatters := []formatter{
		{"java", regexp.MustCompile(`\.java$`), s.javaFormat},
		{"bazel", regexp.MustCompile(`(\.bzl|/BUILD|^BUILD)$`), s.bazelFormat},
		{"go", regexp.MustCompile(`\.go$`), s.goFormat},
		{"commit-msg", regexp.MustCompile(`^/COMMIT_MSG$`), s.commitCheck},
	}

	for _, l := range formatters {
		s.languageRegex[l.lang] = l.regex
	}
	for _, l := range formatters {
		s.formatterMap[l.lang] = l.fun
	}
	return s
}

func (s *Server) splitByLang(in []File) map[string][]File {
	res := map[string][]File{}
	for _, f := range in {
		for lang, regex := range s.languageRegex {
			if regex.MatchString(f.Name) {
				res[lang] = append(res[lang], f)
				break
			}
		}
	}
	return res
}

func (s *Server) Format(req *FormatRequest, rep *FormatReply) error {
	for lang, files := range s.splitByLang(req.Files) {
		var buf bytes.Buffer
		out, err := s.formatterMap[lang](files, &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
}

func (s *Server) commitCheck(in []File, outSink io.Writer) (out []FormattedFile, err error) {
	complaint := s.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 (s *Server) 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 ""
}

func (s *Server) javaFormat(in []File, outSink io.Writer) (out []FormattedFile, err error) {
	if _, err := os.Stat(s.JavaJar); err != nil {
		return nil, fmt.Errorf("Stat(%q): %v", s.JavaJar, err)
	}
	cmd := exec.Command(
		"java",
		"-jar",
		s.JavaJar,
		"-i",
	)
	return s.inlineFixTool(cmd, in, outSink)
}

func (s *Server) bazelFormat(in []File, outSink io.Writer) (out []FormattedFile, err error) {
	if _, err := os.Stat(s.Buildifier); err != nil {
		return nil, fmt.Errorf("Stat(%q): %v", s.Buildifier, err)
	}
	cmd := exec.Command(
		s.Buildifier,
		"-mode=fix",
	)
	return s.inlineFixTool(cmd, in, outSink)
}

func (s *Server) goFormat(in []File, outSink io.Writer) (out []FormattedFile, err error) {
	if _, err := os.Stat(s.Buildifier); err != nil {
		return nil, fmt.Errorf("Stat(%q): %v", s.Buildifier, err)
	}
	cmd := exec.Command(
		s.Gofmt,
		"-mode=fix",
	)
	return s.inlineFixTool(cmd, in, outSink)
}

func (s *Server) inlineFixTool(cmd *exec.Cmd, in []File, outSink io.Writer) (out []FormattedFile, err error) {
	tmpDir, err := ioutil.TempDir("", "fmtserver")
	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
	cmd.Stdout = outSink
	cmd.Stderr = outSink
	log.Println("running", cmd.Args, "in", tmpDir)
	if err := cmd.Run(); err != nil {
		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
}
