// Copyright 2021 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_test

import (
	"context"
	"regexp"
	"strings"
	"testing"
	"time"

	jsonrpc2_v2 "golang.org/x/tools/internal/jsonrpc2_v2"
	"golang.org/x/tools/internal/lsp/protocol"

	. "golang.org/x/tools/internal/lsp/lsprpc"
)

type TestEnv struct {
	Listeners []jsonrpc2_v2.Listener
	Conns     []*jsonrpc2_v2.Connection
	Servers   []*jsonrpc2_v2.Server
}

func (e *TestEnv) Shutdown(t *testing.T) {
	for _, l := range e.Listeners {
		if err := l.Close(); err != nil {
			t.Error(err)
		}
	}
	for _, c := range e.Conns {
		if err := c.Close(); err != nil {
			t.Error(err)
		}
	}
	for _, s := range e.Servers {
		if err := s.Wait(); err != nil {
			t.Error(err)
		}
	}
}

func (e *TestEnv) serve(ctx context.Context, t *testing.T, server jsonrpc2_v2.Binder) (jsonrpc2_v2.Listener, *jsonrpc2_v2.Server) {
	l, err := jsonrpc2_v2.NetPipeListener(ctx)
	if err != nil {
		t.Fatal(err)
	}
	e.Listeners = append(e.Listeners, l)
	s, err := jsonrpc2_v2.Serve(ctx, l, server)
	if err != nil {
		t.Fatal(err)
	}
	e.Servers = append(e.Servers, s)
	return l, s
}

func (e *TestEnv) dial(ctx context.Context, t *testing.T, dialer jsonrpc2_v2.Dialer, client jsonrpc2_v2.Binder, forwarded bool) *jsonrpc2_v2.Connection {
	if forwarded {
		l, _ := e.serve(ctx, t, NewForwardBinder(dialer))
		dialer = l.Dialer()
	}
	conn, err := jsonrpc2_v2.Dial(ctx, dialer, client)
	if err != nil {
		t.Fatal(err)
	}
	e.Conns = append(e.Conns, conn)
	return conn
}

func staticClientBinder(client protocol.Client) jsonrpc2_v2.Binder {
	f := func(context.Context, protocol.Server) protocol.Client { return client }
	return NewClientBinder(f)
}

func staticServerBinder(server protocol.Server) jsonrpc2_v2.Binder {
	f := func(ctx context.Context, client protocol.ClientCloser) protocol.Server {
		return server
	}
	return NewServerBinder(f)
}

func TestClientLoggingV2(t *testing.T) {
	ctx := context.Background()

	for name, forwarded := range map[string]bool{
		"forwarded":  true,
		"standalone": false,
	} {
		t.Run(name, func(t *testing.T) {
			client := FakeClient{Logs: make(chan string, 10)}
			env := new(TestEnv)
			defer env.Shutdown(t)
			l, _ := env.serve(ctx, t, staticServerBinder(PingServer{}))
			conn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded)

			if err := protocol.ServerDispatcherV2(conn).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{}); err != nil {
				t.Errorf("DidOpen: %v", err)
			}
			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")
			}
		})
	}
}

func TestRequestCancellationV2(t *testing.T) {
	ctx := context.Background()

	for name, forwarded := range map[string]bool{
		"forwarded":  true,
		"standalone": false,
	} {
		t.Run(name, func(t *testing.T) {
			server := WaitableServer{
				Started:   make(chan struct{}),
				Completed: make(chan error),
			}
			env := new(TestEnv)
			defer env.Shutdown(t)
			l, _ := env.serve(ctx, t, staticServerBinder(server))
			client := FakeClient{Logs: make(chan string, 10)}
			conn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded)

			sd := protocol.ServerDispatcherV2(conn)
			ctx, cancel := context.WithCancel(ctx)

			result := make(chan error)
			go func() {
				_, err := sd.Hover(ctx, &protocol.HoverParams{})
				result <- err
			}()
			// Wait for the Hover request to start.
			<-server.Started
			cancel()
			if err := <-result; err == nil {
				t.Error("nil error for cancelled Hover(), want non-nil")
			}
			if err := <-server.Completed; err == nil || !strings.Contains(err.Error(), "cancelled hover") {
				t.Errorf("Hover(): unexpected server-side error %v", err)
			}
		})
	}
}
