// 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 local provides access to a local program.
package local // import "golang.org/x/debug/local"

import (
	"golang.org/x/debug"
	"golang.org/x/debug/server"
	"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.
type Program struct {
	s *server.Server
}

// New creates a new program from the specified file.
// The program can then be started by the Run method.
func New(textFile string) (*Program, error) {
	s, err := server.New(textFile)
	return &Program{s: s}, err
}

func (p *Program) Open(name string, mode string) (debug.File, error) {
	req := protocol.OpenRequest{
		Name: name,
		Mode: mode,
	}
	var resp protocol.OpenResponse
	err := p.s.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.s.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.s.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.s.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.s.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.s.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.s.DeleteBreakpoints(&req, &resp)
}

func (p *Program) Eval(expr string) ([]string, error) {
	req := protocol.EvalRequest{
		Expr: expr,
	}
	var resp protocol.EvalResponse
	err := p.s.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.s.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.s.Frames(&req, &resp)
	return resp.Frames, err
}

func (p *Program) Goroutines() ([]*debug.Goroutine, error) {
	req := protocol.GoroutinesRequest{}
	var resp protocol.GoroutinesResponse
	err := p.s.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.s.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.s.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.s.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.s.ReadAt(&req, &resp)
	return copy(p, resp.Data), err
}

func (f *File) WriteAt(p []byte, offset int64) (int, error) {
	panic("unimplemented")
}

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