// Copyright 2022 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 dag implements a language for expressing directed acyclic
// graphs.
//
// The general syntax of a rule is:
//
//	a, b < c, d;
//
// which means c and d come after a and b in the partial order
// (that is, there are edges from c and d to a and b),
// but doesn't provide a relative order between a vs b or c vs d.
//
// The rules can chain together, as in:
//
//	e < f, g < h;
//
// which is equivalent to
//
//	e < f, g;
//	f, g < h;
//
// Except for the special bottom element "NONE", each name
// must appear exactly once on the right-hand side of any rule.
// That rule serves as the definition of the allowed successor
// for that name. The definition must appear before any uses
// of the name on the left-hand side of a rule. (That is, the
// rules themselves must be ordered according to the partial
// order, for easier reading by people.)
//
// Negative assertions double-check the partial order:
//
//	i !< j
//
// means that it must NOT be the case that i < j.
// Negative assertions may appear anywhere in the rules,
// even before i and j have been defined.
//
// Comments begin with #.
package dag

import (
	"cmp"
	"fmt"
	"slices"
	"strings"
)

type Graph struct {
	Nodes   []string
	byLabel map[string]int
	edges   map[string]map[string]bool
}

func newGraph() *Graph {
	return &Graph{byLabel: map[string]int{}, edges: map[string]map[string]bool{}}
}

func (g *Graph) addNode(label string) bool {
	if _, ok := g.byLabel[label]; ok {
		return false
	}
	g.byLabel[label] = len(g.Nodes)
	g.Nodes = append(g.Nodes, label)
	g.edges[label] = map[string]bool{}
	return true
}

func (g *Graph) AddEdge(from, to string) {
	g.edges[from][to] = true
}

func (g *Graph) DelEdge(from, to string) {
	delete(g.edges[from], to)
}

func (g *Graph) HasEdge(from, to string) bool {
	return g.edges[from] != nil && g.edges[from][to]
}

func (g *Graph) Edges(from string) []string {
	edges := make([]string, 0, 16)
	for k := range g.edges[from] {
		edges = append(edges, k)
	}
	slices.SortFunc(edges, func(a, b string) int {
		return cmp.Compare(g.byLabel[a], g.byLabel[b])
	})
	return edges
}

// Parse parses the DAG language and returns the transitive closure of
// the described graph. In the returned graph, there is an edge from "b"
// to "a" if b < a (or a > b) in the partial order.
func Parse(dag string) (*Graph, error) {
	g := newGraph()
	disallowed := []rule{}

	rules, err := parseRules(dag)
	if err != nil {
		return nil, err
	}

	// TODO: Add line numbers to errors.
	var errors []string
	errorf := func(format string, a ...any) {
		errors = append(errors, fmt.Sprintf(format, a...))
	}
	for _, r := range rules {
		if r.op == "!<" {
			disallowed = append(disallowed, r)
			continue
		}
		for _, def := range r.def {
			if def == "NONE" {
				errorf("NONE cannot be a predecessor")
				continue
			}
			if !g.addNode(def) {
				errorf("multiple definitions for %s", def)
			}
			for _, less := range r.less {
				if less == "NONE" {
					continue
				}
				if _, ok := g.byLabel[less]; !ok {
					errorf("use of %s before its definition", less)
				} else {
					g.AddEdge(def, less)
				}
			}
		}
	}

	// Check for missing definition.
	for _, tos := range g.edges {
		for to := range tos {
			if g.edges[to] == nil {
				errorf("missing definition for %s", to)
			}
		}
	}

	// Complete transitive closure.
	for _, k := range g.Nodes {
		for _, i := range g.Nodes {
			for _, j := range g.Nodes {
				if i != k && k != j && g.HasEdge(i, k) && g.HasEdge(k, j) {
					if i == j {
						// Can only happen along with a "use of X before deps" error above,
						// but this error is more specific - it makes clear that reordering the
						// rules will not be enough to fix the problem.
						errorf("graph cycle: %s < %s < %s", j, k, i)
					}
					g.AddEdge(i, j)
				}
			}
		}
	}

	// Check negative assertions against completed allowed graph.
	for _, bad := range disallowed {
		for _, less := range bad.less {
			for _, def := range bad.def {
				if g.HasEdge(def, less) {
					errorf("graph edge assertion failed: %s !< %s", less, def)
				}
			}
		}
	}

	if len(errors) > 0 {
		return nil, fmt.Errorf("%s", strings.Join(errors, "\n"))
	}

	return g, nil
}

// A rule is a line in the DAG language where "less < def" or "less !< def".
type rule struct {
	less []string
	op   string // Either "<" or "!<"
	def  []string
}

type syntaxError string

func (e syntaxError) Error() string {
	return string(e)
}

// parseRules parses the rules of a DAG.
func parseRules(rules string) (out []rule, err error) {
	defer func() {
		e := recover()
		switch e := e.(type) {
		case nil:
			return
		case syntaxError:
			err = e
		default:
			panic(e)
		}
	}()
	p := &rulesParser{lineno: 1, text: rules}

	var prev []string
	var op string
	for {
		list, tok := p.nextList()
		if tok == "" {
			if prev == nil {
				break
			}
			p.syntaxError("unexpected EOF")
		}
		if prev != nil {
			out = append(out, rule{prev, op, list})
		}
		prev = list
		if tok == ";" {
			prev = nil
			op = ""
			continue
		}
		if tok != "<" && tok != "!<" {
			p.syntaxError("missing <")
		}
		op = tok
	}

	return out, err
}

// A rulesParser parses the depsRules syntax described above.
type rulesParser struct {
	lineno   int
	lastWord string
	text     string
}

// syntaxError reports a parsing error.
func (p *rulesParser) syntaxError(msg string) {
	panic(syntaxError(fmt.Sprintf("parsing graph: line %d: syntax error: %s near %s", p.lineno, msg, p.lastWord)))
}

// nextList parses and returns a comma-separated list of names.
func (p *rulesParser) nextList() (list []string, token string) {
	for {
		tok := p.nextToken()
		switch tok {
		case "":
			if len(list) == 0 {
				return nil, ""
			}
			fallthrough
		case ",", "<", "!<", ";":
			p.syntaxError("bad list syntax")
		}
		list = append(list, tok)

		tok = p.nextToken()
		if tok != "," {
			return list, tok
		}
	}
}

// nextToken returns the next token in the deps rules,
// one of ";" "," "<" "!<" or a name.
func (p *rulesParser) nextToken() string {
	for {
		if p.text == "" {
			return ""
		}
		switch p.text[0] {
		case ';', ',', '<':
			t := p.text[:1]
			p.text = p.text[1:]
			return t

		case '!':
			if len(p.text) < 2 || p.text[1] != '<' {
				p.syntaxError("unexpected token !")
			}
			p.text = p.text[2:]
			return "!<"

		case '#':
			i := strings.Index(p.text, "\n")
			if i < 0 {
				i = len(p.text)
			}
			p.text = p.text[i:]
			continue

		case '\n':
			p.lineno++
			fallthrough
		case ' ', '\t':
			p.text = p.text[1:]
			continue

		default:
			i := strings.IndexAny(p.text, "!;,<#\n \t")
			if i < 0 {
				i = len(p.text)
			}
			t := p.text[:i]
			p.text = p.text[i:]
			p.lastWord = t
			return t
		}
	}
}
