// Copyright (c) 2017, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

package main

import (
	"bytes"
	"fmt"
	"os"
	"strings"
)

// convert_comments.go converts C-style block comments to C++-style line
// comments. A block comment is converted if all of the following are true:
//
//   * The comment begins after the first blank line, to leave the license
//     blocks alone.
//
//   * There are no characters between the '*/' and the end of the line.
//
//   * Either one of the following are true:
//
//     - The comment fits on one line.
//
//     - Each line the comment spans begins with N spaces, followed by '/*' for
//       the initial line or ' *' for subsequent lines, where N is the same for
//       each line.
//
// This tool is a heuristic. While it gets almost all cases correct, the final
// output should still be looked over and fixed up as needed.

// allSpaces returns true if |s| consists entirely of spaces.
func allSpaces(s string) bool {
	return strings.IndexFunc(s, func(r rune) bool { return r != ' ' }) == -1
}

// isContinuation returns true if |s| is a continuation line for a multi-line
// comment indented to the specified column.
func isContinuation(s string, column int) bool {
	if len(s) < column+2 {
		return false
	}
	if !allSpaces(s[:column]) {
		return false
	}
	return s[column:column+2] == " *"
}

// indexFrom behaves like strings.Index but only reports matches starting at
// |idx|.
func indexFrom(s, sep string, idx int) int {
	ret := strings.Index(s[idx:], sep)
	if ret < 0 {
		return -1
	}
	return idx + ret
}

// A lineGroup is a contiguous group of lines with an eligible comment at the
// same column. Any trailing '*/'s will already be removed.
type lineGroup struct {
	// column is the column where the eligible comment begins. line[column]
	// and line[column+1] will both be replaced with '/'. It is -1 if this
	// group is not to be converted.
	column int
	lines  []string
}

func addLine(groups *[]lineGroup, line string, column int) {
	if len(*groups) == 0 || (*groups)[len(*groups)-1].column != column {
		*groups = append(*groups, lineGroup{column, nil})
	}
	(*groups)[len(*groups)-1].lines = append((*groups)[len(*groups)-1].lines, line)
}

// writeLine writes |line| to |out|, followed by a newline.
func writeLine(out *bytes.Buffer, line string) {
	out.WriteString(line)
	out.WriteByte('\n')
}

func convertComments(path string, in []byte) []byte {
	lines := strings.Split(string(in), "\n")

	// Account for the trailing newline.
	if len(lines) > 0 && len(lines[len(lines)-1]) == 0 {
		lines = lines[:len(lines)-1]
	}

	// First pass: identify all comments to be converted. Group them into
	// lineGroups with the same column.
	var groups []lineGroup

	// Find the license block separator.
	for len(lines) > 0 {
		line := lines[0]
		lines = lines[1:]
		addLine(&groups, line, -1)
		if len(line) == 0 {
			break
		}
	}

	// inComment is true if we are in the middle of a comment.
	var inComment bool
	// comment is the currently buffered multi-line comment to convert. If
	// |inComment| is true and it is nil, the current multi-line comment is
	// not convertable and we copy lines to |out| as-is.
	var comment []string
	// column is the column offset of |comment|.
	var column int
	for len(lines) > 0 {
		line := lines[0]
		lines = lines[1:]

		var idx int
		if inComment {
			// Stop buffering if this comment isn't eligible.
			if comment != nil && !isContinuation(line, column) {
				for _, l := range comment {
					addLine(&groups, l, -1)
				}
				comment = nil
			}

			// Look for the end of the current comment.
			idx = strings.Index(line, "*/")
			if idx < 0 {
				if comment != nil {
					comment = append(comment, line)
				} else {
					addLine(&groups, line, -1)
				}
				continue
			}

			inComment = false
			if comment != nil {
				if idx == len(line)-2 {
					// This is a convertable multi-line comment.
					if idx >= column+2 {
						// |idx| may be equal to
						// |column| + 1, if the line is
						// a '*/' on its own. In that
						// case, we discard the line.
						comment = append(comment, line[:idx])
					}
					for _, l := range comment {
						addLine(&groups, l, column)
					}
					comment = nil
					continue
				}

				// Flush the buffered comment unmodified.
				for _, l := range comment {
					addLine(&groups, l, -1)
				}
				comment = nil
			}
			idx += 2
		}

		// Parse starting from |idx|, looking for either a convertable
		// line comment or a multi-line comment.
		for {
			idx = indexFrom(line, "/*", idx)
			if idx < 0 {
				addLine(&groups, line, -1)
				break
			}

			endIdx := indexFrom(line, "*/", idx)
			if endIdx < 0 {
				// The comment is, so far, eligible for conversion.
				inComment = true
				column = idx
				comment = []string{line}
				break
			}

			if endIdx != len(line)-2 {
				// Continue parsing for more comments in this line.
				idx = endIdx + 2
				continue
			}

			addLine(&groups, line[:endIdx], idx)
			break
		}
	}

	// Second pass: convert the lineGroups, adjusting spacing as needed.
	var out bytes.Buffer
	var lineNo int
	for _, group := range groups {
		if group.column < 0 {
			for _, line := range group.lines {
				writeLine(&out, line)
			}
		} else {
			// Google C++ style prefers two spaces before a comment
			// if it is on the same line as code, but clang-format
			// has been placing one space for block comments. All
			// comments within a group should be adjusted by the
			// same amount.
			var adjust string
			for _, line := range group.lines {
				if !allSpaces(line[:group.column]) && line[group.column-1] != '(' {
					if line[group.column-1] != ' ' {
						if len(adjust) < 2 {
							adjust = "  "
						}
					} else if line[group.column-2] != ' ' {
						if len(adjust) < 1 {
							adjust = " "
						}
					}
				}
			}

			for i, line := range group.lines {
				// The OpenSSL style writes multiline block comments with a
				// blank line at the top and bottom, like so:
				//
				//   /*
				//    * Some multi-line
				//    * comment
				//    */
				//
				// The trailing lines are already removed above, when buffering.
				// Remove the leading lines here. (The leading lines cannot be
				// removed when buffering because we may discover the comment is
				// not convertible in later lines.)
				//
				// Note the leading line cannot be easily removed if there is
				// code before it, such as the following. Skip those cases.
				//
				//   foo(); /*
				//           * Some multi-line
				//           * comment
				//           */
				if i == 0 && allSpaces(line[:group.column]) && len(line) == group.column+2 {
					continue
				}
				newLine := fmt.Sprintf("%s%s//%s", line[:group.column], adjust, strings.TrimRight(line[group.column+2:], " "))
				if len(newLine) > 80 {
					fmt.Fprintf(os.Stderr, "%s:%d: Line is now longer than 80 characters\n", path, lineNo+i+1)
				}
				writeLine(&out, newLine)
			}

		}
		lineNo += len(group.lines)
	}
	return out.Bytes()
}

func main() {
	for _, arg := range os.Args[1:] {
		in, err := os.ReadFile(arg)
		if err != nil {
			panic(err)
		}
		if err := os.WriteFile(arg, convertComments(arg, in), 0666); err != nil {
			panic(err)
		}
	}
}
