// Copyright 2009 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 ogle

import (
	"debug/proc";
	"fmt";
	"os";
)

/*
 * Hooks and events
 */

// An EventHandler is a function that takes an event and returns a
// response to that event and possibly an error.  If an event handler
// returns an error, the process stops and no other handlers for that
// event are executed.
type EventHandler func(e Event) (EventAction, os.Error)

// An EventAction is an event handler's response to an event.  If all
// of an event's handlers execute without returning errors, their
// results are combined as follows: If any handler returned
// EAContinue, then the process resumes (without returning from
// WaitStop); otherwise, if any handler returned EAStop, the process
// remains stopped; otherwise, if all handlers returned EADefault, the
// process resumes.  A handler may return EARemoveSelf bit-wise or'd
// with any other action to indicate that the handler should be
// removed from the hook.
type EventAction int

const (
	EARemoveSelf	EventAction	= 0x100;
	EADefault	EventAction	= iota;
	EAStop;
	EAContinue;
)

// A EventHook allows event handlers to be added and removed.
type EventHook interface {
	AddHandler(EventHandler);
	RemoveHandler(EventHandler);
	NumHandler() int;
	handle(e Event) (EventAction, os.Error);
	String() string;
}

// EventHook is almost, but not quite, suitable for user-defined
// events.  If we want user-defined events, make EventHook a struct,
// special-case adding and removing handlers in breakpoint hooks, and
// provide a public interface for posting events to hooks.

type Event interface {
	Process() *Process;
	Goroutine() *Goroutine;
	String() string;
}

type commonHook struct {
	// Head of handler chain
	head	*handler;
	// Number of non-internal handlers
	len	int;
}

type handler struct {
	eh	EventHandler;
	// True if this handler must be run before user-defined
	// handlers in order to ensure correctness.
	internal	bool;
	// True if this handler has been removed from the chain.
	removed	bool;
	next	*handler;
}

func (h *commonHook) AddHandler(eh EventHandler) {
	h.addHandler(eh, false)
}

func (h *commonHook) addHandler(eh EventHandler, internal bool) {
	// Ensure uniqueness of handlers
	h.RemoveHandler(eh);

	if !internal {
		h.len++
	}
	// Add internal handlers to the beginning
	if internal || h.head == nil {
		h.head = &handler{eh, internal, false, h.head};
		return;
	}
	// Add handler after internal handlers
	// TODO(austin) This should probably go on the end instead
	prev := h.head;
	for prev.next != nil && prev.internal {
		prev = prev.next
	}
	prev.next = &handler{eh, internal, false, prev.next};
}

func (h *commonHook) RemoveHandler(eh EventHandler) {
	plink := &h.head;
	for l := *plink; l != nil; plink, l = &l.next, l.next {
		if l.eh == eh {
			if !l.internal {
				h.len--
			}
			l.removed = true;
			*plink = l.next;
			break;
		}
	}
}

func (h *commonHook) NumHandler() int	{ return h.len }

func (h *commonHook) handle(e Event) (EventAction, os.Error) {
	action := EADefault;
	plink := &h.head;
	for l := *plink; l != nil; plink, l = &l.next, l.next {
		if l.removed {
			continue
		}
		a, err := l.eh(e);
		if a&EARemoveSelf == EARemoveSelf {
			if !l.internal {
				h.len--
			}
			l.removed = true;
			*plink = l.next;
			a &^= EARemoveSelf;
		}
		if err != nil {
			return EAStop, err
		}
		if a > action {
			action = a
		}
	}
	return action, nil;
}

type commonEvent struct {
	// The process of this event
	p	*Process;
	// The goroutine of this event.
	t	*Goroutine;
}

func (e *commonEvent) Process() *Process	{ return e.p }

func (e *commonEvent) Goroutine() *Goroutine	{ return e.t }

/*
 * Standard event handlers
 */

// EventPrint is a standard event handler that prints events as they
// occur.  It will not cause the process to stop.
func EventPrint(ev Event) (EventAction, os.Error) {
	// TODO(austin) Include process name here?
	fmt.Fprintf(os.Stderr, "*** %v\n", ev.String());
	return EADefault, nil;
}

// EventStop is a standard event handler that causes the process to stop.
func EventStop(ev Event) (EventAction, os.Error) {
	return EAStop, nil
}

/*
 * Breakpoints
 */

type breakpointHook struct {
	commonHook;
	p	*Process;
	pc	proc.Word;
}

// A Breakpoint event occurs when a process reaches a particular
// program counter.  When this event is handled, the current goroutine
// will be the goroutine that reached the program counter.
type Breakpoint struct {
	commonEvent;
	osThread	proc.Thread;
	pc		proc.Word;
}

func (h *breakpointHook) AddHandler(eh EventHandler) {
	h.addHandler(eh, false)
}

func (h *breakpointHook) addHandler(eh EventHandler, internal bool) {
	// We register breakpoint events lazily to avoid holding
	// references to breakpoints without handlers.  Be sure to use
	// the "canonical" breakpoint if there is one.
	if cur, ok := h.p.breakpointHooks[h.pc]; ok {
		h = cur
	}
	oldhead := h.head;
	h.commonHook.addHandler(eh, internal);
	if oldhead == nil && h.head != nil {
		h.p.proc.AddBreakpoint(h.pc);
		h.p.breakpointHooks[h.pc] = h;
	}
}

func (h *breakpointHook) RemoveHandler(eh EventHandler) {
	oldhead := h.head;
	h.commonHook.RemoveHandler(eh);
	if oldhead != nil && h.head == nil {
		h.p.proc.RemoveBreakpoint(h.pc);
		h.p.breakpointHooks[h.pc] = nil, false;
	}
}

func (h *breakpointHook) String() string {
	// TODO(austin) Include process name?
	// TODO(austin) Use line:pc or at least sym+%#x
	return fmt.Sprintf("breakpoint at %#x", h.pc)
}

func (b *Breakpoint) PC() proc.Word	{ return b.pc }

func (b *Breakpoint) String() string {
	// TODO(austin) Include process name and goroutine
	// TODO(austin) Use line:pc or at least sym+%#x
	return fmt.Sprintf("breakpoint at %#x", b.pc)
}

/*
 * Goroutine create/exit
 */

type goroutineCreateHook struct {
	commonHook;
}

func (h *goroutineCreateHook) String() string	{ return "goroutine create" }

// A GoroutineCreate event occurs when a process creates a new
// goroutine.  When this event is handled, the current goroutine will
// be the newly created goroutine.
type GoroutineCreate struct {
	commonEvent;
	parent	*Goroutine;
}

// Parent returns the goroutine that created this goroutine.  May be
// nil if this event is the creation of the first goroutine.
func (e *GoroutineCreate) Parent() *Goroutine	{ return e.parent }

func (e *GoroutineCreate) String() string {
	// TODO(austin) Include process name
	if e.parent == nil {
		return fmt.Sprintf("%v created", e.t)
	}
	return fmt.Sprintf("%v created by %v", e.t, e.parent);
}

type goroutineExitHook struct {
	commonHook;
}

func (h *goroutineExitHook) String() string	{ return "goroutine exit" }

// A GoroutineExit event occurs when a Go goroutine exits.
type GoroutineExit struct {
	commonEvent;
}

func (e *GoroutineExit) String() string {
	// TODO(austin) Include process name
	//return fmt.Sprintf("%v exited", e.t);
	// For debugging purposes
	return fmt.Sprintf("goroutine %#x exited", e.t.g.addr().base)
}
