// 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 langserver

import (
	"strings"
	"testing"

	"github.com/sourcegraph/go-lsp"

	"fidl-lsp/state"
)

func TestLinks(t *testing.T) {
	fileText := `
library test;

using fuchsia.io;
using non.platform.import;
`
	lines := strings.SplitAfter(fileText, "\n")

	handler := NewHandlerWithFiles(TestFile{
		Name: "test.fidl",
		Text: fileText,
	})

	links, err := handler.handleDocumentLinks(documentLinkParams{
		TextDocument: lsp.TextDocumentIdentifier{
			URI: lsp.DocumentURI("test.fidl"),
		},
	})
	if err != nil {
		t.Fatalf("failed to get document links: %s", err)
	}
	expLinks := map[string]lsp.DocumentURI{
		"fuchsia.io": lsp.DocumentURI("https://fuchsia.dev/reference/fidl/fuchsia.io"),
	}
	if len(links) != len(expLinks) {
		t.Fatalf("incorrect number of links; expected 1, actual %d", len(links))
	}
	for expSpan, expLink := range expLinks {
		found := false
		for _, link := range links {
			start, err := state.OffsetInFile(
				lines,
				state.Position{Line: link.Range.Start.Line, Character: link.Range.Start.Character},
			)
			if err != nil {
				t.Fatalf("could not get offset of link in file: %s", err)
			}
			end, err := state.OffsetInFile(
				lines,
				state.Position{Line: link.Range.End.Line, Character: link.Range.End.Character},
			)
			if err != nil {
				t.Fatalf("could not get offset of link in file: %s", err)
			}
			span := fileText[start:end]
			if span == expSpan && link.Target == expLink {
				found = true
				break
			}
		}
		// Check if it's in links
		if !found {
			t.Fatalf("missing expected link `%s` on span `%s`", expLink, expSpan)
		}
	}
}
