package target

import (
	"encoding/json"
	"fmt"
)

type TargetResult struct {
	Name    string              `json:"name"`
	Options TargetResultOptions `json:"options"`
}

func newTargetResult(name string, options TargetResultOptions) *TargetResult {
	return &TargetResult{
		Name:    name,
		Options: options,
	}
}

type TargetResultOptions interface {
	isTargetResultOptions()
}

type rawTargetResult struct {
	Name    string          `json:"name"`
	Options json.RawMessage `json:"options"`
}

func (targetResult *TargetResult) UnmarshalJSON(data []byte) error {
	var rawTR rawTargetResult
	err := json.Unmarshal(data, &rawTR)
	if err != nil {
		return err
	}
	options, err := UnmarshalTargetResultOptions(rawTR.Name, rawTR.Options)
	if err != nil {
		return err
	}

	targetResult.Name = rawTR.Name
	targetResult.Options = options
	return nil
}

func UnmarshalTargetResultOptions(trName string, rawOptions json.RawMessage) (TargetResultOptions, error) {
	var options TargetResultOptions
	switch trName {
	case "org.osbuild.aws":
		options = new(AWSTargetResultOptions)
	case "org.osbuild.aws.s3":
		options = new(AWSS3TargetResultOptions)
	case "org.osbuild.gcp":
		options = new(GCPTargetResultOptions)
	case "org.osbuild.azure.image":
		options = new(AzureImageTargetResultOptions)
	default:
		return nil, fmt.Errorf("Unexpected target result name: %s", trName)
	}
	err := json.Unmarshal(rawOptions, options)

	return options, err
}
