// Copyright 2020 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 state_test

import (
	"testing"

	"fidl-lsp/state"
)

func TestLibraryOfFile(t *testing.T) {
	library, err := state.LibraryOfFile(`library example;`)
	if err != nil {
		t.Errorf("error getting library of file: %s", err)
	}
	expLibrary := "example"
	if library != expLibrary {
		t.Errorf("expected library `%s`, got `%s`", expLibrary, library)
	}

	library, err = state.LibraryOfFile(`
/// Doc comments
library fuchsia.foo.bar;
struct S {};
`)
	if err != nil {
		t.Errorf("error getting library of file: %s", err)
	}
	expLibrary = "fuchsia.foo.bar"
	if library != expLibrary {
		t.Errorf("expected library `%s`, got `%s`", expLibrary, library)
	}

	library, err = state.LibraryOfFile(`library .invalid.name;`)
	if err == nil {
		t.Error("expect error getting library of file")
	}

	library, err = state.LibraryOfFile(`library exampl // Missing semicolon`)
	if err == nil {
		t.Error("expect error getting library of file")
	}
}

func TestParseLibraryMatch(t *testing.T) {
	library, ok := state.ParseLibraryMatch(`
library example;
//      ~~~~~~~ expected range
`)
	if !ok {
		t.Errorf("error getting library of file")
	}
	expLibrary := state.LibraryMatch{
		Lib: "example",
		Range: state.Range{
			Start: state.Position{Line: 1, Character: 8},
			End:   state.Position{Line: 1, Character: 15},
		},
	}
	if library != expLibrary {
		t.Errorf("expected library `%v`, got `%v`", expLibrary, library)
	}

	library, ok = state.ParseLibraryMatch(`
/// Doc comments
library fuchsia.foo.bar;
//      ~~~~~~~~~~~~~~~ expected range
struct S {};
`)
	if !ok {
		t.Errorf("error getting library of file")
	}
	expLibrary = state.LibraryMatch{
		Lib: "fuchsia.foo.bar",
		Range: state.Range{
			Start: state.Position{Line: 2, Character: 8},
			End:   state.Position{Line: 2, Character: 23},
		},
	}
	if library != expLibrary {
		t.Errorf("expected library `%v`, got `%v`", expLibrary, library)
	}

	library, ok = state.ParseLibraryMatch(`library .invalid.name;`)
	if ok {
		t.Error("expect error getting library of file")
	}

	library, ok = state.ParseLibraryMatch(`library exampl // Missing semicolon`)
	if ok {
		t.Error("expect error getting library of file")
	}
}

func TestParsePlatformImportsMatch(t *testing.T) {
	imports := state.ParsePlatformImportsMatch(`
library example;
using fuchsia.foo.bar;
using fuchsia.baz.qux;
using non.platform.import;
using TypeAlias = uint8;
`)

	expImports := []state.LibraryMatch{
		{
			Lib: "fuchsia.foo.bar",
			Range: state.Range{
				Start: state.Position{Line: 2, Character: 6},
				End:   state.Position{Line: 2, Character: 21},
			},
		},
		{
			Lib: "fuchsia.baz.qux",
			Range: state.Range{
				Start: state.Position{Line: 3, Character: 6},
				End:   state.Position{Line: 3, Character: 21},
			},
		},
	}
	if len(imports) != len(expImports) {
		t.Errorf("expected %d imports, found %d", len(expImports), len(imports))
	}
	for i, expImport := range expImports {
		if imports[i] != expImport {
			t.Errorf("unexpected import `%v`, expected `%v`", imports[i], expImport)
		}
	}
}
