// Copyright 2018 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 cmd handles the gopls command line.
// It contains a handler for each of the modes, along with all the flag handling
// and the command line output format.
package cmd

import (
	"context"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"net"
	"os"
	"strings"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/jsonrpc2"
	"golang.org/x/tools/internal/lsp"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/span"
	"golang.org/x/tools/internal/tool"
)

// Application is the main application as passed to tool.Main
// It handles the main command line parsing and dispatch to the sub commands.
type Application struct {
	// Core application flags

	// Embed the basic profiling flags supported by the tool package
	tool.Profile

	// We include the server configuration directly for now, so the flags work
	// even without the verb.
	// TODO: Remove this when we stop allowing the serve verb by default.
	Serve Serve

	// An initial, common go/packages configuration
	Config packages.Config

	// Support for remote lsp server
	Remote string `flag:"remote" help:"*EXPERIMENTAL* - forward all commands to a remote lsp"`
}

// Name implements tool.Application returning the binary name.
func (app *Application) Name() string { return "gopls" }

// Usage implements tool.Application returning empty extra argument usage.
func (app *Application) Usage() string { return "<command> [command-flags] [command-args]" }

// ShortHelp implements tool.Application returning the main binary help.
func (app *Application) ShortHelp() string {
	return "The Go Language source tools."
}

// DetailedHelp implements tool.Application returning the main binary help.
// This includes the short help for all the sub commands.
func (app *Application) DetailedHelp(f *flag.FlagSet) {
	fmt.Fprint(f.Output(), `
Available commands are:
`)
	for _, c := range app.commands() {
		fmt.Fprintf(f.Output(), "  %s : %v\n", c.Name(), c.ShortHelp())
	}
	fmt.Fprint(f.Output(), `
gopls flags are:
`)
	f.PrintDefaults()
}

// Run takes the args after top level flag processing, and invokes the correct
// sub command as specified by the first argument.
// If no arguments are passed it will invoke the server sub command, as a
// temporary measure for compatibility.
func (app *Application) Run(ctx context.Context, args ...string) error {
	app.Serve.app = app
	if len(args) == 0 {
		tool.Main(ctx, &app.Serve, args)
		return nil
	}
	if app.Config.Dir == "" {
		if wd, err := os.Getwd(); err == nil {
			app.Config.Dir = wd
		}
	}
	app.Config.Mode = packages.LoadSyntax
	app.Config.Tests = true
	if app.Config.Fset == nil {
		app.Config.Fset = token.NewFileSet()
	}
	app.Config.Context = ctx
	app.Config.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
		return parser.ParseFile(fset, filename, src, parser.AllErrors|parser.ParseComments)
	}
	command, args := args[0], args[1:]
	for _, c := range app.commands() {
		if c.Name() == command {
			tool.Main(ctx, c, args)
			return nil
		}
	}
	return tool.CommandLineErrorf("Unknown command %v", command)
}

// commands returns the set of commands supported by the gopls tool on the
// command line.
// The command is specified by the first non flag argument.
func (app *Application) commands() []tool.Application {
	return []tool.Application{
		&app.Serve,
		&query{app: app},
		&check{app: app},
	}
}

type cmdClient interface {
	protocol.Client

	prepare(app *Application, server protocol.Server)
}

func (app *Application) connect(ctx context.Context, client cmdClient) (protocol.Server, error) {
	var server protocol.Server
	switch app.Remote {
	case "":
		server = lsp.NewClientServer(client)
	case "internal":
		cr, sw, _ := os.Pipe()
		sr, cw, _ := os.Pipe()
		var jc *jsonrpc2.Conn
		jc, server, _ = protocol.NewClient(jsonrpc2.NewHeaderStream(cr, cw), client)
		go jc.Run(ctx)
		go lsp.NewServer(jsonrpc2.NewHeaderStream(sr, sw)).Run(ctx)
	default:
		conn, err := net.Dial("tcp", app.Remote)
		if err != nil {
			return nil, err
		}
		stream := jsonrpc2.NewHeaderStream(conn, conn)
		var jc *jsonrpc2.Conn
		jc, server, _ = protocol.NewClient(stream, client)
		go jc.Run(ctx)
	}

	params := &protocol.InitializeParams{}
	params.RootURI = string(span.FileURI(app.Config.Dir))
	params.Capabilities.Workspace.Configuration = true
	params.Capabilities.TextDocument.Hover.ContentFormat = []protocol.MarkupKind{protocol.PlainText}

	client.prepare(app, server)
	if _, err := server.Initialize(ctx, params); err != nil {
		return nil, err
	}
	if err := server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {
		return nil, err
	}
	return server, nil
}

type baseClient struct {
	protocol.Server
	app    *Application
	server protocol.Server
	fset   *token.FileSet
}

func (c *baseClient) ShowMessage(ctx context.Context, p *protocol.ShowMessageParams) error { return nil }
func (c *baseClient) ShowMessageRequest(ctx context.Context, p *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) {
	return nil, nil
}
func (c *baseClient) LogMessage(ctx context.Context, p *protocol.LogMessageParams) error {
	switch p.Type {
	case protocol.Error:
		log.Print("Error:", p.Message)
	case protocol.Warning:
		log.Print("Warning:", p.Message)
	case protocol.Info:
		log.Print("Info:", p.Message)
	case protocol.Log:
		log.Print("Log:", p.Message)
	default:
		log.Print(p.Message)
	}
	return nil
}
func (c *baseClient) Telemetry(ctx context.Context, t interface{}) error { return nil }
func (c *baseClient) RegisterCapability(ctx context.Context, p *protocol.RegistrationParams) error {
	return nil
}
func (c *baseClient) UnregisterCapability(ctx context.Context, p *protocol.UnregistrationParams) error {
	return nil
}
func (c *baseClient) WorkspaceFolders(ctx context.Context) ([]protocol.WorkspaceFolder, error) {
	return nil, nil
}
func (c *baseClient) Configuration(ctx context.Context, p *protocol.ConfigurationParams) ([]interface{}, error) {
	results := make([]interface{}, len(p.Items))
	for i, item := range p.Items {
		if item.Section != "gopls" {
			continue
		}
		env := map[string]interface{}{}
		for _, value := range c.app.Config.Env {
			l := strings.SplitN(value, "=", 2)
			if len(l) != 2 {
				continue
			}
			env[l[0]] = l[1]
		}
		results[i] = map[string]interface{}{"env": env}
	}
	return results, nil
}
func (c *baseClient) ApplyEdit(ctx context.Context, p *protocol.ApplyWorkspaceEditParams) (bool, error) {
	return false, nil
}
func (c *baseClient) PublishDiagnostics(ctx context.Context, p *protocol.PublishDiagnosticsParams) error {
	return nil
}

func (c *baseClient) prepare(app *Application, server protocol.Server) {
	c.app = app
	c.server = server
	c.fset = token.NewFileSet()
}

func (c *baseClient) AddFile(ctx context.Context, uri span.URI) (*protocol.ColumnMapper, error) {
	fname, err := uri.Filename()
	if err != nil {
		return nil, fmt.Errorf("%v: %v", uri, err)
	}
	content, err := ioutil.ReadFile(fname)
	if err != nil {
		return nil, fmt.Errorf("%v: %v", uri, err)
	}
	f := c.fset.AddFile(fname, -1, len(content))
	f.SetLinesForContent(content)
	m := protocol.NewColumnMapper(uri, c.fset, f, content)
	p := &protocol.DidOpenTextDocumentParams{}
	p.TextDocument.URI = string(uri)
	p.TextDocument.Text = string(content)
	if err := c.server.DidOpen(ctx, p); err != nil {
		return nil, fmt.Errorf("%v: %v", uri, err)
	}
	return m, nil
}
