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

import (
	"context"
	"io"
	"math/rand"
	"strconv"

	"golang.org/x/tools/internal/gocommand"
	"golang.org/x/tools/internal/lsp/debug/tag"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/telemetry/event"
	"golang.org/x/xerrors"
)

func (s *Server) runGenerate(ctx context.Context, dir string, recursive bool) {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	token := strconv.FormatInt(rand.Int63(), 10)
	s.inProgressMu.Lock()
	s.inProgress[token] = cancel
	s.inProgressMu.Unlock()
	defer s.clearInProgress(token)

	er := &eventWriter{ctx: ctx}
	wc := s.newProgressWriter(ctx, cancel, token)
	defer wc.Close()
	args := []string{"-x"}
	if recursive {
		args = append(args, "./...")
	}
	inv := &gocommand.Invocation{
		Verb:       "generate",
		Args:       args,
		Env:        s.session.Options().Env,
		WorkingDir: dir,
	}
	stderr := io.MultiWriter(er, wc)
	err := inv.RunPiped(ctx, er, stderr)
	if err != nil {
		event.Error(ctx, "generate: command error: %v", err, tag.Directory.Of(dir))
		if !xerrors.Is(err, context.Canceled) {
			s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
				Type:    protocol.Error,
				Message: "go generate exited with an error, check gopls logs",
			})
		}
	}
}

// eventWriter writes every incoming []byte to
// event.Print with the operation=generate tag
// to distinguish its logs from others.
type eventWriter struct {
	ctx context.Context
}

func (ew *eventWriter) Write(p []byte) (n int, err error) {
	event.Print(ew.ctx, string(p), tag.Operation.Of("generate"))
	return len(p), nil
}

// newProgressWriter returns an io.WriterCloser that can be used
// to report progress on the "go generate" command based on the
// client capabilities.
func (s *Server) newProgressWriter(ctx context.Context, cancel func(), token string) io.WriteCloser {
	var wc interface {
		io.WriteCloser
		start()
	}
	if s.supportsWorkDoneProgress {
		wc = &workDoneWriter{ctx, token, s.client}
	} else {
		wc = &messageWriter{ctx, cancel, s.client}
	}
	wc.start()
	return wc
}

// messageWriter implements progressWriter
// and only tells the user that "go generate"
// has started through window/showMessage but does not
// report anything afterwards. This is because each
// log shows up as a separate window and therefore
// would be obnoxious to show every incoming line.
// Request cancellation happens synchronously through
// the ShowMessageRequest response.
type messageWriter struct {
	ctx    context.Context
	cancel func()
	client protocol.Client
}

func (lw *messageWriter) Write(p []byte) (n int, err error) {
	return len(p), nil
}

func (lw *messageWriter) start() {
	go func() {
		msg, err := lw.client.ShowMessageRequest(lw.ctx, &protocol.ShowMessageRequestParams{
			Type:    protocol.Log,
			Message: "go generate has started, check logs for progress",
			Actions: []protocol.MessageActionItem{{
				Title: "Cancel",
			}},
		})
		if err != nil {
			event.Error(lw.ctx, "error sending initial generate msg", err)
			return
		}
		if msg != nil && msg.Title == "Cancel" {
			lw.cancel()
		}
	}()
}

func (lw *messageWriter) Close() error {
	return lw.client.ShowMessage(lw.ctx, &protocol.ShowMessageParams{
		Type:    protocol.Info,
		Message: "go generate has finished",
	})
}

// workDoneWriter implements progressWriter
// that will send $/progress notifications
// to the client. Request cancellations
// happens separately through the
// window/workDoneProgress/cancel request
// in which case the given context will be rendered
// done.
type workDoneWriter struct {
	ctx    context.Context
	token  string
	client protocol.Client
}

func (wdw *workDoneWriter) Write(p []byte) (n int, err error) {
	return len(p), wdw.client.Progress(wdw.ctx, &protocol.ProgressParams{
		Token: wdw.token,
		Value: &protocol.WorkDoneProgressReport{
			Kind:        "report",
			Cancellable: true,
			Message:     string(p),
		},
	})
}

func (wdw *workDoneWriter) start() {
	err := wdw.client.WorkDoneProgressCreate(wdw.ctx, &protocol.WorkDoneProgressCreateParams{
		Token: wdw.token,
	})
	if err != nil {
		event.Error(wdw.ctx, "generate progress create", err)
		return
	}
	err = wdw.client.Progress(wdw.ctx, &protocol.ProgressParams{
		Token: wdw.token,
		Value: &protocol.WorkDoneProgressBegin{
			Kind:        "begin",
			Cancellable: true,
			Message:     "running go generate",
			Title:       "generate",
		},
	})
	if err != nil {
		event.Error(wdw.ctx, "generate progress begin", err)
	}
}

func (wdw *workDoneWriter) Close() error {
	return wdw.client.Progress(wdw.ctx, &protocol.ProgressParams{
		Token: wdw.token,
		Value: protocol.WorkDoneProgressEnd{
			Kind:    "end",
			Message: "finished",
		},
	})
}
