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

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"sync"
	"time"
	"unicode/utf8"
)

// When sandbox time begins.
var epoch = time.Unix(1257894000, 0)

// Recorder records the standard and error outputs of a sandbox program
// (comprised of playback headers) and converts it to a sequence of Events.
// It sanitizes each Event's Message to ensure it is valid UTF-8.
//
// Playground programs precede all their writes with a header (described
// below) that describes the time the write occurred (in playground time) and
// the length of the data that will be written. If a non-header is
// encountered where a header is expected, the output is scanned for the next
// header and the intervening text string is added to the sequence an event
// occurring at the same time as the preceding event.
//
// A playback header has this structure:
// 	4 bytes: "\x00\x00PB", a magic header
// 	8 bytes: big-endian int64, unix time in nanoseconds
// 	4 bytes: big-endian int32, length of the next write
//
type Recorder struct {
	mu     sync.Mutex
	writes []recorderWrite
}

type recorderWrite struct {
	b    []byte
	kind string
}

func (r *Recorder) Stdout() io.Writer { return recorderWriter{r, "stdout"} }
func (r *Recorder) Stderr() io.Writer { return recorderWriter{r, "stderr"} }

type recorderWriter struct {
	r    *Recorder
	kind string
}

func (w recorderWriter) Write(b []byte) (n int, err error) {
	w.r.mu.Lock()
	defer w.r.mu.Unlock()

	// Append this write to the previous one if it has the same kind.
	if len(w.r.writes) > 0 {
		prev := &w.r.writes[len(w.r.writes)-1]
		if prev.kind == w.kind {
			prev.b = append(prev.b, b...)
			return len(b), nil
		}
	}

	// Otherwise, append a new write.
	w.r.writes = append(w.r.writes, recorderWrite{
		append([]byte(nil), b...), w.kind,
	})

	return len(b), nil
}

type Event struct {
	Message string
	Kind    string        // "stdout" or "stderr"
	Delay   time.Duration // time to wait before printing Message
}

func (r *Recorder) Events() ([]Event, error) {
	r.mu.Lock()
	defer r.mu.Unlock()

	var (
		out []Event
		now = epoch
	)
	for _, w := range r.writes {
		events, err := decode(w.kind, w.b)
		if err != nil {
			return nil, err
		}
		for _, e := range events {
			delay := e.time.Sub(now)
			if delay < 0 {
				delay = 0
			}
			out = append(out, Event{
				Message: string(sanitize(e.msg)),
				Kind:    e.kind,
				Delay:   delay,
			})
			if delay > 0 {
				now = e.time
			}
		}
	}
	return out, nil
}

type event struct {
	msg  []byte
	kind string
	time time.Time
}

func decode(kind string, output []byte) ([]event, error) {
	var (
		magic     = []byte{0, 0, 'P', 'B'}
		headerLen = 8 + 4
		last      = epoch
		events    []event
	)
	add := func(t time.Time, b []byte) {
		var prev *event
		if len(events) > 0 {
			prev = &events[len(events)-1]
		}
		if prev != nil && t.Equal(prev.time) {
			// Merge this event with previous event, to avoid
			// sending a lot of events for a big output with no
			// significant timing information.
			prev.msg = append(prev.msg, b...)
		} else {
			e := event{msg: b, kind: kind, time: t}
			events = append(events, e)
		}
		last = t
	}
	for i := 0; i < len(output); {
		if !bytes.HasPrefix(output[i:], magic) {
			// Not a header; find next header.
			j := bytes.Index(output[i:], magic)
			if j < 0 {
				// No more headers; bail.
				add(last, output[i:])
				break
			}
			add(last, output[i:i+j])
			i += j
		}
		i += len(magic)

		// Decode header.
		if len(output)-i < headerLen {
			return nil, errors.New("short header")
		}
		header := output[i : i+headerLen]
		nanos := int64(binary.BigEndian.Uint64(header[0:]))
		t := time.Unix(0, nanos)
		if t.Before(last) {
			// Force timestamps to be monotonic. (This could
			// be an encoding error, which we ignore now but will
			// will likely be picked up when decoding the length.)
			t = last
		}
		n := int(binary.BigEndian.Uint32(header[8:]))
		if n < 0 {
			return nil, fmt.Errorf("bad length: %v", n)
		}
		i += headerLen

		// Slurp output.
		// Truncated output is OK (probably caused by sandbox limits).
		end := i + n
		if end > len(output) {
			end = len(output)
		}
		add(t, output[i:end])
		i += n
	}
	return events, nil
}

// sanitize scans b for invalid utf8 code points. If found, it reconstructs
// the slice replacing the invalid codes with \uFFFD, properly encoded.
func sanitize(b []byte) []byte {
	if utf8.Valid(b) {
		return b
	}
	var buf bytes.Buffer
	for len(b) > 0 {
		r, size := utf8.DecodeRune(b)
		b = b[size:]
		buf.WriteRune(r)
	}
	return buf.Bytes()
}
