// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package web

import (
	"bytes"
	"fmt"
	"html"
	"html/template"
	"log"
	"regexp"
	"strings"

	"golang.org/x/website/internal/texthtml"
)

func (s *siteDir) code(file string, arg ...interface{}) (_ template.HTML, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("%v", r)
		}
	}()

	_, text, _, cfg, err := s.locate("code", file, arg...)
	if err != nil {
		return "", err
	}
	cfg.GoComments = true
	if cfg.HL == "" {
		cfg.HL = "HL"
	}

	var buf bytes.Buffer
	fmt.Fprintf(&buf, "<div class=\"code\">\n\n")
	fmt.Fprintf(&buf, "<pre>")
	// HTML-escape text and syntax-color comments like elsewhere.
	buf.Write(texthtml.Format([]byte(text), cfg))
	fmt.Fprintf(&buf, "</pre>\n")
	fmt.Fprintf(&buf, "</div>\n\n")
	return template.HTML(buf.String()), nil
}

func (s *siteDir) play(file string, arg ...interface{}) (_ template.HTML, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("%v", r)
		}
	}()

	before, text, after, cfg, err := s.locate("play", file, arg...)
	if err != nil {
		return "", err
	}
	cfg.Playground = true

	var buf bytes.Buffer
	fmt.Fprintf(&buf, "<div class=\"playground\">\n\n")
	if before != "" {
		fmt.Fprintf(&buf, "<pre style=\"display: none\"><span>%s</span>\n</pre>\n", html.EscapeString(before))
	}
	// HTML-escape text and syntax-color comments like elsewhere.
	fmt.Fprintf(&buf, "<pre contenteditable=\"true\" spellcheck=\"false\">")
	buf.Write(texthtml.Format([]byte(text), cfg))
	fmt.Fprintf(&buf, "</pre>\n")
	if after != "" {
		fmt.Fprintf(&buf, "<pre style=\"display: none\"><span>%s</span>\n</pre>\n", html.EscapeString(after))
	}
	fmt.Fprintf(&buf, "</div>\n\n")

	return template.HTML(buf.String()), nil
}

func (s *siteDir) locate(verb, file string, arg ...interface{}) (before, text, after string, cfg texthtml.Config, err error) {
	btext, err := s.readFile(s.dir, file)
	if err != nil {
		return
	}
	text = string(btext)
	if len(arg) > 0 {
		if s, ok := arg[len(arg)-1].(string); ok && strings.HasPrefix(s, "HL") {
			cfg.HL = s
			arg = arg[:len(arg)-1]
		}
	}
	if len(arg) > 0 {
		if n, ok := arg[len(arg)-1].(int); ok {
			if n == 0 {
				n = -1
			}
			cfg.Line = n
			arg = arg[:len(arg)-1]
		}
	}
	switch len(arg) {
	case 0:
		// text is already whole file.
		if cfg.Line == -1 {
			cfg.Line = 1
		}
		lines := strings.SplitAfter(text, "\n")
		filterOmit(lines)
		text = strings.Join(lines, "")
	case 1:
		var n int
		before, text, after, n = s.oneLine(file, text, arg[0])
		if cfg.Line == -1 {
			cfg.Line = n
		}
	case 2:
		var n int
		before, text, after, n = s.multipleLines(file, text, arg[0], arg[1])
		if cfg.Line == -1 {
			cfg.Line = n
		}
	default:
		err = fmt.Errorf("incorrect code invocation: %s %q [%v, ...] (%d arguments)", verb, file, arg[0], len(arg))
		return
	}

	// Trim leading and trailing blank lines from output.
	text = strings.Trim(text, "\n")
	if text != "" {
		text += "\n"
	}
	// Replace tabs by spaces, which work better in HTML.
	text = strings.Replace(text, "\t", "    ", -1)

	return
}

// Functions in this file panic on error, but the panic is recovered
// to an error by 'code'.

// stringFor returns a textual representation of the arg, formatted according to its nature.
func stringFor(arg interface{}) string {
	switch arg := arg.(type) {
	case int:
		return fmt.Sprintf("%d", arg)
	case string:
		if len(arg) > 2 && arg[0] == '/' && arg[len(arg)-1] == '/' {
			return fmt.Sprintf("%#q", arg)
		}
		return fmt.Sprintf("%q", arg)
	default:
		log.Panicf("unrecognized argument: %v type %T", arg, arg)
	}
	return ""
}

// oneLine returns the single line generated by a two-argument code invocation.
func (s *Site) oneLine(file, body string, arg interface{}) (before, text, after string, num int) {
	lines := strings.SplitAfter(body, "\n")
	line, pattern, isInt := parseArg(arg, file, len(lines))
	if !isInt {
		line = match(file, 0, lines, pattern)
	}
	filterOmit(lines)
	line--
	return strings.Join(lines[:line], ""),
		lines[line],
		strings.Join(lines[line+1:], ""),
		line
}

// multipleLines returns the text generated by a three-argument code invocation.
func (s *Site) multipleLines(file, body string, arg1, arg2 interface{}) (before, text, after string, num int) {
	lines := strings.SplitAfter(body, "\n")
	line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
	line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
	if !isInt1 {
		line1 = match(file, 0, lines, pattern1)
	}
	if !isInt2 {
		line2 = match(file, line1, lines, pattern2)
	} else if line2 < line1 {
		log.Panicf("lines out of order for %q: %d %d", file, line1, line2)
	}
	filterOmit(lines)
	line1--
	return strings.Join(lines[:line1], ""),
		strings.Join(lines[line1:line2], ""),
		strings.Join(lines[line2:], ""),
		line1
}

// parseArg returns the integer or string value of the argument and tells which it is.
func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
	switch n := arg.(type) {
	case int:
		if n <= 0 || n > max {
			log.Panicf("%q:%d is out of range", file, n)
		}
		return n, "", true
	case string:
		return 0, n, false
	}
	log.Panicf("unrecognized argument %v type %T", arg, arg)
	return
}

// match identifies the input line that matches the pattern in a code invocation.
// If start>0, match lines starting there rather than at the beginning.
// The return value is 1-indexed.
func match(file string, start int, lines []string, pattern string) int {
	// $ matches the end of the file.
	if pattern == "$" {
		if len(lines) == 0 {
			log.Panicf("%q: empty file", file)
		}
		return len(lines)
	}
	// /regexp/ matches the line that matches the regexp.
	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
		re, err := regexp.Compile("(?m)" + pattern[1:len(pattern)-1])
		if err != nil {
			log.Panic(err)
		}
		for i := start; i < len(lines); i++ {
			if re.MatchString(lines[i]) {
				return i + 1
			}
		}
		log.Panicf("%s: no match for %#q", file, pattern)
	}
	log.Panicf("unrecognized pattern: %q", pattern)
	return 0
}

func filterOmit(lines []string) {
	for i, s := range lines {
		if strings.HasSuffix(s, "OMIT\n") {
			lines[i] = ""
		}
	}

}
