// Copyright 2019 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 htmlcheck provides a set of functions that check for properties
// of a parsed HTML document.
package htmlcheck

import (
	"fmt"
	"io"
	"regexp"
	"strings"

	"github.com/andybalholm/cascadia"
	"golang.org/x/net/html"
)

// A Checker is a function from an HTML node to an error describing a failure.
type Checker func(*html.Node) error

// Run is a convenience function to run the checker against HTML read from
// reader.
func Run(reader io.Reader, checker Checker) error {
	node, err := html.Parse(reader)
	if err != nil {
		return err
	}
	return checker(node)
}

// In returns a Checker that applies the given checkers to the first node
// matching the CSS selector. The empty selector denotes the entire subtree of
// the Checker's argument node.
//
// Calling In(selector), with no checkers, just checks for the presence of
// a node matching the selector. (For the negation, see NotIn.)
//
// A nil Checker is valid and always succeeds.
func In(selector string, checkers ...Checker) Checker {
	sel := mustParseSelector(selector)
	return func(n *html.Node) error {
		var m *html.Node
		// cascadia.Query does not test against its argument node.
		if sel.Match(n) {
			m = n
		} else {
			m = cascadia.Query(n, sel)
		}
		if m == nil {
			return fmt.Errorf("no element matches selector %q", selector)
		}
		if err := check(m, checkers); err != nil {
			if selector == "" {
				return err
			}
			return fmt.Errorf("%s: %v", selector, err)
		}
		return nil
	}
}

// InAll runs the checkers against all nodes matching selector.
func InAll(selector string, checkers ...Checker) Checker {
	sel := mustParseSelector(selector)
	return func(n *html.Node) error {
		els := allMatching(n, sel)
		for i, el := range els {
			if err := check(el, checkers); err != nil {
				return fmt.Errorf("%s, #%d: %v", selector, i, err)
			}
		}
		return nil
	}
}

func allMatching(n *html.Node, sel cascadia.Sel) []*html.Node {
	var els []*html.Node
	if sel.Match(n) {
		els = append(els, n)
	}
	return append(els, cascadia.QueryAll(n, sel)...)
}

// NotIn returns a checker that succeeds only if no nodes match selector.
func NotIn(selector string) Checker {
	sel := mustParseSelector(selector)
	return func(n *html.Node) error {
		if sel.Match(n) || cascadia.Query(n, sel) != nil {
			return fmt.Errorf("%q matched one or more elements", selector)
		}
		return nil
	}
}

// check calls all the Checkers on n, returning the error of the first one to fail.
func check(n *html.Node, Checkers []Checker) error {
	for _, m := range Checkers {
		if m == nil {
			continue
		}
		if err := m(n); err != nil {
			return err
		}
	}
	return nil
}

// mustParseSelector parses the given CSS selector. An empty string
// is treated as "*" (match everything).
func mustParseSelector(s string) cascadia.Sel {
	if s == "" {
		s = "*"
	}
	sel, err := cascadia.Parse(s)
	if err != nil {
		panic(fmt.Sprintf("parsing %q: %v", s, err))
	}
	return sel
}

// HasText returns a Checker that checks whether the given regexp matches the node's text.
// The text of a node n is the concatenated contents of all text nodes in n's subtree.
// HasText panics if the argument doesn't compile.
func HasText(wantRegexp string) Checker {
	re := regexp.MustCompile(wantRegexp)
	return func(n *html.Node) error {
		var b strings.Builder
		nodeText(n, &b)
		text := b.String()
		if !re.MatchString(text) {
			if len(text) > 100 {
				text = text[:97] + "..."
			}
			return fmt.Errorf("\n`%s` does not match\n%q", wantRegexp, text)
		}
		return nil
	}
}

// HasExactText returns a checker that checks whether the given string matches
// the node's text exactly.
func HasExactText(want string) Checker {
	return HasText("^" + regexp.QuoteMeta(want) + "$")
}

// nodeText appends the text of n's subtree to b. This is the concatenated
// contents of all text nodes, visited depth-first.
func nodeText(n *html.Node, b *strings.Builder) {
	if n == nil {
		return
	}
	switch n.Type {
	case html.TextNode:
		b.WriteString(n.Data)
	case html.ElementNode, html.DocumentNode:
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			nodeText(c, b)
		}
	}
}

// HasAttr returns a Checker that checks for an attribute with the given name whose
// value matches the given regular expression.
// HasAttr panics if wantValRegexp does not compile.
func HasAttr(name, wantValRegexp string) Checker {
	re := regexp.MustCompile(wantValRegexp)
	return func(n *html.Node) error {
		for _, a := range n.Attr {
			if a.Key == name {
				if !re.MatchString(a.Val) {
					return fmt.Errorf("[%q]:\n`%s` does not match\n%q", name, wantValRegexp, a.Val)
				}
				return nil
			}
		}
		return fmt.Errorf("[%q]: no such attribute", name)
	}
}

// HasHref returns a Checker that checks whether the node has an "href"
// attribute with exactly val.
func HasHref(val string) Checker {
	return HasAttr("href", "^"+regexp.QuoteMeta(val)+"$")
}

// Dump returns a Checker that always returns nil, and as a side-effect writes a
// human-readable description of n's subtree to standard output. It is useful
// for debugging.
func Dump() Checker {
	return func(n *html.Node) error {
		dump(n, 0)
		return nil
	}
}

func dump(n *html.Node, depth int) {
	for i := 0; i < depth; i++ {
		fmt.Print("  ")
	}
	fmt.Printf("type %d, data %q, attr %v\n", n.Type, n.Data, n.Attr)
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		dump(c, depth+1)
	}
}
