// 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 client provides remote access to an ogle proxy.
package client // import "golang.org/x/debug/ogle/program/client"

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

	"golang.org/x/debug/ogle/program"
	"golang.org/x/debug/ogle/program/proxyrpc"
)

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

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

// New connects to the specified host using SSH, starts an ogle proxy
// 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, OgleproxyCmd, "-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()
	// Read back one line. It must start "OGLE" and we hope says "OK".
	msg, err := readLine(fromStdout)
	if err != nil {
		return nil, err
	}
	switch msg {
	case "OGLE BAD":
		// Error is on next line.
		msg, err = readLine(fromStdout)
		if err == nil {
			err = errors.New(msg)
		}
		return nil, err
	case "OGLE OK":
	default:
		// 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
}

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

func (p *Program) Open(name string, mode string) (program.File, error) {
	req := proxyrpc.OpenRequest{
		Name: name,
		Mode: mode,
	}
	var resp proxyrpc.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) (program.Status, error) {
	req := proxyrpc.RunRequest{args}
	var resp proxyrpc.RunResponse
	err := p.client.Call("Server.Run", &req, &resp)
	if err != nil {
		return program.Status{}, err
	}
	return resp.Status, nil
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File implements the program.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 := proxyrpc.ReadAtRequest{
		FD:     f.fd,
		Len:    len(p),
		Offset: offset,
	}
	var resp proxyrpc.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 := proxyrpc.WriteAtRequest{
		FD:     f.fd,
		Data:   p,
		Offset: offset,
	}
	var resp proxyrpc.WriteAtResponse
	err := f.prog.client.Call("Server.WriteAt", &req, &resp)
	return resp.Len, err
}

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