/*
Copyright 2013 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 lint provides helper methods for quickly running lint checks
// against a proposed change on Gerrit.
package lint

import (
	"errors"
	"fmt"
	"log"
	"strings"

	"gwt.googlesource.com/buildglue.git/checkstyle"
	"gwt.googlesource.com/buildglue.git/gerrit"
	"gwt.googlesource.com/buildglue.git/git"
)

// Errors that can be returned by Lint.
var (
	LintFailed = errors.New("commit failed lint checking")
)

// Should be kept in sync with GWT's build.xml files.
var checks = []struct {
	config   string
	includes []string
	excludes []string
}{
	{
		config: "eclipse/settings/code-style/gwt-checkstyle.xml",
		includes: []string{
			"dev/core/src/",
			"dev/core/super/com/google/gwt/dev/jjs/intrinsic/",
			"user/src/",
			"user/super/com/google/gwt/emul/",
			"user/super/com/google/gwt/junit/translatable/",
		},
		excludes: []string{
			"dev/core/src/com/google/gwt/dev/shell/remoteui/RemoteMessageProto.java",
			"dev/core/src/com/google/gwt/dev/asm/",
			"dev/core/src/com/google/gwt/dev/js/rhino/",
			"dev/core/src/org/eclipse/",
			"dev/core/src/org/apache/",
			"user/src/javax/validation/",
			"user/src/org/hibernate/validator/",
		},
	},
	{
		config: "eclipse/settings/code-style/gwt-checkstyle-tests.xml",
		includes: []string{
			"user/test/com/google/",
			"user/test/test/",
		},
	},
}

// Match returns true if file is a ".java" file that starts with a string
// from includes but does not start with any strings from excludes.
func match(file string, includes, excludes []string) bool {
	if !strings.HasSuffix(file, ".java") {
		return false
	}
	for _, exclude := range excludes {
		if strings.HasPrefix(file, exclude) {
			return false
		}
	}
	for _, include := range includes {
		if strings.HasPrefix(file, include) {
			return true
		}
	}
	return false
}

// Matches returns the sublist of files that match the provided includes
// and excludes rules.
func matches(files, includes, excludes []string) []string {
	res := []string{}
	for _, file := range files {
		if match(file, includes, excludes) {
			res = append(res, file)
		}
	}
	return res
}

type linter struct {
	rev      string
	comments map[string][]gerrit.Comment
	failed   bool
}

func newLinter(rev string) *linter {
	return &linter{
		rev:      rev,
		comments: make(map[string][]gerrit.Comment),
	}
}

func (l *linter) comment(file string, line int, severity, message string) {
	comment := gerrit.Comment{Line: line, Message: fmt.Sprintf("[%s] %s", severity, message)}
	l.comments[file] = append(l.comments[file], comment)
	if severity == "error" {
		l.failed = true
	}
}

func (l *linter) checkStyle(config string, files []string) error {
	out, err := checkstyle.Run(config, files)
	if err != nil {
		log.Println("running checkstyle failed:", err)
		return err
	}
	for _, file := range out {
		if len(file.Errors) == 0 {
			continue
		}
		blameable, err := git.Blame(l.rev, file.Name)
		if err != nil {
			return err
		}
		for _, err := range file.Errors {
			if blameable[err.Line] {
				l.comment(file.Name, err.Line, err.Severity, err.Message)
			}
		}
	}
	return nil
}

func (l *linter) checkMessage(commitmsg []string) {
	warn := func(line int, message string) {
		// Gerrit includes some extra header lines before the commit message.
		// TODO(mdempsky): Is it always exactly six lines?
		l.comment("/COMMIT_MSG", line+6, "warning", message)
	}

	if len(commitmsg) >= 1 && len(commitmsg[0]) > 50 {
		warn(1, "Subject line should be 50 characters or fewer.")
	}
	if len(commitmsg) >= 3 && len(commitmsg[1]) > 0 {
		warn(2, "Subject line and body should be separated by a blank line.")
	}
	for i, line := range commitmsg {
		if i >= 2 && len(line) > 72 {
			warn(i+1, "Commit message lines should be 72 characters or fewer.")
			break
		}
	}
}

func (l *linter) review() gerrit.Review {
	res := gerrit.Review{}
	if l.failed {
		res.Message = ("Oops, this change failed the fast style check! " +
			"Please fix all errors and try again.")
		res.Labels = &gerrit.Labels{Verified: -1}
	} else if len(l.comments) != 0 {
		res.Message = ("This change passed the fast style check, " +
			"but still triggered some non-error warnings. " +
			"Please review and fix if appropriate.")
	} else {
		res.Message = ("Woo hoo, this change passed the fast style check " +
			"with ZERO new warnings! You rock!")
	}
	if len(l.comments) != 0 {
		res.Comments = l.comments
	}
	return res
}

// Lint fetches ref from Gerrit, inspects the commit message and runs checkstyle against
// any added or modified files, and posts a review to Gerrit with the results.
// Returns a LintFailed error if any lint errors were found.
func Lint(ref string) error {
	if err := git.Run("fetch", "https://gwt.googlesource.com/gwt", ref); err != nil {
		log.Println("fetch failed:", err)
		return err
	}
	rev, err := git.Line("rev-parse", "FETCH_HEAD")
	if err != nil {
		return err
	}
	if err = git.Run("checkout", rev); err != nil {
		return err
	}
	files, err := git.Lines("diff-tree", "-r", "--name-only", "--diff-filter=AM", rev+"^", rev)
	if err != nil {
		return err
	}

	log.Println("running lint checks")

	linter := newLinter(rev)
	for _, check := range checks {
		if err := linter.checkStyle(check.config, matches(files, check.includes, check.excludes)); err != nil {
			log.Println("checkstyle error:", err)
			return err
		}
	}

	commitmsg, err := git.Lines("show", "-s", "--pretty=format:%B", rev)
	if err != nil {
		return err
	}
	linter.checkMessage(commitmsg)

	if err = gerrit.Post(ref, linter.review()); err != nil {
		return err
	}

	if linter.failed {
		return LintFailed
	}
	return nil
}
