// Copyright (C) 2016 The Android Open Source Project
//
// 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.

package gapii

import (
	"fmt"
	"io"
	"math"
	"net"
	"time"

	"android.googlesource.com/platform/tools/gpu/framework/binary/cyclic"
	"android.googlesource.com/platform/tools/gpu/framework/binary/schema"
	"android.googlesource.com/platform/tools/gpu/framework/binary/vle"
	"android.googlesource.com/platform/tools/gpu/framework/log"
	"android.googlesource.com/platform/tools/gpu/framework/task"
	"android.googlesource.com/platform/tools/gpu/gapid/atom"
)

// CaptureTag is the trace file header tag.
const CaptureTag = "GapiiTraceFile_V1.1"

// Flags is a bit-field of flags to use when creating a capture.
type Flags uint32

const (
	// DisablePrecompiledShaders fakes no support for PCS, forcing the app to
	// share shader source.
	DisablePrecompiledShaders Flags = 0x00000001
	// RecordErrorState queries the driver error state after each all and stores
	// errors as extras.
	RecordErrorState Flags = 0x10000000
)

// Options to use when creating a capture.
type Options struct {
	// If non-zero, then a framebuffer-observation will be made after every n end-of-frames.
	ObserveFrameFreqency uint32
	// If non-zero, then a framebuffer-observation will be made after every n draw calls.
	ObserveDrawFrequency uint32
	// Combination of FlagXX bits.
	Flags Flags
}

const sizeGap = 1024 * 1024 * 5
const timeGap = time.Second

type siSize int64

var formats = []string{
	"%.0fB",
	"%.2fKB",
	"%.2fMB",
	"%.2fGB",
	"%.2fTB",
	"%.2fPB",
	"%.2fEB",
}

func (s siSize) String() string {
	if s == 0 {
		return "0.0B"
	}
	size := float64(s)
	e := math.Floor(math.Log(size) / math.Log(1000))
	f := formats[int(e)]
	v := math.Floor(size/math.Pow(1000, e)*10+0.5) / 10
	return fmt.Sprintf(f, v)
}

func capture(ctx log.Context, port int, w io.Writer, o Options) (int64, error) {
	if task.Stopped(ctx) {
		return 0, nil
	}
	conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
	if err != nil {
		return 0, nil // Treat failure-to-connect as target-not-ready instead of an error.
	}
	defer conn.Close()
	if err := sendHeader(conn, o); err != nil {
		return 0, err
	}

	var count, nextSize siSize
	startTime := time.Now()
	nextTime := startTime
	for {
		if task.Stopped(ctx) {
			ctx.Printf("Stop: %v", count)
			break
		}
		now := time.Now()
		conn.SetReadDeadline(now.Add(time.Millisecond * 100)) // Allow for stop event and UI refreshes.
		n, err := io.CopyN(w, conn, 1024*64)
		count += siSize(n)
		if err == io.EOF {
			ctx.Printf("EOF: %v", count)
			break
		}
		if err != nil {
			err, isnet := err.(net.Error)
			if !isnet || (!err.Temporary() && !err.Timeout()) {
				ctx.Info().Fail(err, "Connection error")
				return int64(count), err
			}
		}
		if count > nextSize || now.After(nextTime) {
			nextSize = count + sizeGap
			nextTime = now.Add(timeGap)
			delta := time.Duration(int64(now.Sub(startTime)/time.Millisecond)) * time.Millisecond
			ctx.Printf("Capturing: %v in %v", count, delta)
		}
	}
	return int64(count), nil
}

// Capture opens up the specified port and then waits for a capture to be
// delivered using the specified capture options.
// It copies the capture into the supplied writer.
func Capture(ctx log.Context, port int, w io.Writer, options Options) (int64, error) {
	ctx.Printf("Waiting for connection to localhost:%d...", port)
	for {
		count, err := capture(ctx, port, w, options)
		if err != nil {
			return count, err
		}
		if count != 0 {
			return count, nil
		}
		// ADB has an annoying tendancy to insta-close forwarded sockets when
		// there's no application waiting for the connection. Treat this as
		// another waiting-for-connection case.
		select {
		case <-task.ShouldStop(ctx):
			ctx.Print("Aborted.")
			return 0, nil
		case <-time.After(500 * time.Millisecond):
			ctx.Print("Retry...")
		}
	}
}

// ReadCapture converts the contents of a capture stream to an atom list.
func ReadCapture(ctx log.Context, name string, in io.Reader) (*atom.List, error) {
	list := atom.NewList()
	d := cyclic.Decoder(vle.Reader(in))
	tag := d.String()
	if d.Error() != nil {
		return list, d.Error()
	}
	if tag != CaptureTag {
		return list, fmt.Errorf("Invalid capture tag '%s'", tag)
	}
	for {
		obj := d.Variant()
		if d.Error() != nil {
			if d.Error() != io.EOF {
				ctx.Warning().I("len", len(list.Atoms)).Fail(d.Error(), "Decode of capture errored")
				if len(list.Atoms) > 0 {
					a := list.Atoms[len(list.Atoms)-1]
					ctx.Notice().V("atom", a).Log("Last atom successfully decoded")
				}
			}
			break
		}
		switch obj := obj.(type) {
		case atom.Atom:
			list.Atoms = append(list.Atoms, obj)
		case *schema.Object:
			a, err := atom.Wrap(obj)
			if err != nil {
				return list, err
			}
			list.Atoms = append(list.Atoms, a)
		default:
			return list, fmt.Errorf("Expected atom, got '%T' after decoding %d atoms", obj, len(list.Atoms))
		}
	}
	return list, nil
}
