// Copyright (C) 2015 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 database

import (
	"bytes"
	"fmt"
	"sync"
	"time"

	"android.googlesource.com/platform/tools/gpu/binary"
	"android.googlesource.com/platform/tools/gpu/log"
)

// Transient database wrapper. The wrapper allows transient stores to
// be stored in RAM rather than disk.  A resource stored transiently
// must be loaded exactly once. After being loaded it is dropped from
// the store and another load will be an error. If the transient
// resource is never loaded it will eventually be purged.

// The transient database wrapper is used by the replay system where
// opcode streams are encoded as large byte streams which are normally
// used once with a few milliseconds of creation.

// How much to keep in RAM before trying to purge
const purgeSizeBytes = 100 << 10 // 100MB

// How many dropped timestamps to keep before trying to purge
const purgeDroppedCount = 100 // 100

// How many nanoseconds before it is safe to purge an item
const keepTimeNanoSeconds = int64(30) * int64(1000000000) // 30 seconds

func CreateTransientDatabase(inner Database) Database {
	return &transient{inner: inner, entries: make(map[binary.ID][]byte), droppedAt: make(map[binary.ID]time.Time), storedAt: make(map[binary.ID]time.Time)}
}

type transient struct {
	inner     Database                // database for non-transient resources
	mutex     sync.Mutex              // held when modifying the maps or size
	entries   map[binary.ID][]byte    // the transient resource data
	droppedAt map[binary.ID]time.Time // the time the transient resource was dropped from the store
	storedAt  map[binary.ID]time.Time // the time the transient resource was stored in the store
	size      int                     // the total size of all the transient resources
}

func (t *transient) StoreLink(to, id binary.ID, logger log.Logger) error {
	return fmt.Errorf("Can not StoreLink in a Transient Database")
}

func (t *transient) StoreRequest(request binary.Object, logger log.Logger) (id binary.ID, err error) {
	return binary.ID{}, fmt.Errorf("Can not StoreRequest in a Transient Database")
}

// Drop a resource from the store. The t.mutex is already held.
func (t *transient) dropLocked(id binary.ID, logger log.Logger) {
	if entry, ok := t.entries[id]; ok {
		t.size -= len(entry)
		delete(t.entries, id)
		// Keep track of the fact that this id has been dropped.
		now := time.Now()
		t.droppedAt[id] = now
	}

	delete(t.storedAt, id)
}

// Store a resource in the transient store. If the store gets large purge old info.
func (t *transient) Store(r binary.Object, logger log.Logger) (id binary.ID, err error) {
	logger = logger.Enter("Transient.Store")
	defer func() { logger.Info("↪ id: %v, err: %v total_size: %v", id, err, t.size) }()

	buf := &bytes.Buffer{}
	enc := binary.NewEncoder(buf)
	if err := r.Encode(enc); err != nil {
		return binary.ID{}, err
	}

	data := buf.Bytes()
	id = binary.NewID(data)

	t.mutex.Lock()
	now := time.Now()
	// Purge any old items from the transient store, if it is large.
	if t.size+len(data) > purgeSizeBytes {
		for id, storedTime := range t.storedAt {
			if now.Sub(storedTime).Nanoseconds() > keepTimeNanoSeconds {
				t.dropLocked(id, logger)
				if t.size <= purgeSizeBytes {
					break
				}
			}
		}
	}

	// Purge any old dropped markers from the store, if there are many.
	if len(t.droppedAt) > purgeDroppedCount {
		for id, droppedTime := range t.droppedAt {
			if now.Sub(droppedTime).Nanoseconds() > keepTimeNanoSeconds {
				delete(t.droppedAt, id)
				if len(t.droppedAt) <= purgeDroppedCount {
					break
				}
			}
		}
	}

	t.entries[id] = data
	t.storedAt[id] = now
	t.size += len(data)
	delete(t.droppedAt, id)

	t.mutex.Unlock()
	return id, nil
}

// Load a resource from the transient store. If not present in the transient store look in the
// underlying store. If in the transient store, drop it and return it.
func (t *transient) Load(id binary.ID, logger log.Logger, out binary.Object) (err error) {
	logger = logger.Enter("Transient.Load")
	logger.Info("(id: %v total_size: %v)", id, t.size)
	defer func() { logger.Info("↪ err: %v total_size: %v", err, t.size) }()

	t.mutex.Lock()
	if entry, ok := t.entries[id]; ok {
		t.mutex.Unlock()
		d := binary.NewDecoder(bytes.NewBuffer(entry))
		err := out.Decode(d)
		t.mutex.Lock()
		t.dropLocked(id, logger)
		t.mutex.Unlock()
		return err
	} else {
		if t, ok := t.droppedAt[id]; ok {
			return fmt.Errorf("Id %v was dropped at %v", id, t)
		}
		t.mutex.Unlock()
		return t.inner.Load(id, logger, out)
	}
}

func (t *transient) Contains(id binary.ID, logger log.Logger) bool {
	_, found := t.entries[id]
	return found || t.inner.Contains(id, logger)
}

func (t *transient) Captures() (map[string]binary.ID, error) {
	return nil, nil
}

func (t *transient) Close() {
	t.inner.Close()
}
