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

// Package parse provides functions to parse LSP logs.
// Fully processed logs are returned by ToRLog().
package parse

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"
)

// MsgType is the type of message.
type MsgType int

const (
	// ClRequest from client to server has method and id
	ClRequest MsgType = iota
	// ClResponse from server to client
	ClResponse
	// SvRequest from server to client, has method and id
	SvRequest
	// SvResponse from client to server
	SvResponse
	// ToServer notification has method, but no id
	ToServer
	// ToClient notification
	ToClient
	// ReportErr is an error message
	ReportErr // errors have method and id
)

// Logmsg is the type of a parsed log entry.
type Logmsg struct {
	Type    MsgType
	Method  string
	ID      string      // for requests/responses. Client and server request ids overlap
	Elapsed string      // for responses
	Hdr     string      // header. do we need to keep all these strings?
	Rest    string      // the unparsed result, with newlines or not
	Body    interface{} // the parsed result
}

// ReadLogs from a file. Most users should use ToRlog().
func ReadLogs(fname string) ([]*Logmsg, error) {
	byid := make(map[string]int)
	msgs := []*Logmsg{}
	fd, err := os.Open(fname)
	if err != nil {
		return nil, err
	}
	defer fd.Close()
	logrdr := bufio.NewScanner(fd)
	logrdr.Buffer(nil, 1<<25) //  a large buffer, for safety
	logrdr.Split(scanLogs)
	for i := 0; logrdr.Scan(); i++ {
		flds := strings.SplitN(logrdr.Text(), "\n", 2)
		if len(flds) == 1 {
			flds = append(flds, "") // for Errors
		}
		msg, err := parselog(flds[0], flds[1])
		if err != nil {
			return nil, fmt.Errorf("failed to parse %q: %v", logrdr.Text(), err)
		}
		switch msg.Type {
		case ClRequest, SvRequest:
			v, err := msg.unmarshal(Requests(msg.Method))
			if err != nil {
				return nil, fmt.Errorf("%v for %s, %T", err, msg.Method, Requests(msg.Method))
			}
			msg.Body = v
		case ClResponse, SvResponse:
			v, err := msg.doresponse()
			if err != nil {
				return nil, fmt.Errorf("%v %s", err, msg.Method)
			}
			msg.Body = v
		case ToServer, ToClient:
			v, err := msg.unmarshal(Notifs(msg.Method))
			if err != nil && Notifs(msg.Method) != nil {
				return nil, fmt.Errorf("%s/%T: %v", msg.Method, Notifs(msg.Method), err)
			}
			msg.Body = v
		case ReportErr:
			msg.Body = msg.ID // cause?
		}
		byid[msg.ID]++
		msgs = append(msgs, msg)
	}
	if err = logrdr.Err(); err != nil {
		return msgs, err
	}
	return msgs, nil
}

// parse a single log message, given first line, and the rest
func parselog(first, rest string) (*Logmsg, error) {
	if strings.HasPrefix(rest, "Params: ") {
		rest = rest[8:]
	} else if strings.HasPrefix(rest, "Result: ") {
		rest = rest[8:]
	}
	msg := &Logmsg{Hdr: first, Rest: rest}
	fixid := func(s string) string {
		// emacs does (n)., gopls does (n)'.
		s = strings.Trim(s, "()'.{)")
		return s
	}
	flds := strings.Fields(first)
	chk := func(s string, n int) bool { return strings.Contains(first, s) && len(flds) == n }
	// gopls and emacs differ in how they report elapsed time
	switch {
	case chk("Sending request", 9):
		msg.Type = ClRequest
		msg.Method = flds[6][1:]
		msg.ID = fixid(flds[8][:len(flds[8])-2])
	case chk("Received response", 11):
		msg.Type = ClResponse
		msg.Method = flds[6][1:]
		msg.ID = fixid(flds[8])
		msg.Elapsed = flds[10]
	case chk("Received request", 9):
		msg.Type = SvRequest
		msg.Method = flds[6][1:]
		msg.ID = fixid(flds[8])
	case chk("Sending response", 11), // gopls
		chk("Sending response", 13): // emacs
		msg.Type = SvResponse
		msg.Method = flds[6][1:]
		msg.ID = fixid(flds[8][:len(flds[8])-1])
		msg.Elapsed = flds[10]
	case chk("Sending notification", 7):
		msg.Type = ToServer
		msg.Method = strings.Trim(flds[6], ".'")
		if len(flds) == 9 {
			log.Printf("len=%d method=%s %q", len(flds), msg.Method, first)
		}
	case chk("Received notification", 7):
		msg.Type = ToClient
		msg.Method = flds[6][1 : len(flds[6])-2]
	case strings.HasPrefix(first, "[Error - "):
		msg.Type = ReportErr
		both := flds[5]
		idx := strings.Index(both, "#") // relies on ID.Number
		msg.Method = both[:idx]
		msg.ID = fixid(both[idx+1:])
		msg.Rest = strings.Join(flds[6:], " ")
	default:
		return nil, fmt.Errorf("surprise, first=%q with %d flds", first, len(flds))
	}
	return msg, nil
}

// unmarshal into a proposed type
func (l *Logmsg) unmarshal(p interface{}) (interface{}, error) {
	r := []byte(l.Rest)
	if err := json.Unmarshal(r, p); err != nil {
		// need general alternatives, but for now
		// if p is *[]foo and rest is {}, return an empty p (or *p?)
		// or, cheat:
		if l.Rest == "{}" {
			return nil, nil
		}
		return nil, err
	}
	return p, nil
}

func (l *Logmsg) doresponse() (interface{}, error) {
	for _, x := range Responses(l.Method) {
		v, err := l.unmarshal(x)
		if err == nil {
			return v, nil
		}
		if x == nil {
			return new(interface{}), nil
		}
	}
	// failure!
	rr := Responses(l.Method)
	for _, x := range rr {
		log.Printf("tried %T", x)
	}
	log.Fatalf("(%d) doresponse failed for %s %q", len(rr), l.Method, l.Rest)
	return nil, nil
}

// be a little forgiving in separating log records
var recSep = regexp.MustCompile("\n\n\n|\r\n\r\n\r\n")

// return offset of start of next record, contents of record, error
func scanLogs(b []byte, atEOF bool) (int, []byte, error) { //bufio.SplitFunc
	got := recSep.FindIndex(b)
	if got == nil {
		if atEOF && len(b) > 0 {
			return 0, nil, errors.New("malformed log: all logs should end with a separator")
		}
		return 0, nil, nil
	}
	return got[1], b[:got[0]], nil
}

// String returns a user-useful versin of a Direction
func (d MsgType) String() string {
	switch d {
	case ClRequest:
		return "clrequest"
	case ClResponse:
		return "clresponse"
	case SvRequest:
		return "svrequest"
	case SvResponse:
		return "svresponse"
	case ToServer:
		return "toserver"
	case ToClient:
		return "toclient"
	case ReportErr:
		return "reporterr"
	}
	return fmt.Sprintf("dirname: %d unknown", d)
}
