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

import (
	"context"
	"regexp"
	"sync"
	"testing"
	"time"

	"golang.org/x/tools/internal/jsonrpc2/servertest"
	"golang.org/x/tools/internal/lsp/cache"
	"golang.org/x/tools/internal/lsp/debug"
	"golang.org/x/tools/internal/lsp/fake"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/telemetry/event"
)

type fakeClient struct {
	protocol.Client

	logs chan string
}

func (c fakeClient) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {
	c.logs <- params.Message
	return nil
}

type pingServer struct{ protocol.Server }

func (s pingServer) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
	event.Print(ctx, "ping")
	return nil
}

func (s pingServer) Shutdown(ctx context.Context) error {
	return nil
}

func TestClientLogging(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	server := pingServer{}
	client := fakeClient{logs: make(chan string, 10)}

	ctx = debug.WithInstance(ctx, "", "")
	ss := NewStreamServer(cache.New(ctx, nil))
	ss.serverForTest = server
	ts := servertest.NewPipeServer(ctx, ss)
	defer ts.Close()
	cc := ts.Connect(ctx)
	cc.AddHandler(protocol.ClientHandler(client))

	protocol.ServerDispatcher(cc).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{})

	select {
	case got := <-client.logs:
		want := "ping"
		matched, err := regexp.MatchString(want, got)
		if err != nil {
			t.Fatal(err)
		}
		if !matched {
			t.Errorf("got log %q, want a log containing %q", got, want)
		}
	case <-time.After(1 * time.Second):
		t.Error("timeout waiting for client log")
	}
}

// waitableServer instruments LSP request so that we can control their timing.
// The requests chosen are arbitrary: we simply needed one that blocks, and
// another that doesn't.
type waitableServer struct {
	protocol.Server

	started chan struct{}
}

func (s waitableServer) Hover(ctx context.Context, _ *protocol.HoverParams) (*protocol.Hover, error) {
	s.started <- struct{}{}
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case <-time.After(200 * time.Millisecond):
	}
	return &protocol.Hover{}, nil
}

func (s waitableServer) Resolve(_ context.Context, item *protocol.CompletionItem) (*protocol.CompletionItem, error) {
	return item, nil
}

func (s waitableServer) Shutdown(ctx context.Context) error {
	return nil
}

func TestRequestCancellation(t *testing.T) {
	server := waitableServer{
		started: make(chan struct{}),
	}
	baseCtx := context.Background()
	serveCtx := debug.WithInstance(baseCtx, "", "")
	ss := NewStreamServer(cache.New(serveCtx, nil))
	ss.serverForTest = server
	tsDirect := servertest.NewTCPServer(serveCtx, ss)
	defer tsDirect.Close()

	forwarderCtx := debug.WithInstance(baseCtx, "", "")
	forwarder := NewForwarder("tcp", tsDirect.Addr)
	tsForwarded := servertest.NewPipeServer(forwarderCtx, forwarder)
	defer tsForwarded.Close()

	tests := []struct {
		serverType string
		ts         servertest.Connector
	}{
		{"direct", tsDirect},
		{"forwarder", tsForwarded},
	}

	for _, test := range tests {
		t.Run(test.serverType, func(t *testing.T) {
			cc := test.ts.Connect(baseCtx)
			cc.AddHandler(protocol.Canceller{})
			ctx := context.Background()
			ctx1, cancel1 := context.WithCancel(ctx)
			var (
				err1, err2 error
				wg         sync.WaitGroup
			)
			wg.Add(2)
			go func() {
				defer wg.Done()
				_, err1 = protocol.ServerDispatcher(cc).Hover(ctx1, &protocol.HoverParams{})
			}()
			go func() {
				defer wg.Done()
				_, err2 = protocol.ServerDispatcher(cc).Resolve(ctx, &protocol.CompletionItem{})
			}()
			// Wait for the Hover request to start.
			<-server.started
			cancel1()
			wg.Wait()
			if err1 == nil {
				t.Errorf("cancelled Hover(): got nil err")
			}
			if err2 != nil {
				t.Errorf("uncancelled Hover(): err: %v", err2)
			}
			if _, err := protocol.ServerDispatcher(cc).Resolve(ctx, &protocol.CompletionItem{}); err != nil {
				t.Errorf("subsequent Hover(): %v", err)
			}
		})
	}
}

const exampleProgram = `
-- go.mod --
module mod

go 1.12
-- main.go --
package main

import "fmt"

func main() {
	fmt.Println("Hello World.")
}`

func TestDebugInfoLifecycle(t *testing.T) {
	resetExitFuncs := OverrideExitFuncsForTest()
	defer resetExitFuncs()

	baseCtx := context.Background()
	clientCtx := debug.WithInstance(baseCtx, "", "")
	serverCtx := debug.WithInstance(baseCtx, "", "")

	cache := cache.New(serverCtx, nil)
	ss := NewStreamServer(cache)
	tsBackend := servertest.NewTCPServer(serverCtx, ss)

	forwarder := NewForwarder("tcp", tsBackend.Addr)
	tsForwarder := servertest.NewPipeServer(clientCtx, forwarder)

	ws, err := fake.NewWorkspace("gopls-lsprpc-test", []byte(exampleProgram))
	if err != nil {
		t.Fatal(err)
	}
	defer ws.Close()

	conn1 := tsForwarder.Connect(clientCtx)
	ed1, err := fake.NewConnectedEditor(clientCtx, ws, conn1)
	if err != nil {
		t.Fatal(err)
	}
	defer ed1.Shutdown(clientCtx)
	conn2 := tsBackend.Connect(baseCtx)
	ed2, err := fake.NewConnectedEditor(baseCtx, ws, conn2)
	if err != nil {
		t.Fatal(err)
	}
	defer ed2.Shutdown(baseCtx)

	serverDebug := debug.GetInstance(serverCtx)
	if got, want := len(serverDebug.State.Clients()), 2; got != want {
		t.Errorf("len(server:Clients) = %d, want %d", got, want)
	}
	if got, want := len(serverDebug.State.Sessions()), 2; got != want {
		t.Errorf("len(server:Sessions) = %d, want %d", got, want)
	}
	clientDebug := debug.GetInstance(clientCtx)
	if got, want := len(clientDebug.State.Servers()), 1; got != want {
		t.Errorf("len(client:Servers) = %d, want %d", got, want)
	}
	// Close one of the connections to verify that the client and session were
	// dropped.
	if err := ed1.Shutdown(clientCtx); err != nil {
		t.Fatal(err)
	}
	if got, want := len(serverDebug.State.Sessions()), 1; got != want {
		t.Errorf("len(server:Sessions()) = %d, want %d", got, want)
	}
	// TODO(rfindley): once disconnection works, assert that len(Clients) == 1
	// (as of writing, it is still 2)
}

// TODO: add a test for telemetry.
