// Copyright 2019 The Fuchsia 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 fidlgen_test

import (
	"encoding/json"
	"fmt"
	"math"
	"testing"

	"github.com/google/go-cmp/cmp"
	"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
	"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgentest"
)

// toDocComment formats doc comments in a by adding a leading space and a
// trailing newline.
func toDocComment(input string) string {
	return " " + input + "\n"
}

func TestCanUnmarshalLargeOrdinal(t *testing.T) {
	input := `{
		"ordinal": 18446744073709551615
	}`

	var method fidlgen.Method
	err := json.Unmarshal([]byte(input), &method)
	if err != nil {
		t.Fatalf("failed to unmarshal: %s", err)
	}
	if method.Ordinal != math.MaxUint64 {
		t.Fatalf("method.Ordinal: expected math.MaxUint64, found %d", method.Ordinal)
	}
}

func TestCanUnmarshalAttributeValue(t *testing.T) {
	root := fidlgentest.EndToEndTest{T: t}.Single(`
		library example;

		[doc="MyUnion", UpperCamelCase, lower_snake_case, CAPS]
		flexible union MyUnion {
			/// my_union_member
			[Unknown] 1: bool my_union_member;
		};
	`)

	// MyUnion
	unionName := string(root.Unions[0].Name)
	wantUnionName := "MyUnion"
	unionAttrs := root.Unions[0].Attributes
	if len(unionAttrs.Attributes) != 4 {
		t.Errorf("got %d attributes on '%s', want %d", len(unionAttrs.Attributes), unionName, 4)
	}
	if val, found := unionAttrs.LookupAttribute("Doc"); !found || val.Value != wantUnionName {
		t.Errorf("'%s' 'doc' attribute: got '%s', want '%s'", unionName, val.Value, wantUnionName)
	}
	if _, found := unionAttrs.LookupAttribute("UpperCamelCase"); !found {
		t.Errorf("'%s' 'UpperCamelCase' attribute: not found (using UpperCamelCase search)", unionName)
	}
	if _, found := unionAttrs.LookupAttribute("upper_camel_case"); !found {
		t.Errorf("'%s' 'UpperCamelCase' attribute: not found (using lower-case search)", unionName)
	}
	if _, found := unionAttrs.LookupAttribute("LowerSnakeCase"); !found {
		t.Errorf("'%s' 'lower_snake_case' attribute: not found (using UpperCamelCase search)", unionName)
	}
	if _, found := unionAttrs.LookupAttribute("lower_snake_case"); !found {
		t.Errorf("'%s' 'lower_snake_case' attribute: not found (using lower-case search)", unionName)
	}
	if _, found := unionAttrs.LookupAttribute("Caps"); !found {
		t.Errorf("'%s' 'CAPS' attribute: not found (using UpperCamelCase search)", unionName)
	}
	if _, found := unionAttrs.LookupAttribute("caps"); !found {
		t.Errorf("'%s' 'CAPS' attribute: not found (using lower-snake-case search)", unionName)
	}
	if _, found := unionAttrs.LookupAttribute("CAPS"); !found {
		t.Errorf("'%s' 'CAPS' attribute: not found (using default string for search)", unionName)
	}

	// my_union_member
	unionMemName := string(root.Unions[0].Members[0].Name)
	wantUnionMemName := "my_union_member"
	unionMemAttrs := root.Unions[0].Members[0].Attributes
	if unionMemName != wantUnionMemName {
		t.Errorf("got union with name '%s', want '%s'", unionMemName, wantUnionMemName)
	}
	if len(unionMemAttrs.Attributes) != 2 {
		t.Errorf("got %d attributes on '%s', want %d", len(unionMemAttrs.Attributes), unionMemName, 2)
	}
	if val, found := unionMemAttrs.LookupAttribute("Doc"); !found || val.Value != toDocComment(wantUnionMemName) {
		t.Errorf("'%s' 'doc' attribute: got '%s', want '%s'", unionMemName, val.Value, toDocComment(wantUnionMemName))
	}
	if _, found := unionMemAttrs.LookupAttribute("Unknown"); !found {
		t.Errorf("'%s' 'unknown' attribute: not found", unionMemName)
	}
	if _, found := unionMemAttrs.LookupAttribute("Missing"); found {
		t.Errorf("'%s' 'missing' attribute: found when non-existant", unionMemName)
	}
	if _, found := unionMemAttrs.LookupAttribute("missing"); found {
		t.Errorf("'%s' 'missing' attribute: found when non-existant", unionMemName)
	}
}

func TestCanUnmarshalSignedEnumUnknownValue(t *testing.T) {
	inputTmpl := `{
		"enum_declarations": [
			{
			"type": "int32",
			"strict": false,
			"maybe_unknown_value": %s
			}
		]
	}`

	cases := []struct {
		jsonValue     string
		expectedValue int64
	}{
		{"0", 0},
		{"300", 300},
		{"-300", -300},
		{"9223372036854775806", math.MaxInt64 - 1},
		{"9223372036854775807", math.MaxInt64},
		{"-9223372036854775808", math.MinInt64},
	}
	for _, ex := range cases {
		root, err := fidlgen.ReadJSONIrContent([]byte(fmt.Sprintf(inputTmpl, ex.jsonValue)))
		if err != nil {
			t.Fatalf("failed to read JSON IR: %s", err)
		}
		enumOfSignedInt := root.Enums[0]
		unknownValue, err := enumOfSignedInt.UnknownValueAsInt64()
		if err != nil {
			t.Fatalf("failed to retrieve UnknownValueAsInt64: %s", err)
		}
		if unknownValue != ex.expectedValue {
			t.Fatalf("jsonValue '%s': expected %d, actual %d",
				ex.jsonValue, ex.expectedValue, unknownValue)
		}
	}
}

func TestCanUnmarshalUnsignedEnumUnknownValue(t *testing.T) {
	inputTmpl := `{
		"enum_declarations": [
			{
			"type": "uint32",
			"strict": false,
			"maybe_unknown_value": %s
			}
		]
	}`

	cases := []struct {
		jsonValue     string
		expectedValue uint64
	}{
		{"0", 0},
		{"300", 300},
		{"18446744073709551614", math.MaxUint64 - 1},
		{"18446744073709551615", math.MaxUint64},
	}
	for _, ex := range cases {
		root, err := fidlgen.ReadJSONIrContent([]byte(fmt.Sprintf(inputTmpl, ex.jsonValue)))
		if err != nil {
			t.Fatalf("failed to read JSON IR: %s", err)
		}
		enumOfSignedInt := root.Enums[0]
		unknownValue, err := enumOfSignedInt.UnknownValueAsUint64()
		if err != nil {
			t.Fatalf("failed to retrieve UnknownValueAsUint64: %s", err)
		}
		if unknownValue != ex.expectedValue {
			t.Fatalf("jsonValue '%s': expected %d, actual %d",
				ex.jsonValue, ex.expectedValue, unknownValue)
		}
	}
}

func TestCanUnmarshalBitsStrictness(t *testing.T) {
	inputTmpl := `{
		"bits_declarations": [
			{
				"type": {
					"kind": "primitive",
					"subtype": "uint32"
				},
				"mask": "1",
				"members": [],
				"strict": %s
			}
		]
	}`

	cases := []struct {
		jsonValue     string
		expectedValue fidlgen.Strictness
	}{
		{"false", fidlgen.IsFlexible},
		{"true", fidlgen.IsStrict},
	}
	for _, ex := range cases {
		root, err := fidlgen.ReadJSONIrContent([]byte(fmt.Sprintf(inputTmpl, ex.jsonValue)))
		if err != nil {
			t.Fatalf("failed to read JSON IR: %s", err)
		}
		bits := root.Bits[0]
		if bits.Strictness != ex.expectedValue {
			t.Fatalf("jsonValue '%s': expected %v, actual %v",
				ex.jsonValue, ex.expectedValue, bits.Strictness)
		}
	}
}

func TestParseCompoundIdentifier(t *testing.T) {
	type testCase struct {
		input          fidlgen.EncodedCompoundIdentifier
		expectedOutput fidlgen.CompoundIdentifier
	}
	tests := []testCase{
		{
			input:          "Decl",
			expectedOutput: compoundIdentifier([]string{""}, "Decl", ""),
		},
		{
			input:          "fuchsia.some.library/Decl",
			expectedOutput: compoundIdentifier([]string{"fuchsia", "some", "library"}, "Decl", ""),
		},
		{
			input:          "Name.MEMBER",
			expectedOutput: compoundIdentifier([]string{""}, "Name", "MEMBER"),
		},

		{
			input:          "fuchsia.some.library/Decl.MEMBER",
			expectedOutput: compoundIdentifier([]string{"fuchsia", "some", "library"}, "Decl", "MEMBER"),
		},
	}
	for _, test := range tests {
		output := fidlgen.ParseCompoundIdentifier(test.input)
		diff := cmp.Diff(output, test.expectedOutput)
		if len(diff) > 0 {
			t.Errorf("unexpected output for input %q diff: %s", test.input, diff)
		}
	}
}

func compoundIdentifier(library []string, name, member string) fidlgen.CompoundIdentifier {
	var convertedLibrary fidlgen.LibraryIdentifier
	for _, part := range library {
		convertedLibrary = append(convertedLibrary, fidlgen.Identifier(part))
	}
	return fidlgen.CompoundIdentifier{
		Library: convertedLibrary,
		Name:    fidlgen.Identifier(name),
		Member:  fidlgen.Identifier(member),
	}
}
