// Copyright 2009 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 testing

import (
	"strings";
)

var good_re = []string{
	``,
	`.`,
	`^.$`,
	`a`,
	`a*`,
	`a+`,
	`a?`,
	`a|b`,
	`a*|b*`,
	`(a*|b)(c*|d)`,
	`[a-z]`,
	`[a-abc-c\-\]\[]`,
	`[a-z]+`,
	`[]`,
	`[abc]`,
	`[^1234]`,
	`[^\n]`,
}

// TODO: nice to do this with a map
type stringError struct {
	re	string;
	err	string;
}
var bad_re = []stringError{
	stringError{ `*`,	 	ErrBareClosure },
	stringError{ `(abc`,	ErrUnmatchedLpar },
	stringError{ `abc)`,	ErrUnmatchedRpar },
	stringError{ `x[a-z`,	ErrUnmatchedLbkt },
	stringError{ `abc]`,	ErrUnmatchedRbkt },
	stringError{ `[z-a]`,	ErrBadRange },
	stringError{ `abc\`,	ErrExtraneousBackslash },
	stringError{ `a**`,	ErrBadClosure },
	stringError{ `a*+`,	ErrBadClosure },
	stringError{ `a??`,	ErrBadClosure },
	stringError{ `*`,	 	ErrBareClosure },
	stringError{ `\x`,	ErrBadBackslash },
}

type vec []int;

type tester struct {
	re	string;
	text	string;
	match	vec;
}

var matches = []tester {
	tester{ ``,	"",	vec{0,0} },
	tester{ `a`,	"a",	vec{0,1} },
	tester{ `x`,	"y",	vec{} },
	tester{ `b`,	"abc",	vec{1,2} },
	tester{ `.`,	"a",	vec{0,1} },
	tester{ `.*`,	"abcdef",	vec{0,6} },
	tester{ `^abcd$`,	"abcd",	vec{0,4} },
	tester{ `^bcd'`,	"abcdef",	vec{} },
	tester{ `^abcd$`,	"abcde",	vec{} },
	tester{ `a+`,	"baaab",	vec{1,4} },
	tester{ `a*`,	"baaab",	vec{0,0} },
	tester{ `[a-z]+`,	"abcd",	vec{0,4} },
	tester{ `[^a-z]+`,	"ab1234cd",	vec{2,6} },
	tester{ `[a\-\]z]+`,	"az]-bcz",	vec{0,4} },
	tester{ `[^\n]+`,	"abcd\n",	vec{0,4} },
	tester{ `[日本語]+`,	"日本語日本語",	vec{0,18} },
	tester{ `()`,	"",	vec{0,0, 0,0} },
	tester{ `(a)`,	"a",	vec{0,1, 0,1} },
	tester{ `(.)(.)`,	"日a",	vec{0,4, 0,3, 3,4} },
	tester{ `(.*)`,	"",	vec{0,0, 0,0} },
	tester{ `(.*)`,	"abcd",	vec{0,4, 0,4} },
	tester{ `(..)(..)`,	"abcd",	vec{0,4, 0,2, 2,4} },
	tester{ `(([^xyz]*)(d))`,	"abcd",	vec{0,4, 0,4, 0,3, 3,4} },
	tester{ `((a|b|c)*(d))`,	"abcd",	vec{0,4, 0,4, 2,3, 3,4} },
	tester{ `(((a|b|c)*)(d))`,	"abcd",	vec{0,4, 0,4, 0,3, 2,3, 3,4} },
	tester{ `a*(|(b))c*`,	"aacc",	vec{0,4, 2,2, -1,-1} },
}

func compileTest(t *T, expr string, error string) *Regexp {
	re, err := CompileRegexp(expr);
	if err != error {
		t.Error("compiling `", expr, "`; unexpected error: ", err);
	}
	return re
}

func printVec(t *T, m []int) {
	l := len(m);
	if l == 0 {
		t.Log("\t<no match>");
	} else {
		for i := 0; i < l; i = i+2 {
			t.Log("\t", m[i], ",", m[i+1])
		}
	}
}

func printStrings(t *T, m []string) {
	l := len(m);
	if l == 0 {
		t.Log("\t<no match>");
	} else {
		for i := 0; i < l; i = i+2 {
			t.Logf("\t%q", m[i])
		}
	}
}

func printBytes(t *T, b [][]byte) {
	l := len(b);
	if l == 0 {
		t.Log("\t<no match>");
	} else {
		for i := 0; i < l; i = i+2 {
			t.Logf("\t%q", b[i])
		}
	}
}

func equal(m1, m2 []int) bool {
	l := len(m1);
	if l != len(m2) {
		return false
	}
	for i := 0; i < l; i++ {
		if m1[i] != m2[i] {
			return false
		}
	}
	return true
}

func equalStrings(m1, m2 []string) bool {
	l := len(m1);
	if l != len(m2) {
		return false
	}
	for i := 0; i < l; i++ {
		if m1[i] != m2[i] {
			return false
		}
	}
	return true
}

func equalBytes(m1 [][]byte, m2 []string) bool {
	l := len(m1);
	if l != len(m2) {
		return false
	}
	for i := 0; i < l; i++ {
		if string(m1[i]) != m2[i] {
			return false
		}
	}
	return true
}

func executeTest(t *T, expr string, str string, match []int) {
	re := compileTest(t, expr, "");
	if re == nil {
		return
	}
	m := re.ExecuteString(str);
	if !equal(m, match) {
		t.Error("ExecuteString failure on `", expr, "` matching `", str, "`:");
		printVec(t, m);
		t.Log("should be:");
		printVec(t, match);
	}
	// now try bytes
	m = re.Execute(strings.Bytes(str));
	if !equal(m, match) {
		t.Error("Execute failure on `", expr, "` matching `", str, "`:");
		printVec(t, m);
		t.Log("should be:");
		printVec(t, match);
	}
}

func TestGoodCompile(t *T) {
	for i := 0; i < len(good_re); i++ {
		compileTest(t, good_re[i], "");
	}
}

func TestBadCompile(t *T) {
	for i := 0; i < len(bad_re); i++ {
		compileTest(t, bad_re[i].re, bad_re[i].err)
	}
}

func TestExecute(t *T) {
	for i := 0; i < len(matches); i++ {
		test := &matches[i];
		executeTest(t, test.re, test.text, test.match)
	}
}

func matchTest(t *T, expr string, str string, match []int) {
	re := compileTest(t, expr, "");
	if re == nil {
		return
	}
	m := re.MatchString(str);
	if m != (len(match) > 0) {
		t.Error("MatchString failure on `", expr, "` matching `", str, "`:", m, "should be", len(match) > 0);
	}
	// now try bytes
	m = re.Match(strings.Bytes(str));
	if m != (len(match) > 0) {
		t.Error("Match failure on `", expr, "` matching `", str, "`:", m, "should be", len(match) > 0);
	}
}

func TestMatch(t *T) {
	for i := 0; i < len(matches); i++ {
		test := &matches[i];
		matchTest(t, test.re, test.text, test.match)
	}
}

func matchStringsTest(t *T, expr string, str string, match []int) {
	re := compileTest(t, expr, "");
	if re == nil {
		return
	}
	strs := make([]string, len(match)/2);
	for i := 0; i < len(match); i++ {
		strs[i/2] = str[match[i] : match[i+1]]
	}
	m := re.MatchStrings(str);
	if !equalStrings(m, strs) {
		t.Error("MatchStrings failure on `", expr, "` matching `", str, "`:");
		printStrings(t, m);
		t.Log("should be:");
		printStrings(t, strs);
	}
	// now try bytes
	s := re.MatchSlices(strings.Bytes(str));
	if !equalBytes(s, strs) {
		t.Error("MatchSlices failure on `", expr, "` matching `", str, "`:");
		printBytes(t, s);
		t.Log("should be:");
		printStrings(t, strs);
	}
}

func TestMatchStrings(t *T) {
	for i := 0; i < len(matches); i++ {
		test := &matches[i];
		matchTest(t, test.re, test.text, test.match)
	}
}

func matchFunctionTest(t *T, expr string, str string, match []int) {
	m, err := MatchString(expr, str);
	if err == "" {
		return
	}
	if m != (len(match) > 0) {
		t.Error("function Match failure on `", expr, "` matching `", str, "`:", m, "should be", len(match) > 0);
	}
}

func TestMatchFunction(t *T) {
	for i := 0; i < len(matches); i++ {
		test := &matches[i];
		matchFunctionTest(t, test.re, test.text, test.match)
	}
}
