// Copyright 2014 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 blueprint

import (
	"fmt"
	"io"
	"strings"
	"unicode"
)

const (
	indentWidth    = 4
	maxIndentDepth = 2
	lineWidth      = 80
)

var indentString = strings.Repeat(" ", indentWidth*maxIndentDepth)

type ninjaWriter struct {
	writer io.Writer

	justDidBlankLine bool // true if the last operation was a BlankLine
}

func newNinjaWriter(writer io.Writer) *ninjaWriter {
	return &ninjaWriter{
		writer: writer,
	}
}

func (n *ninjaWriter) Comment(comment string) error {
	n.justDidBlankLine = false

	const lineHeaderLen = len("# ")
	const maxLineLen = lineWidth - lineHeaderLen

	var lineStart, lastSplitPoint int
	for i, r := range comment {
		if unicode.IsSpace(r) {
			// We know we can safely split the line here.
			lastSplitPoint = i + 1
		}

		var line string
		var writeLine bool
		switch {
		case r == '\n':
			// Output the line without trimming the left so as to allow comments
			// to contain their own indentation.
			line = strings.TrimRightFunc(comment[lineStart:i], unicode.IsSpace)
			writeLine = true

		case (i-lineStart > maxLineLen) && (lastSplitPoint > lineStart):
			// The line has grown too long and is splittable.  Split it at the
			// last split point.
			line = strings.TrimSpace(comment[lineStart:lastSplitPoint])
			writeLine = true
		}

		if writeLine {
			line = strings.TrimSpace("# "+line) + "\n"
			_, err := io.WriteString(n.writer, line)
			if err != nil {
				return err
			}
			lineStart = lastSplitPoint
		}
	}

	if lineStart != len(comment) {
		line := strings.TrimSpace(comment[lineStart:])
		_, err := fmt.Fprintf(n.writer, "# %s\n", line)
		if err != nil {
			return err
		}
	}

	return nil
}

func (n *ninjaWriter) Pool(name string) error {
	n.justDidBlankLine = false
	_, err := fmt.Fprintf(n.writer, "pool %s\n", name)
	return err
}

func (n *ninjaWriter) Rule(name string) error {
	n.justDidBlankLine = false
	_, err := fmt.Fprintf(n.writer, "rule %s\n", name)
	return err
}

func (n *ninjaWriter) Build(rule string, outputs, explicitDeps, implicitDeps,
	orderOnlyDeps []string) error {

	n.justDidBlankLine = false

	const lineWrapLen = len(" $")
	const maxLineLen = lineWidth - lineWrapLen

	wrapper := ninjaWriterWithWrap{
		ninjaWriter: n,
		maxLineLen:  maxLineLen,
	}

	wrapper.WriteString("build")

	for _, output := range outputs {
		wrapper.WriteStringWithSpace(output)
	}

	wrapper.WriteString(":")

	wrapper.WriteStringWithSpace(rule)

	for _, dep := range explicitDeps {
		wrapper.WriteStringWithSpace(dep)
	}

	if len(implicitDeps) > 0 {
		wrapper.WriteStringWithSpace("|")

		for _, dep := range implicitDeps {
			wrapper.WriteStringWithSpace(dep)
		}
	}

	if len(orderOnlyDeps) > 0 {
		wrapper.WriteStringWithSpace("||")

		for _, dep := range orderOnlyDeps {
			wrapper.WriteStringWithSpace(dep)
		}
	}

	return wrapper.Flush()
}

func (n *ninjaWriter) Assign(name, value string) error {
	n.justDidBlankLine = false
	_, err := fmt.Fprintf(n.writer, "%s = %s\n", name, value)
	return err
}

func (n *ninjaWriter) ScopedAssign(name, value string) error {
	n.justDidBlankLine = false
	_, err := fmt.Fprintf(n.writer, "%s%s = %s\n", indentString[:indentWidth], name, value)
	return err
}

func (n *ninjaWriter) Default(targets ...string) error {
	n.justDidBlankLine = false

	const lineWrapLen = len(" $")
	const maxLineLen = lineWidth - lineWrapLen

	wrapper := ninjaWriterWithWrap{
		ninjaWriter: n,
		maxLineLen:  maxLineLen,
	}

	wrapper.WriteString("default")

	for _, target := range targets {
		wrapper.WriteString(" " + target)
	}

	return wrapper.Flush()
}

func (n *ninjaWriter) BlankLine() (err error) {
	// We don't output multiple blank lines in a row.
	if !n.justDidBlankLine {
		n.justDidBlankLine = true
		_, err = io.WriteString(n.writer, "\n")
	}
	return err
}

type ninjaWriterWithWrap struct {
	*ninjaWriter
	maxLineLen int
	writtenLen int
	err        error
}

func (n *ninjaWriterWithWrap) writeString(s string, space bool) {
	if n.err != nil {
		return
	}

	spaceLen := 0
	if space {
		spaceLen = 1
	}

	if n.writtenLen+len(s)+spaceLen > n.maxLineLen {
		_, n.err = io.WriteString(n.writer, " $\n")
		if n.err != nil {
			return
		}
		_, n.err = io.WriteString(n.writer, indentString[:indentWidth*2])
		if n.err != nil {
			return
		}
		n.writtenLen = indentWidth * 2
		s = strings.TrimLeftFunc(s, unicode.IsSpace)
	} else if space {
		io.WriteString(n.writer, " ")
		n.writtenLen++
	}

	_, n.err = io.WriteString(n.writer, s)
	n.writtenLen += len(s)
}

func (n *ninjaWriterWithWrap) WriteString(s string) {
	n.writeString(s, false)
}

func (n *ninjaWriterWithWrap) WriteStringWithSpace(s string) {
	n.writeString(s, true)
}

func (n *ninjaWriterWithWrap) Flush() error {
	if n.err != nil {
		return n.err
	}
	_, err := io.WriteString(n.writer, "\n")
	return err
}
