// Copyright 2019 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.

// Replay logs. See README.md
package main

import (
	"bufio"
	"context"
	"flag"
	"fmt"
	exec "golang.org/x/sys/execabs"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"

	"golang.org/x/tools/gopls/integration/parse"
	"golang.org/x/tools/internal/fakenet"
	"golang.org/x/tools/internal/jsonrpc2"
	p "golang.org/x/tools/internal/lsp/protocol"
)

var (
	command = flag.String("cmd", "", "location of server to send to, looks for gopls")
	cmp     = flag.Bool("cmp", false, "only compare log and /tmp/seen")
	logrdr  *bufio.Scanner
	msgs    []*parse.Logmsg
	// requests and responses/errors, by id
	clreq  = make(map[string]*parse.Logmsg)
	clresp = make(map[string]*parse.Logmsg)
	svreq  = make(map[string]*parse.Logmsg)
	svresp = make(map[string]*parse.Logmsg)
)

func main() {
	log.SetFlags(log.Lshortfile)
	flag.Usage = func() {
		fmt.Fprintln(flag.CommandLine.Output(), "replay [options] <logfile>")
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}
	logf := flag.Arg(0)

	orig, err := parse.ToRlog(logf)
	if err != nil {
		log.Fatalf("error parsing logfile %q: %v", logf, err)
	}
	ctx := context.Background()
	msgs = orig.Logs
	log.Printf("old %d, hist:%s", len(msgs), orig.Histogram)

	if !*cmp {
		log.Print("calling mimic")
		mimic(ctx)
	}
	seen, err := parse.ToRlog("/tmp/seen")
	if err != nil {
		log.Fatal(err)
	}
	newMsgs := seen.Logs
	log.Printf("new %d, hist:%s", len(newMsgs), seen.Histogram)

	ok := make(map[string]int)
	f := func(x []*parse.Logmsg, label string, diags map[p.DocumentURI][]p.Diagnostic) {
		counts := make(map[parse.MsgType]int)
		for _, l := range x {
			if l.Method == "window/logMessage" {
				// don't care
				//continue
			}
			if l.Method == "textDocument/publishDiagnostics" {
				v, ok := l.Body.(*p.PublishDiagnosticsParams)
				if !ok {
					log.Fatalf("got %T expected PublishDiagnosticsParams", l.Body)
				}
				diags[v.URI] = v.Diagnostics
			}
			counts[l.Type]++
			// notifications only
			if l.Type != parse.ToServer && l.Type != parse.ToClient {
				continue
			}
			s := fmt.Sprintf("%s %s %s", strings.Replace(l.Hdr, "\r", "", -1), label, l.Type)
			if i := strings.Index(s, "notification"); i != -1 {
				s = s[i+12:]
			}
			if len(s) > 120 {
				s = s[:120]
			}
			ok[s]++
		}
		msg := ""
		for i := parse.ClRequest; i <= parse.ReportErr; i++ {
			msg += fmt.Sprintf("%s:%d ", i, counts[i])
		}
		log.Printf("%s: %s", label, msg)
	}
	mdiags := make(map[p.DocumentURI][]p.Diagnostic)
	f(msgs, "old", mdiags)
	vdiags := make(map[p.DocumentURI][]p.Diagnostic)
	f(newMsgs, "new", vdiags)
	buf := []string{}
	for k := range ok {
		buf = append(buf, fmt.Sprintf("%s %d", k, ok[k]))
	}
	if len(buf) > 0 {
		log.Printf("counts of notifications")
		sort.Strings(buf)
		for _, k := range buf {
			log.Print(k)
		}
	}
	buf = buf[0:0]
	for k, v := range mdiags {
		va := vdiags[k]
		if len(v) != len(va) {
			buf = append(buf, fmt.Sprintf("new has %d, old has %d for %s",
				len(va), len(v), k))
		}
	}
	for ka := range vdiags {
		if _, ok := mdiags[ka]; !ok {
			buf = append(buf, fmt.Sprintf("new diagnostics, but no old ones, for %s",
				ka))
		}
	}
	if len(buf) > 0 {
		log.Print("diagnostics differ:")
		for _, s := range buf {
			log.Print(s)
		}
	}
}

func send(ctx context.Context, l *parse.Logmsg, stream jsonrpc2.Stream, id *jsonrpc2.ID) {
	if id == nil {
		// need to use the number version of ID
		n, err := strconv.Atoi(l.ID)
		if err != nil {
			n = 0
		}
		nid := jsonrpc2.NewIntID(int64(n))
		id = &nid
	}
	var msg jsonrpc2.Message
	var err error
	switch l.Type {
	case parse.ClRequest:
		msg, err = jsonrpc2.NewCall(*id, l.Method, l.Body)
	case parse.SvResponse:
		msg, err = jsonrpc2.NewResponse(*id, l.Body, nil)
	case parse.ToServer:
		msg, err = jsonrpc2.NewNotification(l.Method, l.Body)
	default:
		log.Fatalf("sending %s", l.Type)
	}
	if err != nil {
		log.Fatal(err)
	}
	stream.Write(ctx, msg)
}

func respond(ctx context.Context, c *jsonrpc2.Call, stream jsonrpc2.Stream) {
	// c is a server request
	// pick out the id, and look for the response in msgs
	id := c.ID()
	idstr := fmt.Sprint(id)
	for _, l := range msgs {
		if l.ID == idstr && l.Type == parse.SvResponse {
			// check that the methods match?
			// need to send back the same ID we got.
			send(ctx, l, stream, &id)
			return
		}
	}
	log.Fatalf("no response found %q %+v %+v", c.Method(), c.ID(), c)
}

func findgopls() string {
	totry := [][]string{{"GOBIN", "/gopls"}, {"GOPATH", "/bin/gopls"}, {"HOME", "/go/bin/gopls"}}
	// looks in the places go install would install:
	// GOBIN, else GOPATH/bin, else HOME/go/bin
	ok := func(s string) bool {
		fd, err := os.Open(s)
		if err != nil {
			return false
		}
		fi, err := fd.Stat()
		if err != nil {
			return false
		}
		return fi.Mode()&0111 != 0
	}
	for _, t := range totry {
		g := os.Getenv(t[0])
		if g != "" && ok(g+t[1]) {
			gopls := g + t[1]
			log.Printf("using gopls at %s", gopls)
			return gopls
		}
	}
	log.Fatal("could not find gopls")
	return ""
}

func mimic(ctx context.Context) {
	log.Printf("mimic %d", len(msgs))
	if *command == "" {
		*command = findgopls()
	}
	cmd := exec.Command(*command, "-logfile", "/tmp/seen", "-rpc.trace")
	toServer, err := cmd.StdinPipe()
	if err != nil {
		log.Fatal(err)
	}
	fromServer, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	err = cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	conn := fakenet.NewConn("stdio", fromServer, toServer)
	stream := jsonrpc2.NewHeaderStream(conn)
	rchan := make(chan jsonrpc2.Message, 10) // do we need buffering?
	rdr := func() {
		for {
			msg, _, err := stream.Read(ctx)
			if err != nil {
				rchan <- nil // close it instead?
				return
			}
			rchan <- msg
		}
	}
	go rdr()
	// send as many as possible: all clrequests and toservers up to a clresponse
	// and loop
	seenids := make(map[string]bool) // id's that have been responded to:
big:
	for _, l := range msgs {
		switch l.Type {
		case parse.ToServer: // just send these as we get to them
			send(ctx, l, stream, nil)
		case parse.ClRequest:
			send(ctx, l, stream, nil) // for now, wait for a response, to make sure code is ok
			fallthrough
		case parse.ClResponse, parse.ReportErr: // don't go past these until they're received
			if seenids[l.ID] {
				break // onward, as it has been received already
			}
		done:
			for {
				msg := <-rchan
				if msg == nil {
					break big
				}
				// if it's svrequest, do something
				// if it's clresponse or reporterr, add to seenids, and if it
				// is l.id, break out of the loop, and continue the outer loop

				switch msg := msg.(type) {
				case *jsonrpc2.Call:
					if parse.FromServer(msg.Method()) {
						respond(ctx, msg, stream)
						continue done // still waiting
					}
				case *jsonrpc2.Response:
					id := fmt.Sprint(msg.ID())
					seenids[id] = true
					if id == l.ID {
						break done
					}
				}
			}
		case parse.SvRequest: // not ours to send
			continue
		case parse.SvResponse: // sent by us, if the request arrives
			continue
		case parse.ToClient: // we don't send these
			continue
		}
	}
}
