// Copyright 2018 The CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cue

import (
	"fmt"
	"math/big"
	"testing"

	"github.com/cockroachdb/apd/v2"
	"github.com/google/go-cmp/cmp"
	"github.com/google/go-cmp/cmp/cmpopts"

	"cuelang.org/go/cue/ast"
)

var testBase = newExpr(&ast.BasicLit{})

func mkInt(a int64) *numLit {
	return newInt(testBase, base10).setInt64(a)
}
func mkIntString(a string) *numLit {
	return newInt(testBase, base10).setString(a)
}
func mkFloat(a string) *numLit {
	return newFloat(testBase, base10).setString(a)
}

var diffOpts = []cmp.Option{
	cmp.Comparer(func(x, y big.Rat) bool {
		return x.String() == y.String()
	}),
	cmp.Comparer(func(x, y big.Int) bool {
		return x.String() == y.String()
	}),
	cmp.AllowUnexported(
		nullLit{},
		boolLit{},
		stringLit{},
		bytesLit{},
		numLit{},
	),
	cmpopts.IgnoreUnexported(
		bottom{},
		baseValue{},
		baseValue{},
	),
}

var (
	nullSentinel  = &nullLit{}
	trueSentinel  = &boolLit{b: true}
	falseSentinel = &boolLit{b: false}
)

func TestLiterals(t *testing.T) {
	mkMul := func(x int64, m multiplier, base int) *numLit {
		return newInt(testBase, newRepresentation(m, base, false)).setInt64(x)
	}
	hk := newInt(testBase, newRepresentation(0, 10, true)).setInt64(100000)
	testCases := []struct {
		lit  string
		node value
	}{
		{"0", mkInt(0)},
		{"null", nullSentinel},
		{"true", trueSentinel},
		{"false", falseSentinel},
		{"fls", &bottom{}},
		{`"foo"`, &stringLit{str: "foo"}},
		{`#"foo"#`, &stringLit{str: "foo"}},
		{`#""foo"#`, &stringLit{str: `"foo`}},
		{`#" ""#`, &stringLit{str: ` "`}},
		{`"\"foo\""`, &stringLit{str: `"foo"`}},
		{`"foo\u0032"`, &stringLit{str: `foo2`}},
		{`"foo\U00000033"`, &stringLit{str: `foo3`}},
		{`"foo\U0001f499"`, &stringLit{str: `foo💙`}},
		{`"\a\b\f\n\r\t\v"`, &stringLit{str: "\a\b\f\n\r\t\v"}},
		{`"""
		"""`, &stringLit{str: ""}},
		{`"""
			abc
			"""`, &stringLit{str: "abc"}},
		{`"""
			abc
			def
			"""`, &stringLit{str: "abc\ndef"}},
		{`"""
			abc
				def
			"""`, &stringLit{str: "abc\n\tdef"}},
		{`'\xff'`, &bytesLit{b: []byte("\xff")}},
		{"1", mkInt(1)},
		{"100_000", hk},
		{"1.", mkFloat("1")},
		{"0.0", mkFloat("0.0")},
		{".0", mkFloat(".0")},
		{"012.34", mkFloat("012.34")},
		{".01", mkFloat(".01")},
		{".01e2", mkFloat("1")},
		{"0.", mkFloat("0.")},
		{"1K", mkMul(1000, mulK, 10)},
		{".5K", mkMul(500, mulK, 10)},
		{"1Mi", mkMul(1024*1024, mulMi, 10)},
		{"1.5Mi", mkMul((1024+512)*1024, mulMi, 10)},
		{"1.3Mi", &bottom{}}, // Cannot be accurately represented.
		{"1.3G", mkMul(1300000000, mulG, 10)},
		{"1.3e+20", mkFloat("1.3e+20")},
		{"1.3e20", mkFloat("1.3e+20")},
		{"1.3e-5", mkFloat("1.3e-5")},
		{".3e-1", mkFloat("0.3e-1")},
		{"0e-5", mkFloat("0e-5")},
		{"0E-5", mkFloat("0e-5")},
		{"5e-5", mkFloat("5e-5")},
		{"5E-5", mkFloat("5e-5")},
		{"0x1234", mkMul(0x1234, 0, 16)},
		{"0xABCD", mkMul(0xABCD, 0, 16)},
		{"0b11001000", mkMul(0xc8, 0, 2)},
		{"0b1", mkMul(1, 0, 2)},
		{"0o755", mkMul(0755, 0, 8)},
		{"0755", mkMul(0755, 0, 8)},
	}
	p := litParser{
		ctx: &context{Context: &apd.BaseContext},
	}
	for i, tc := range testCases {
		t.Run(fmt.Sprintf("%d/%+q", i, tc.lit), func(t *testing.T) {
			got := p.parse(&ast.BasicLit{Value: tc.lit})
			if !cmp.Equal(got, tc.node, diffOpts...) {
				t.Error(cmp.Diff(got, tc.node, diffOpts...))
				t.Errorf("%#v, %#v\n", got, tc.node)
			}
		})
	}
}

func TestLiteralErrors(t *testing.T) {
	testCases := []struct {
		lit string
	}{
		{`"foo\u"`},
		{`"foo\u003"`},
		{`"foo\U1234567"`},
		{`"foo\U12345678"`},
		{`"foo\Ug"`},
		{`"\xff"`},
		// not allowed in string literal, only binary
		{`"foo\x00"`},
		{`0x`},
		{`0o`},
		{`0b`},
		{`0_`},
		{"0128"},
		{``},
		{`"`},
		{`"a`},
		// wrong indentation
		{`"""
			abc
		def
			"""`},
		// non-matching quotes
		{`"""
			abc
			'''`},
		{`"""
			abc
			"`},
		{`"abc \( foo "`},
	}
	p := litParser{
		ctx: &context{Context: &apd.BaseContext},
	}
	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%+q", tc.lit), func(t *testing.T) {
			got := p.parse(&ast.BasicLit{Value: tc.lit})
			if _, ok := got.(*bottom); !ok {
				t.Fatalf("expected error but found none")
			}
		})
	}
}
