// Package config creates an osquery configuration plugin.
//
// See https://osquery.readthedocs.io/en/latest/development/config-plugins/ for more.
package config

import (
	"context"

	"github.com/kolide/osquery-go/gen/osquery"
)

// GenerateConfigsFunc returns the configurations generated by this plugin.
// The returned map should use the source name as key, and the config
// JSON as values. The context argument can optionally be used for
// cancellation in long-running operations.
type GenerateConfigsFunc func(ctx context.Context) (map[string]string, error)

// Plugin is an osquery configuration plugin. Plugin implements the OsqueryPlugin
// interface.
type Plugin struct {
	name     string
	generate GenerateConfigsFunc
}

// NewConfigPlugin takes a value that implements ConfigPlugin and wraps it with
// the appropriate methods to satisfy the OsqueryPlugin interface. Use this to
// easily create configuration plugins.
func NewPlugin(name string, fn GenerateConfigsFunc) *Plugin {
	return &Plugin{name: name, generate: fn}
}

func (t *Plugin) Name() string {
	return t.name
}

// Registry name for config plugins
const configRegistryName = "config"

func (t *Plugin) RegistryName() string {
	return configRegistryName
}

func (t *Plugin) Routes() osquery.ExtensionPluginResponse {
	return osquery.ExtensionPluginResponse{}
}

func (t *Plugin) Ping() osquery.ExtensionStatus {
	return osquery.ExtensionStatus{Code: 0, Message: "OK"}
}

// Key that the request method is stored under
const requestActionKey = "action"

// Action value used when config is requested
const genConfigAction = "genConfig"

func (t *Plugin) Call(ctx context.Context, request osquery.ExtensionPluginRequest) osquery.ExtensionResponse {
	switch request[requestActionKey] {
	case genConfigAction:
		configs, err := t.generate(ctx)
		if err != nil {
			return osquery.ExtensionResponse{
				Status: &osquery.ExtensionStatus{
					Code:    1,
					Message: "error getting config: " + err.Error(),
				},
			}
		}

		return osquery.ExtensionResponse{
			Status:   &osquery.ExtensionStatus{Code: 0, Message: "OK"},
			Response: osquery.ExtensionPluginResponse{configs},
		}

	default:
		return osquery.ExtensionResponse{
			Status: &osquery.ExtensionStatus{
				Code:    1,
				Message: "unknown action: " + request["action"],
			},
		}
	}

}

func (t *Plugin) Shutdown() {}
