// Copyright 2018 The gVisor Authors.
//
// 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 state

import (
	"context"
	"fmt"
	"reflect"
	"sort"
	"sync"

	pb "gvisor.dev/gvisor/pkg/state/object_go_proto"
)

// entry is a single map entry.
type entry struct {
	name   string
	object *pb.Object
}

// internalMap is the internal Map state.
//
// These are recycled via a pool to avoid churn.
type internalMap struct {
	// es is encodeState.
	es *encodeState

	// ds is decodeState.
	ds *decodeState

	// os is current object being decoded.
	//
	// This will always be nil during encode.
	os *objectState

	// data stores the encoded values.
	data []entry
}

var internalMapPool = sync.Pool{
	New: func() interface{} {
		return new(internalMap)
	},
}

// newInternalMap returns a cached map.
func newInternalMap(es *encodeState, ds *decodeState, os *objectState) *internalMap {
	m := internalMapPool.Get().(*internalMap)
	m.es = es
	m.ds = ds
	m.os = os
	if m.data != nil {
		m.data = m.data[:0]
	}
	return m
}

// Map is a generic state container.
//
// This is the object passed to Save and Load in order to store their state.
//
// Detailed documentation is available in individual methods.
type Map struct {
	*internalMap
}

// Save adds the given object to the map.
//
// You should pass always pointers to the object you are saving. For example:
//
// type X struct {
// 	A int
// 	B *int
// }
//
// func (x *X) Save(m Map) {
// 	m.Save("A", &x.A)
// 	m.Save("B", &x.B)
// }
//
// func (x *X) Load(m Map) {
// 	m.Load("A", &x.A)
// 	m.Load("B", &x.B)
// }
func (m Map) Save(name string, objPtr interface{}) {
	m.save(name, reflect.ValueOf(objPtr).Elem(), ".%s")
}

// SaveValue adds the given object value to the map.
//
// This should be used for values where pointers are not available, or casts
// are required during Save/Load.
//
// For example, if we want to cast external package type P.Foo to int64:
//
// type X struct {
//	A P.Foo
// }
//
// func (x *X) Save(m Map) {
//	m.SaveValue("A", int64(x.A))
// }
//
// func (x *X) Load(m Map) {
//	m.LoadValue("A", new(int64), func(x interface{}) {
//		x.A = P.Foo(x.(int64))
//	})
// }
func (m Map) SaveValue(name string, obj interface{}) {
	m.save(name, reflect.ValueOf(obj), ".(value %s)")
}

// save is helper for the above. It takes the name of value to save the field
// to, the field object (obj), and a format string that specifies how the
// field's saving logic is dispatched from the struct (normal, value, etc.). The
// format string should expect one string parameter, which is the name of the
// field.
func (m Map) save(name string, obj reflect.Value, format string) {
	if m.es == nil {
		// Not currently encoding.
		m.Failf("no encode state for %q", name)
	}

	// Attempt the encode.
	//
	// These are sorted at the end, after all objects are added and will be
	// sorted and checked for duplicates (see encodeStruct).
	m.data = append(m.data, entry{
		name:   name,
		object: m.es.encodeObject(obj, false, format, name),
	})
}

// Load loads the given object from the map.
//
// See Save for an example.
func (m Map) Load(name string, objPtr interface{}) {
	m.load(name, reflect.ValueOf(objPtr), false, nil, ".%s")
}

// LoadWait loads the given objects from the map, and marks it as requiring all
// AfterLoad executions to complete prior to running this object's AfterLoad.
//
// See Save for an example.
func (m Map) LoadWait(name string, objPtr interface{}) {
	m.load(name, reflect.ValueOf(objPtr), true, nil, ".(wait %s)")
}

// LoadValue loads the given object value from the map.
//
// See SaveValue for an example.
func (m Map) LoadValue(name string, objPtr interface{}, fn func(interface{})) {
	o := reflect.ValueOf(objPtr)
	m.load(name, o, true, func() { fn(o.Elem().Interface()) }, ".(value %s)")
}

// load is helper for the above. It takes the name of value to load the field
// from, the target field pointer (objPtr), whether load completion of the
// struct depends on the field's load completion (wait), the load completion
// logic (fn), and a format string that specifies how the field's loading logic
// is dispatched from the struct (normal, wait, value, etc.). The format string
// should expect one string parameter, which is the name of the field.
func (m Map) load(name string, objPtr reflect.Value, wait bool, fn func(), format string) {
	if m.ds == nil {
		// Not currently decoding.
		m.Failf("no decode state for %q", name)
	}

	// Find the object.
	//
	// These are sorted up front (and should appear in the state file
	// sorted as well), so we can do a binary search here to ensure that
	// large structs don't behave badly.
	i := sort.Search(len(m.data), func(i int) bool {
		return m.data[i].name >= name
	})
	if i >= len(m.data) || m.data[i].name != name {
		// There is no data for this name?
		m.Failf("no data found for %q", name)
	}

	// Perform the decode.
	m.ds.decodeObject(m.os, objPtr.Elem(), m.data[i].object, format, name)
	if wait {
		// Mark this individual object a blocker.
		m.ds.waitObject(m.os, m.data[i].object, fn)
	}
}

// Failf fails the save or restore with the provided message. Processing will
// stop after calling Failf, as the state package uses a panic & recover
// mechanism for state errors. You should defer any cleanup required.
func (m Map) Failf(format string, args ...interface{}) {
	panic(fmt.Errorf(format, args...))
}

// AfterLoad schedules a function execution when all objects have been allocated
// and their automated loading and customized load logic have been executed. fn
// will not be executed until all of current object's dependencies' AfterLoad()
// logic, if exist, have been executed.
func (m Map) AfterLoad(fn func()) {
	if m.ds == nil {
		// Not currently decoding.
		m.Failf("not decoding")
	}

	// Queue the local callback; this will execute when all of the above
	// data dependencies have been cleared.
	m.os.callbacks = append(m.os.callbacks, fn)
}

// Context returns the current context object.
func (m Map) Context() context.Context {
	if m.es != nil {
		return m.es.ctx
	} else if m.ds != nil {
		return m.ds.ctx
	}
	return context.Background() // No context.
}
