// Copyright 2015 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.

// +build ignore

// This program generates table.go from
// http://www.w3.org/TR/SVG/types.html#ColorKeywords
package main

import (
	"bytes"
	"fmt"
	"go/format"
	"image/color"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"sort"
	"strconv"
	"strings"

	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

// matchFunc matches HTML nodes.
type matchFunc func(*html.Node) bool

// appendAll recursively traverses the parse tree rooted under the provided
// node and appends all nodes matched by the matchFunc to dst.
func appendAll(dst []*html.Node, n *html.Node, mf matchFunc) []*html.Node {
	if mf(n) {
		dst = append(dst, n)
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		dst = appendAll(dst, c, mf)
	}
	return dst
}

// matchAtom returns a matchFunc that matches a Node with the specified Atom.
func matchAtom(a atom.Atom) matchFunc {
	return func(n *html.Node) bool {
		return n.DataAtom == a
	}
}

// matchAtomAttr returns a matchFunc that matches a Node with the specified
// Atom and a html.Attribute's namespace, key and value.
func matchAtomAttr(a atom.Atom, namespace, key, value string) matchFunc {
	return func(n *html.Node) bool {
		return n.DataAtom == a && getAttr(n, namespace, key) == value
	}
}

// getAttr fetches the value of a html.Attribute for a given namespace and key.
func getAttr(n *html.Node, namespace, key string) string {
	for _, attr := range n.Attr {
		if attr.Namespace == namespace && attr.Key == key {
			return attr.Val
		}
	}
	return ""
}

// re extracts RGB values from strings like "rgb( 0, 223, 128)".
var re = regexp.MustCompile(`rgb\(\s*([0-9]+),\s*([0-9]+),\s*([0-9]+)\)`)

// parseRGB parses a color from a string like "rgb( 0, 233, 128)". It sets
// the alpha value of the color to full opacity.
func parseRGB(s string) (color.RGBA, error) {
	m := re.FindStringSubmatch(s)
	if m == nil {
		return color.RGBA{}, fmt.Errorf("malformed color: %q", s)
	}
	var rgb [3]uint8
	for i, t := range m[1:] {
		num, err := strconv.ParseUint(t, 10, 8)
		if err != nil {
			return color.RGBA{}, fmt.Errorf("malformed value %q in %q: %s", t, s, err)
		}
		rgb[i] = uint8(num)
	}
	return color.RGBA{rgb[0], rgb[1], rgb[2], 0xFF}, nil
}

// extractSVGColors extracts named colors from the parse tree of the SVG 1.1
// spec HTML document "Chapter 4: Basic data types and interfaces".
func extractSVGColors(tree *html.Node) (map[string]color.RGBA, error) {
	ret := make(map[string]color.RGBA)

	// Find the tables which store the color keywords in the parse tree.
	colorTables := appendAll(nil, tree, func(n *html.Node) bool {
		return n.DataAtom == atom.Table && strings.Contains(getAttr(n, "", "summary"), "color keywords part")
	})

	for _, table := range colorTables {
		// Color names and values are stored in TextNodes within spans in each row.
		for _, tr := range appendAll(nil, table, matchAtom(atom.Tr)) {
			nameSpan := appendAll(nil, tr, matchAtomAttr(atom.Span, "", "class", "prop-value"))
			valueSpan := appendAll(nil, tr, matchAtomAttr(atom.Span, "", "class", "color-keyword-value"))

			// Since SVG 1.1 defines an odd number of colors, the last row
			// in the second table does not have contents. We skip it.
			if len(nameSpan) != 1 || len(valueSpan) != 1 {
				continue
			}
			n, v := nameSpan[0].FirstChild, valueSpan[0].FirstChild
			// This sanity checks for the existence of TextNodes under spans.
			if n == nil || n.Type != html.TextNode || v == nil || v.Type != html.TextNode {
				return nil, fmt.Errorf("extractSVGColors: couldn't find name/value text nodes")
			}
			val, err := parseRGB(v.Data)
			if err != nil {
				return nil, fmt.Errorf("extractSVGColors: couldn't parse name/value %q/%q: %s", n.Data, v.Data, err)
			}
			ret[n.Data] = val
		}
	}
	return ret, nil
}

const preamble = `// generated by go generate; DO NOT EDIT.

package colornames

import "image/color"

`

// WriteColorNames writes table.go.
func writeColorNames(w io.Writer, m map[string]color.RGBA) {
	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	fmt.Fprintln(w, preamble)
	fmt.Fprintln(w, "// Map contains named colors defined in the SVG 1.1 spec.")
	fmt.Fprintln(w, "var Map = map[string]color.RGBA{")
	for _, k := range keys {
		c := m[k]
		fmt.Fprintf(w, "%q:color.RGBA{%#02x, %#02x, %#02x, %#02x}, // rgb(%d, %d, %d)\n",
			k, c.R, c.G, c.B, c.A, c.R, c.G, c.B)
	}
	fmt.Fprintln(w, "}\n")
	fmt.Fprintln(w, "// Names contains the color names defined in the SVG 1.1 spec.")
	fmt.Fprintln(w, "var Names = []string{")
	for _, k := range keys {
		fmt.Fprintf(w, "%q,\n", k)
	}
	fmt.Fprintln(w, "}\n")
	fmt.Fprintln(w, "var (")
	for _, k := range keys {
		c := m[k]
		// Make the upper case version of k: "Darkred" instead of "darkred".
		k = string(k[0]-0x20) + k[1:]
		fmt.Fprintf(w, "%s=color.RGBA{%#02x, %#02x, %#02x, %#02x} // rgb(%d, %d, %d)\n",
			k, c.R, c.G, c.B, c.A, c.R, c.G, c.B)
	}
	fmt.Fprintln(w, ")")
}

const url = "http://www.w3.org/TR/SVG/types.html"

func main() {
	res, err := http.Get(url)
	if err != nil {
		log.Fatalf("Couldn't read from %s: %s\n", url, err)
	}
	defer res.Body.Close()

	tree, err := html.Parse(res.Body)
	if err != nil {
		log.Fatalf("Couldn't parse %s: %s\n", url, err)
	}

	colors, err := extractSVGColors(tree)
	if err != nil {
		log.Fatalf("Couldn't extract colors: %s\n", err)
	}

	buf := &bytes.Buffer{}
	writeColorNames(buf, colors)
	fmted, err := format.Source(buf.Bytes())
	if err != nil {
		log.Fatalf("Error while formatting code: %s\n", err)
	}

	if err := ioutil.WriteFile("table.go", fmted, 0644); err != nil {
		log.Fatalf("Error writing table.go: %s\n", err)
	}
}
