// Copyright 2014 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 remote provides remote access to a debugproxy server.
package remote // import "golang.org/x/debug/remote"

import (
	"fmt"
	"io"
	"net/rpc"
	"os"
	"os/exec"

	"golang.org/x/debug"
	"golang.org/x/debug/server/protocol"
)

var _ debug.Program = (*Program)(nil)
var _ debug.File = (*File)(nil)

// Program implements the debug.Program interface.
// Through that interface it provides access to a program being
// debugged on a possibly remote machine by communicating
// with a debugproxy adjacent to the target program.
type Program struct {
	client *rpc.Client
}

// DebugproxyCmd is the path to the debugproxy command. It is a variable in case
// the default value, "debugproxy", is not in the $PATH.
var DebugproxyCmd = "debugproxy"

// New connects to the specified host using SSH, starts DebugproxyCmd
// there, and creates a new program from the specified file.
// The program can then be started by the Run method.
func New(host string, textFile string) (*Program, error) {
	// TODO: add args.
	cmdStrs := []string{"/usr/bin/ssh", host, DebugproxyCmd, "-text", textFile}
	if host == "localhost" {
		cmdStrs = cmdStrs[2:]
	}
	cmd := exec.Command(cmdStrs[0], cmdStrs[1:]...)
	stdin, toStdin, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	fromStdout, stdout, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = os.Stderr // Stderr from proxy appears on our stderr.
	err = cmd.Start()
	if err != nil {
		return nil, err
	}
	stdout.Close()
	if msg, err := readLine(fromStdout); err != nil {
		return nil, err
	} else if msg != "OK" {
		// Communication error.
		return nil, fmt.Errorf("unrecognized message %q", msg)
	}
	program := &Program{
		client: rpc.NewClient(&rwc{
			ssh: cmd,
			r:   fromStdout,
			w:   toStdin,
		}),
	}
	return program, nil
}

// readLine reads one line of text from the reader. It does no buffering.
// The trailing newline is read but not returned.
func readLine(r io.Reader) (string, error) {
	b := make([]byte, 0, 10)
	var c [1]byte
	for {
		_, err := io.ReadFull(r, c[:])
		if err != nil {
			return "", err
		}
		if c[0] == '\n' {
			break
		}
		b = append(b, c[0])
	}
	return string(b), nil
}

// rwc creates a single io.ReadWriteCloser from a read side and a write side.
// It also holds the command object so we can wait for SSH to complete.
// It allows us to do RPC over an SSH connection.
type rwc struct {
	ssh *exec.Cmd
	r   *os.File
	w   *os.File
}

func (rwc *rwc) Read(p []byte) (int, error) {
	return rwc.r.Read(p)
}

func (rwc *rwc) Write(p []byte) (int, error) {
	return rwc.w.Write(p)
}

func (rwc *rwc) Close() error {
	rerr := rwc.r.Close()
	werr := rwc.w.Close()
	cerr := rwc.ssh.Wait()
	if cerr != nil {
		// Wait exit status is most important.
		return cerr
	}
	if rerr != nil {
		return rerr
	}
	return werr
}

func (p *Program) Open(name string, mode string) (debug.File, error) {
	req := protocol.OpenRequest{
		Name: name,
		Mode: mode,
	}
	var resp protocol.OpenResponse
	err := p.client.Call("Server.Open", &req, &resp)
	if err != nil {
		return nil, err
	}
	f := &File{
		prog: p,
		fd:   resp.FD,
	}
	return f, nil
}

func (p *Program) Run(args ...string) (debug.Status, error) {
	req := protocol.RunRequest{args}
	var resp protocol.RunResponse
	err := p.client.Call("Server.Run", &req, &resp)
	if err != nil {
		return debug.Status{}, err
	}
	return resp.Status, nil
}

func (p *Program) Stop() (debug.Status, error) {
	panic("unimplemented")
}

func (p *Program) Resume() (debug.Status, error) {
	req := protocol.ResumeRequest{}
	var resp protocol.ResumeResponse
	err := p.client.Call("Server.Resume", &req, &resp)
	if err != nil {
		return debug.Status{}, err
	}
	return resp.Status, nil
}

func (p *Program) Kill() (debug.Status, error) {
	panic("unimplemented")
}

func (p *Program) Breakpoint(address uint64) ([]uint64, error) {
	req := protocol.BreakpointRequest{
		Address: address,
	}
	var resp protocol.BreakpointResponse
	err := p.client.Call("Server.Breakpoint", &req, &resp)
	return resp.PCs, err
}

func (p *Program) BreakpointAtFunction(name string) ([]uint64, error) {
	req := protocol.BreakpointAtFunctionRequest{
		Function: name,
	}
	var resp protocol.BreakpointResponse
	err := p.client.Call("Server.BreakpointAtFunction", &req, &resp)
	return resp.PCs, err
}

func (p *Program) BreakpointAtLine(file string, line uint64) ([]uint64, error) {
	req := protocol.BreakpointAtLineRequest{
		File: file,
		Line: line,
	}
	var resp protocol.BreakpointResponse
	err := p.client.Call("Server.BreakpointAtLine", &req, &resp)
	return resp.PCs, err
}

func (p *Program) DeleteBreakpoints(pcs []uint64) error {
	req := protocol.DeleteBreakpointsRequest{PCs: pcs}
	var resp protocol.DeleteBreakpointsResponse
	return p.client.Call("Server.DeleteBreakpoints", &req, &resp)
}

func (p *Program) Eval(expr string) ([]string, error) {
	req := protocol.EvalRequest{
		Expr: expr,
	}
	var resp protocol.EvalResponse
	err := p.client.Call("Server.Eval", &req, &resp)
	return resp.Result, err
}

func (p *Program) Evaluate(e string) (debug.Value, error) {
	req := protocol.EvaluateRequest{
		Expression: e,
	}
	var resp protocol.EvaluateResponse
	err := p.client.Call("Server.Evaluate", &req, &resp)
	return resp.Result, err
}

func (p *Program) Frames(count int) ([]debug.Frame, error) {
	req := protocol.FramesRequest{
		Count: count,
	}
	var resp protocol.FramesResponse
	err := p.client.Call("Server.Frames", &req, &resp)
	return resp.Frames, err
}

func (p *Program) Goroutines() ([]*debug.Goroutine, error) {
	req := protocol.GoroutinesRequest{}
	var resp protocol.GoroutinesResponse
	err := p.client.Call("Server.Goroutines", &req, &resp)
	return resp.Goroutines, err
}

func (p *Program) VarByName(name string) (debug.Var, error) {
	req := protocol.VarByNameRequest{Name: name}
	var resp protocol.VarByNameResponse
	err := p.client.Call("Server.VarByName", &req, &resp)
	return resp.Var, err
}

func (p *Program) Value(v debug.Var) (debug.Value, error) {
	req := protocol.ValueRequest{Var: v}
	var resp protocol.ValueResponse
	err := p.client.Call("Server.Value", &req, &resp)
	return resp.Value, err
}

func (p *Program) MapElement(m debug.Map, index uint64) (debug.Var, debug.Var, error) {
	req := protocol.MapElementRequest{Map: m, Index: index}
	var resp protocol.MapElementResponse
	err := p.client.Call("Server.MapElement", &req, &resp)
	return resp.Key, resp.Value, err
}

// File implements the debug.File interface, providing access
// to file-like resources associated with the target program.
type File struct {
	prog *Program // The Program associated with the file.
	fd   int      // File descriptor.
}

func (f *File) ReadAt(p []byte, offset int64) (int, error) {
	req := protocol.ReadAtRequest{
		FD:     f.fd,
		Len:    len(p),
		Offset: offset,
	}
	var resp protocol.ReadAtResponse
	err := f.prog.client.Call("Server.ReadAt", &req, &resp)
	return copy(p, resp.Data), err
}

func (f *File) WriteAt(p []byte, offset int64) (int, error) {
	req := protocol.WriteAtRequest{
		FD:     f.fd,
		Data:   p,
		Offset: offset,
	}
	var resp protocol.WriteAtResponse
	err := f.prog.client.Call("Server.WriteAt", &req, &resp)
	return resp.Len, err
}

func (f *File) Close() error {
	req := protocol.CloseRequest{
		FD: f.fd,
	}
	var resp protocol.CloseResponse
	err := f.prog.client.Call("Server.Close", &req, &resp)
	return err
}
