// Copyright 2020 The Fuchsia 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 fuzz

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
)

// A Handle provides a way to persist and restore information about an Instance
// between separate invocations of the tool.
//
// In this case, it is a simple wrapper around a JSON file on disk, kept as
// simple as possible by updating only in bulk and avoiding any caching.
//
// It is not safe to use the same Handle simultaneously in multiple processes.
// This does not pose an issue under expected use, however, because the only
// time Handles are currently modified after creation is when they are deleted
// by a call to `stop_instance`. The only potential consequence would be an
// attempt to connect to an already-stopped instance, which will throw an
// appropriate error.

type Handle string

// HandleData represents the top-level structure of the data stored within the
// Handle.
type HandleData struct {
	connector Connector
	launcher  Launcher
}

// annotatedHandleData is the format of the serialized data. Type information
// is stored alongside the objects so that they can be properly deserialized.
type annotatedHandleData struct {
	ConnectorType string
	Connector     json.RawMessage

	LauncherType string
	Launcher     json.RawMessage
}

// NewHandle allocates a new handle for use. It will persist until explicitly Released.
func NewHandle() (Handle, error) {
	tmpFile, err := ioutil.TempFile("", "undercoat_*.handle")
	if err != nil {
		return "", fmt.Errorf("error allocating tempfile: %s", err)
	}
	defer tmpFile.Close()

	// Start with an empty JSON object
	tmpFile.WriteString("{}")

	return Handle(tmpFile.Name()), nil
}

// NewHandleWithData is a convenience function for populating a new Handle
// at the same time as creating it.
func NewHandleWithData(initialData HandleData) (Handle, error) {
	handle, err := NewHandle()
	if err != nil {
		return "", fmt.Errorf("error creating handle: %s", err)
	}

	if err := handle.SetData(initialData); err != nil {
		handle.Release()
		return "", fmt.Errorf("error initializing handle: %s", err)
	}

	return handle, nil
}

// LoadHandleFromString recreates a previously-created Handle from its string
// representation as returned by Serialize()
func LoadHandleFromString(s string) (Handle, error) {
	h := Handle(s)
	// Make sure we can load it, and error out early if not
	if _, err := h.loadFromDisk(); err != nil {
		return "", fmt.Errorf("error loading handle: %s", err)
	}
	return h, nil
}

// Serialize returns a printable representation of the Handle
func (h Handle) Serialize() string {
	return string(h)
}

// GetData will load and return data from the Handle, as previously stored by SetData.
func (h Handle) GetData() (*HandleData, error) {
	rawData, err := h.loadFromDisk()
	if err != nil {
		return nil, fmt.Errorf("error loading handle: %s", err)
	}

	var data HandleData

	switch rawData.ConnectorType {
	case "SSHConnector":
		data.connector = NewSSHConnector("", 0, "")
	case "":
		// connector is empty
	default:
		return nil, fmt.Errorf("unknown connector type: %q", rawData.ConnectorType)
	}
	if rawData.ConnectorType != "" {
		if err := json.Unmarshal(rawData.Connector, &data.connector); err != nil {
			return nil, fmt.Errorf("error unmarshaling connector: %s", err)
		}
	}

	switch rawData.LauncherType {
	case "QemuLauncher":
		data.launcher = NewQemuLauncher(nil)
	case "":
		// launcher is empty
	default:
		return nil, fmt.Errorf("unknown launcher type: %q", rawData.LauncherType)
	}
	if rawData.LauncherType != "" {
		if err := json.Unmarshal(rawData.Launcher, &data.launcher); err != nil {
			return nil, fmt.Errorf("error unmarshaling launcher: %s", err)
		}
	}

	return &data, nil
}

// SetData stores all exported fields of the given data into the Handle, so
// they can later be retrieved with GetData. Any existing data in the Handle
// will be overwritten.
func (h Handle) SetData(data HandleData) error {
	// Make sure we haven't been released
	if _, err := h.loadFromDisk(); err != nil {
		return fmt.Errorf("error loading handle: %s", err)
	}

	var rawData annotatedHandleData

	// Save type information
	if data.connector != nil {
		rawData.ConnectorType = reflect.TypeOf(data.connector).Elem().Name()
	}
	if data.launcher != nil {
		rawData.LauncherType = reflect.TypeOf(data.launcher).Elem().Name()
	}

	// Serialize sub-objects
	connectorData, err := json.Marshal(data.connector)
	if err != nil {
		return fmt.Errorf("error serializing connector: %s", err)
	}
	rawData.Connector = connectorData

	launcherData, err := json.Marshal(data.launcher)
	if err != nil {
		return fmt.Errorf("error serializing launcher: %s", err)
	}
	rawData.Launcher = launcherData

	// Serialize outer object
	jsonData, err := json.Marshal(rawData)
	if err != nil {
		return fmt.Errorf("error serializing handle: %s", err)
	}

	// Persist immediately
	if err := ioutil.WriteFile(string(h), jsonData, 0600); err != nil {
		return fmt.Errorf("error writing handle: %s", err)
	}

	return nil
}

// Release removes any resources used by the Handle. After calling Release, the handle
// will become invalid and cannot be further used.
func (h Handle) Release() {
	os.Remove(string(h))
}

func (h Handle) loadFromDisk() (*annotatedHandleData, error) {
	jsonData, err := ioutil.ReadFile(string(h))
	if err != nil {
		return nil, fmt.Errorf("error opening file: %s", err)
	}

	var data annotatedHandleData

	if err := json.Unmarshal(jsonData, &data); err != nil {
		return nil, fmt.Errorf("error unmarshaling: %s", err)
	}

	return &data, nil
}
