// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This package implements a trace file writer, whose files can be opened in
// chrome://tracing.
//
// It implements the JSON Array Format defined here:
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
package tracer

import (
	"bytes"
	"compress/gzip"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"

	"android/soong/ui/logger"
	"android/soong/ui/status"
)

type Thread uint64

const (
	MainThread     = Thread(iota)
	MaxInitThreads = Thread(iota)
)

type Tracer interface {
	Begin(name string, thread Thread)
	End(thread Thread)
	Complete(name string, thread Thread, begin, end uint64)

	CountersAtTime(name string, thread Thread, time uint64, counters []Counter)

	ImportMicrofactoryLog(filename string)

	StatusTracer() status.StatusOutput

	NewThread(name string) Thread
}

type tracerImpl struct {
	lock sync.Mutex
	log  logger.Logger

	buf  bytes.Buffer
	file *os.File
	w    io.WriteCloser

	firstEvent bool
	nextTid    uint64
}

var _ Tracer = &tracerImpl{}

type viewerEvent struct {
	Name  string      `json:"name,omitempty"`
	Phase string      `json:"ph"`
	Scope string      `json:"s,omitempty"`
	Time  uint64      `json:"ts"`
	Dur   uint64      `json:"dur,omitempty"`
	Pid   uint64      `json:"pid"`
	Tid   uint64      `json:"tid"`
	ID    uint64      `json:"id,omitempty"`
	Arg   interface{} `json:"args,omitempty"`
}

type nameArg struct {
	Name string `json:"name"`
}

type nopCloser struct{ io.Writer }

func (nopCloser) Close() error { return nil }

// New creates a new Tracer, storing log in order to log errors later.
// Events are buffered in memory until SetOutput is called.
func New(log logger.Logger) *tracerImpl {
	ret := &tracerImpl{
		log: log,

		firstEvent: true,
		nextTid:    uint64(MaxInitThreads),
	}
	ret.startBuffer()

	return ret
}

func (t *tracerImpl) startBuffer() {
	t.w = nopCloser{&t.buf}
	fmt.Fprintln(t.w, "[")

	t.defineThread(MainThread, "main")
}

func (t *tracerImpl) close() {
	if t.file != nil {
		fmt.Fprintln(t.w, "]")

		if err := t.w.Close(); err != nil {
			t.log.Println("Error closing trace writer:", err)
		}

		if err := t.file.Close(); err != nil {
			t.log.Println("Error closing trace file:", err)
		}
		t.file = nil
		t.startBuffer()
	}
}

// SetOutput creates the output file (rotating old files).
func (t *tracerImpl) SetOutput(filename string) {
	t.lock.Lock()
	defer t.lock.Unlock()

	t.close()

	// chrome://tracing requires that compressed trace files end in .gz
	if !strings.HasSuffix(filename, ".gz") {
		filename += ".gz"
	}

	f, err := logger.CreateFileWithRotation(filename, 5)
	if err != nil {
		t.log.Println("Failed to create trace file:", err)
		return
	}
	// Save the file, since closing the gzip Writer doesn't close the
	// underlying file.
	t.file = f
	t.w = gzip.NewWriter(f)

	// Write out everything that happened since the start
	if _, err := io.Copy(t.w, &t.buf); err != nil {
		t.log.Println("Failed to write trace buffer to file:", err)
	}
	t.buf = bytes.Buffer{}
}

// Close closes the output file. Any future events will be buffered until the
// next call to SetOutput.
func (t *tracerImpl) Close() {
	t.lock.Lock()
	defer t.lock.Unlock()

	t.close()
}

func (t *tracerImpl) writeEvent(event *viewerEvent) {
	t.lock.Lock()
	defer t.lock.Unlock()

	t.writeEventLocked(event)
}

func (t *tracerImpl) writeEventLocked(event *viewerEvent) {
	bytes, err := json.Marshal(event)
	if err != nil {
		t.log.Println("Failed to marshal event:", err)
		t.log.Verbosef("Event: %#v", event)
		return
	}

	if !t.firstEvent {
		fmt.Fprintln(t.w, ",")
	} else {
		t.firstEvent = false
	}

	if _, err = t.w.Write(bytes); err != nil {
		t.log.Println("Trace write error:", err)
	}
}

func (t *tracerImpl) defineThread(thread Thread, name string) {
	t.writeEventLocked(&viewerEvent{
		Name:  "thread_name",
		Phase: "M",
		Pid:   0,
		Tid:   uint64(thread),
		Arg: &nameArg{
			Name: name,
		},
	})
}

// NewThread returns a new Thread with an unused tid, writing the name out to
// the trace file.
func (t *tracerImpl) NewThread(name string) Thread {
	t.lock.Lock()
	defer t.lock.Unlock()

	ret := Thread(t.nextTid)
	t.nextTid += 1

	t.defineThread(ret, name)
	return ret
}

// Begin starts a new Duration Event. More than one Duration Event may be active
// at a time on each Thread, but they're nested.
func (t *tracerImpl) Begin(name string, thread Thread) {
	t.writeEvent(&viewerEvent{
		Name:  name,
		Phase: "B",
		Time:  uint64(time.Now().UnixNano()) / 1000,
		Pid:   0,
		Tid:   uint64(thread),
	})
}

// End finishes the most recent active Duration Event on the thread.
func (t *tracerImpl) End(thread Thread) {
	t.writeEvent(&viewerEvent{
		Phase: "E",
		Time:  uint64(time.Now().UnixNano()) / 1000,
		Pid:   0,
		Tid:   uint64(thread),
	})
}

// Complete writes a Complete Event, which are like Duration Events, but include
// a begin and end timestamp in the same event.
func (t *tracerImpl) Complete(name string, thread Thread, begin, end uint64) {
	t.writeEvent(&viewerEvent{
		Name:  name,
		Phase: "X",
		Time:  begin / 1000,
		Dur:   (end - begin) / 1000,
		Pid:   0,
		Tid:   uint64(thread),
	})
}

type Counter struct {
	Name  string
	Value int64
}

type countersMarshaller []Counter

var _ json.Marshaler = countersMarshaller(nil)

func (counters countersMarshaller) MarshalJSON() ([]byte, error) {
	// This produces similar output to a map[string]int64, but maintains the order of the slice.
	buf := bytes.Buffer{}
	buf.WriteRune('{')
	for i, counter := range counters {
		name, err := json.Marshal(counter.Name)
		if err != nil {
			return nil, err
		}
		buf.Write(name)
		buf.WriteByte(':')
		value, err := json.Marshal(counter.Value)
		if err != nil {
			return nil, err
		}
		buf.Write(value)
		if i != len(counters)-1 {
			buf.WriteRune(',')
		}
	}
	buf.WriteRune('}')
	return buf.Bytes(), nil
}

// CountersAtTime writes a Counter event at the given timestamp in nanoseconds.
func (t *tracerImpl) CountersAtTime(name string, thread Thread, time uint64, counters []Counter) {
	t.writeEvent(&viewerEvent{
		Name:  name,
		Phase: "C",
		Time:  time / 1000,
		Pid:   0,
		Tid:   uint64(thread),
		Arg:   countersMarshaller(counters),
	})
}
