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

import (
	"bytes"
	"fmt"
	"math"

	"code.google.com/p/ogle/arch"
	"code.google.com/p/ogle/debug/dwarf"
)

// Routines to print a value using DWARF type descriptions.
// TODO: Does this deserve its own package? It has no dependencies on Server.

// A Printer pretty-prints a values in the target address space.
// It can be reused after each printing operation to avoid unnecessary
// allocations. However, it is not safe for concurrent access.
type Printer struct {
	err      error // Sticky error value.
	peeker   Peeker
	dwarf    *dwarf.Data
	arch     *arch.Architecture
	printBuf bytes.Buffer     // Accumulates the output.
	tmp      []byte           // Temporary used for I/O.
	visited  map[uintptr]bool // Prevents looping on cyclic data.
	// The cache stores a local copy of part of the address space.
	// Saves I/O overhead when scanning map buckets by letting
	// printValueAt use the contents of already-read bucket data.
	cache    []byte  // Already-read data.
	cacheOff uintptr // Starting address of cache.
}

// printf prints to printBuf, unless there has been an error.
func (p *Printer) printf(format string, args ...interface{}) {
	if p.err != nil {
		return
	}
	fmt.Fprintf(&p.printBuf, format, args...)
}

// errorf sets the sticky error for the printer, if not already set.
func (p *Printer) errorf(format string, args ...interface{}) {
	if p.err != nil {
		return
	}
	p.err = fmt.Errorf(format, args...)
}

// ok checks the error. If it is the first non-nil error encountered,
// it is printed to printBuf, parenthesized for discrimination, and remembered.
func (p *Printer) ok(err error) bool {
	if p.err == nil && err != nil {
		p.printf("(%s)", err)
		p.err = err
	}
	return p.err == nil
}

// peek reads len bytes at offset, leaving p.tmp with the data and sized appropriately.
// It uses the cache if the request is within it.
func (p *Printer) peek(offset uintptr, length int64) bool {
	p.tmp = p.tmp[:length]
	if p.cacheOff <= offset && offset+uintptr(length) <= p.cacheOff+uintptr(len(p.cache)) {
		copy(p.tmp, p.cache[offset-p.cacheOff:])
		return true
	}
	return p.ok(p.peeker.peek(offset, p.tmp))
}

// setCache initializes the cache to contain the contents of the
// address space at the specified offset.
func (p *Printer) setCache(offset, length uintptr) bool {
	if uintptr(cap(p.cache)) >= length {
		p.cache = p.cache[:length]
	} else {
		p.cache = make([]byte, length)
	}
	p.cacheOff = offset
	ok := p.ok(p.peeker.peek(offset, p.cache))
	if !ok {
		p.resetCache()
	}
	return ok
}

func (p *Printer) resetCache() {
	p.cache = p.cache[0:0]
	p.cacheOff = 0
}

// Peeker is like a read that probes the remote address space.
type Peeker interface {
	peek(offset uintptr, buf []byte) error
}

// NewPrinter returns a printer that can use the Peeker to access and print
// values of the specified architecture described by the provided DWARF data.
func NewPrinter(arch *arch.Architecture, dwarf *dwarf.Data, peeker Peeker) *Printer {
	return &Printer{
		peeker:  peeker,
		arch:    arch,
		dwarf:   dwarf,
		visited: make(map[uintptr]bool),
		tmp:     make([]byte, 100), // Enough for a largish string.
	}
}

// reset resets the Printer. It must be called before starting a new
// printing operation.
func (p *Printer) reset() {
	p.err = nil
	p.printBuf.Reset()
	p.resetCache()
	// Just wipe the map rather than reallocating. It's almost always tiny.
	for k := range p.visited {
		delete(p.visited, k)
	}
}

// Sprint returns the pretty-printed value of the item with the given name, such as "main.global".
func (p *Printer) Sprint(name string) (string, error) {
	entry, err := p.dwarf.LookupEntry(name)
	if err != nil {
		return "", err
	}
	p.reset()
	switch entry.Tag {
	case dwarf.TagVariable: // TODO: What other entries have global location attributes?
		addr := uintptr(0)
		iface := entry.Val(dwarf.AttrLocation)
		if iface != nil {
			addr = p.decodeLocation(iface.([]byte))
		}
		p.printEntryValueAt(entry, addr)
	default:
		p.errorf("unrecognized entry type %s", entry.Tag)
	}
	return p.printBuf.String(), p.err
}

// Figure 24 of DWARF v4.
const (
	locationAddr = 0x03
)

// decodeLocation decodes the dwarf data describing an address.
func (p *Printer) decodeLocation(data []byte) uintptr {
	switch data[0] {
	case locationAddr:
		return uintptr(p.arch.Uintptr(data[1:]))
	default:
		p.errorf("unimplemented location type %#x", data[0])
	}
	return 0
}

// SprintEntry returns the pretty-printed value of the item with the specified DWARF Entry and address.
func (p *Printer) SprintEntry(entry *dwarf.Entry, addr uintptr) (string, error) {
	p.reset()
	p.printEntryValueAt(entry, addr)
	return p.printBuf.String(), p.err
}

// printEntryValueAt pretty-prints the data at the specified addresss
// using the type information in the Entry.
func (p *Printer) printEntryValueAt(entry *dwarf.Entry, addr uintptr) {
	if addr == 0 {
		p.printf("<nil>")
		return
	}
	switch entry.Tag {
	case dwarf.TagVariable, dwarf.TagFormalParameter:
		// OK
	default:
		p.errorf("unrecognized entry type %s", entry.Tag)
		return
	}
	iface := entry.Val(dwarf.AttrType)
	if iface == nil {
		p.errorf("no type")
		return
	}
	typ, err := p.dwarf.Type(iface.(dwarf.Offset))
	if err != nil {
		p.errorf("type lookup: %v", err)
		return
	}
	p.printValueAt(typ, addr)
}

// printValueAt pretty-prints the data at the specified addresss
// using the provided type information.
func (p *Printer) printValueAt(typ dwarf.Type, addr uintptr) {
	// Make sure we don't recur forever.
	if p.visited[addr] {
		p.printf("(@%x...)", addr)
		return
	}
	switch typ := typ.(type) {
	case *dwarf.BoolType:
		if typ.ByteSize != 1 {
			p.errorf("unrecognized bool size %d", typ.ByteSize)
			return
		}
		if p.peek(addr, 1) {
			p.printf("%t", p.tmp[0] != 0)
		}
	case *dwarf.PtrType:
		// This type doesn't define the ByteSize attribute.
		if p.peek(addr, int64(p.arch.PointerSize)) {
			p.printf("%#x", p.arch.Uintptr(p.tmp))
		}
	case *dwarf.IntType:
		// Sad we can't tell a rune from an int32.
		if p.peek(addr, typ.ByteSize) {
			p.printf("%d", p.arch.IntN(p.tmp))
		}
	case *dwarf.UintType:
		if p.peek(addr, typ.ByteSize) {
			p.printf("%d", p.arch.UintN(p.tmp))
		}
	case *dwarf.FloatType:
		if !p.peek(addr, typ.ByteSize) {
			return
		}
		switch typ.ByteSize {
		case 4:
			p.printf("%g", math.Float32frombits(uint32(p.arch.UintN(p.tmp))))
		case 8:
			p.printf("%g", math.Float64frombits(p.arch.UintN(p.tmp)))
		default:
			p.errorf("unrecognized float size %d", typ.ByteSize)
		}
	case *dwarf.ComplexType:
		if !p.peek(addr, typ.ByteSize) {
			return
		}
		switch typ.ByteSize {
		case 8:
			r := math.Float32frombits(uint32(p.arch.UintN(p.tmp[:4])))
			i := math.Float32frombits(uint32(p.arch.UintN(p.tmp[4:8])))
			p.printf("%g", complex(r, i))
		case 16:
			r := math.Float64frombits(p.arch.UintN(p.tmp[:8]))
			i := math.Float64frombits(p.arch.UintN(p.tmp[8:16]))
			p.printf("%g", complex(r, i))
		default:
			p.errorf("unrecognized complex size %d", typ.ByteSize)
		}
	case *dwarf.StructType:
		p.visited[addr] = true
		if typ.Kind != "struct" {
			// Could be "class" or "union".
			p.errorf("can't handle struct type %s", typ.Kind)
			return
		}
		p.printf("%s {", typ.String())
		for i, field := range typ.Field {
			if i != 0 {
				p.printf(", ")
			}
			p.printValueAt(field.Type, addr+uintptr(field.ByteOffset))
		}
		p.printf("}")
	case *dwarf.ArrayType:
		p.printArrayAt(typ, addr)
	case *dwarf.MapType:
		p.visited[addr] = true
		p.printMapAt(typ, addr)
	case *dwarf.SliceType:
		p.visited[addr] = true
		p.printSliceAt(typ, addr)
	case *dwarf.StringType:
		p.printStringAt(typ, addr)
	case *dwarf.TypedefType:
		p.errorf("unimplemented typedef type %T %v", typ, typ)
	default:
		// TODO: chan func interface
		p.errorf("unimplemented type %v", typ)
	}
}

func (p *Printer) printArrayAt(typ *dwarf.ArrayType, addr uintptr) {
	elemType := typ.Type
	length := typ.Count
	stride := typ.StrideBitSize
	if stride > 0 {
		stride /= 8
	} else {
		stride = p.sizeof(elemType)
		if stride < 0 {
			p.errorf("array elements have no known size")
		}
	}
	p.printf("%s{", typ)
	n := length
	if n > 100 {
		n = 100 // TODO: Have a way to control this?
	}
	for i := int64(0); i < n; i++ {
		if i != 0 {
			p.printf(", ")
		}
		p.printValueAt(elemType, addr)
		addr += uintptr(stride) // TODO: Alignment and padding - not given by Type
	}
	if n < length {
		p.printf(", ...")
	}
	p.printf("}")
}

// mapDesc collects the information necessary to print a map.
type mapDesc struct {
	typ        *dwarf.MapType
	count      int
	numBuckets int
	keySize    uintptr
	elemSize   uintptr
	bucketSize uintptr
}

func (p *Printer) printMapAt(typ *dwarf.MapType, addr uintptr) {
	// Maps are pointers to a struct type.
	structType := typ.Type.(*dwarf.PtrType).Type.(*dwarf.StructType)
	// Indirect through the pointer.
	if !p.peek(addr, int64(p.arch.PointerSize)) {
		return
	}
	addr = uintptr(p.arch.Uintptr(p.tmp[:p.arch.PointerSize]))
	// Now read the struct.
	if !p.peek(addr, structType.ByteSize) {
		return
	}
	// From runtime/hashmap.go; We need to walk the map data structure.
	// Load the struct, then iterate over the buckets.
	// uintgo count (occupancy).
	offset := int(structType.Field[0].ByteOffset)
	count := int(p.arch.Uint(p.tmp[offset : offset+p.arch.IntSize]))
	// uint8 Log2 of number of buckets.
	b := uint(p.tmp[structType.Field[3].ByteOffset])
	// uint8 key size in bytes.
	keySize := uintptr(p.tmp[structType.Field[4].ByteOffset])
	// uint8 element size in bytes.
	elemSize := uintptr(p.tmp[structType.Field[5].ByteOffset])
	// uint16 bucket size in bytes.
	bucketSize := uintptr(p.arch.Uint16(p.tmp[structType.Field[6].ByteOffset:]))
	// pointer to buckets
	offset = int(structType.Field[7].ByteOffset)
	bucketPtr := uintptr(p.arch.Uintptr(p.tmp[offset : offset+p.arch.PointerSize]))
	// pointer to old buckets.
	offset = int(structType.Field[8].ByteOffset)
	oldBucketPtr := uintptr(p.arch.Uintptr(p.tmp[offset : offset+p.arch.PointerSize]))
	// Ready to print.
	p.printf("%s{", typ)
	desc := mapDesc{
		typ:        typ,
		count:      count,
		numBuckets: 1 << b,
		keySize:    keySize,
		elemSize:   elemSize,
		bucketSize: bucketSize,
	}
	p.printMapBucketsAt(desc, bucketPtr)
	p.printMapBucketsAt(desc, oldBucketPtr)
	p.printf("}")
}

// Map bucket layout from runtime/hashmap.go
const (
	bucketCnt  = 8
	minTopHash = 4
)

func (p *Printer) printMapBucketsAt(desc mapDesc, addr uintptr) {
	if addr == 0 {
		return
	}
	for i := 0; desc.count > 0 && i < desc.numBuckets; i++ {
		// After the header, the bucket struct has an array of keys followed by an array of elements.
		// Load this bucket struct into p's cache and initialize "pointers" to the key and value slices.
		if !p.setCache(addr, desc.bucketSize) {
			return
		}
		keyAddr := addr + bucketCnt + uintptr(p.arch.PointerSize)
		elemAddr := keyAddr + bucketCnt*desc.keySize
		addr += desc.bucketSize // Advance to next bucket; keyAddr and elemAddr are all we need now.
		// tophash uint8 [bucketCnt] tells us which buckets are occupied.
		// p.cache has the data but calls to printValueAt below may overwrite the
		// cache, so grab a copy of the relevant data.
		var tophash [bucketCnt]byte
		if copy(tophash[:], p.cache) != bucketCnt {
			p.errorf("bad count copying hash flags")
			return
		}
		overflow := uintptr(p.arch.Uintptr(p.cache[bucketCnt : bucketCnt+p.arch.PointerSize]))
		for j := 0; desc.count > 0 && j < bucketCnt; j++ {
			if tophash[j] >= minTopHash {
				p.printValueAt(desc.typ.KeyType, keyAddr)
				p.printf(":")
				p.printValueAt(desc.typ.ElemType, elemAddr)
				desc.count--
				if desc.count > 0 {
					p.printf(", ")
				}
			}
			keyAddr += desc.keySize
			elemAddr += desc.elemSize
		}
		// pointer to overflow bucket, if any.
		p.printMapBucketsAt(desc, overflow)
	}
}

func (p *Printer) printSliceAt(typ *dwarf.SliceType, addr uintptr) {
	// Slices look like a struct with fields array *elemtype, len uint32/64, cap uint32/64.
	// BUG: Slice header appears to have fields with ByteSize == 0
	if !p.peek(addr, typ.ByteSize) {
		p.errorf("slice header has no known size")
		return
	}
	lo := typ.Field[0].ByteOffset
	hi := lo + int64(p.arch.PointerSize)
	ptr := uintptr(p.arch.UintN(p.tmp[lo:hi]))
	lo = typ.Field[1].ByteOffset
	hi = lo + int64(p.arch.IntSize)
	length := p.arch.UintN(p.tmp[lo:hi])
	// Capacity is unused here.
	elemType := typ.ElemType
	size := p.sizeof(elemType)
	if size < 0 {
		return
	}
	p.printf("%s{", typ)
	for i := uint64(0); i < length; i++ {
		if i != 0 {
			p.printf(", ")
		}
		p.printValueAt(elemType, ptr)
		ptr += uintptr(size) // TODO: Alignment and padding - not given by Type
	}
	p.printf("}")
}

func (p *Printer) printStringAt(typ *dwarf.StringType, addr uintptr) {
	// Strings look like a struct with fields array *elemtype, len uint64.
	// TODO uint64 on 386 too?
	if !p.peek(addr, typ.ByteSize) {
		p.errorf("string header has no known size")
		return
	}
	// BUG: String header appears to have fields with ByteSize == 0
	lo := typ.Field[0].ByteOffset
	hi := lo + int64(p.arch.PointerSize)
	ptr := p.arch.UintN(p.tmp[lo:hi])
	lo = typ.Field[1].ByteOffset
	hi = lo + int64(p.arch.IntSize) // TODO?
	length := p.arch.UintN(p.tmp[lo:hi])
	if length > uint64(cap(p.tmp)) {
		if p.peek(uintptr(ptr), int64(cap(p.tmp))) {
			p.printf("%q...", p.tmp)
		}
	} else {
		if p.peek(uintptr(ptr), int64(length)) {
			p.printf("%q", p.tmp[:length])
		}
	}
}

// sizeof returns the byte size of the type. It returns -1 if no size can be found.
func (p *Printer) sizeof(typ dwarf.Type) int64 {
	size := typ.Size() // Will be -1 if ByteSize is not set.
	if size >= 0 {
		return size
	}
	switch typ.(type) {
	case *dwarf.PtrType:
		// This is the only one we know of, but more may arise.
		return int64(p.arch.PointerSize)
	}
	p.errorf("unknown size for %s", typ)
	return -1
}
