/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.

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 pbm

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/vmware/govmomi/pbm/types"
)

// A struct to capture pbm create spec details.
type CapabilityProfileCreateSpec struct {
	Name           string
	Description    string
	Category       string
	CapabilityList []Capability
}

// A struct to capture pbm capability instance details.
type Capability struct {
	ID           string
	Namespace    string
	PropertyList []Property
}

// A struct to capture pbm property instance details.
type Property struct {
	ID       string
	Operator string
	Value    string
	DataType string
}

func CreateCapabilityProfileSpec(pbmCreateSpec CapabilityProfileCreateSpec) (*types.PbmCapabilityProfileCreateSpec, error) {
	capabilities, err := createCapabilityInstances(pbmCreateSpec.CapabilityList)
	if err != nil {
		return nil, err
	}

	pbmCapabilityProfileSpec := types.PbmCapabilityProfileCreateSpec{
		Name:        pbmCreateSpec.Name,
		Description: pbmCreateSpec.Description,
		Category:    pbmCreateSpec.Category,
		ResourceType: types.PbmProfileResourceType{
			ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE),
		},
		Constraints: &types.PbmCapabilitySubProfileConstraints{
			SubProfiles: []types.PbmCapabilitySubProfile{
				types.PbmCapabilitySubProfile{
					Capability: capabilities,
				},
			},
		},
	}
	return &pbmCapabilityProfileSpec, nil
}

func createCapabilityInstances(rules []Capability) ([]types.PbmCapabilityInstance, error) {
	var capabilityInstances []types.PbmCapabilityInstance
	for _, capabilityRule := range rules {
		capability := types.PbmCapabilityInstance{
			Id: types.PbmCapabilityMetadataUniqueId{
				Namespace: capabilityRule.Namespace,
				Id:        capabilityRule.ID,
			},
		}

		var propertyInstances []types.PbmCapabilityPropertyInstance
		for _, propertyRule := range capabilityRule.PropertyList {
			property := types.PbmCapabilityPropertyInstance{
				Id: propertyRule.ID,
			}
			if propertyRule.Operator != "" {
				property.Operator = propertyRule.Operator
			}
			var err error
			switch strings.ToLower(propertyRule.DataType) {
			case "int":
				// Go int32 is marshalled to xsi:int whereas Go int is marshalled to xsi:long when sending down the wire.
				var val int32
				val, err = verifyPropertyValueIsInt(propertyRule.Value, propertyRule.DataType)
				property.Value = val
			case "bool":
				var val bool
				val, err = verifyPropertyValueIsBoolean(propertyRule.Value, propertyRule.DataType)
				property.Value = val
			case "string":
				property.Value = propertyRule.Value
			case "set":
				set := types.PbmCapabilityDiscreteSet{}
				for _, val := range strings.Split(propertyRule.Value, ",") {
					set.Values = append(set.Values, val)
				}
				property.Value = set
			default:
				return nil, fmt.Errorf("invalid value: %q with datatype: %q", propertyRule.Value, propertyRule.Value)
			}
			if err != nil {
				return nil, fmt.Errorf("invalid value: %q with datatype: %q", propertyRule.Value, propertyRule.Value)
			}
			propertyInstances = append(propertyInstances, property)
		}
		constraintInstances := []types.PbmCapabilityConstraintInstance{
			types.PbmCapabilityConstraintInstance{
				PropertyInstance: propertyInstances,
			},
		}
		capability.Constraint = constraintInstances
		capabilityInstances = append(capabilityInstances, capability)
	}
	return capabilityInstances, nil
}

// Verify if the capability value is of type integer.
func verifyPropertyValueIsInt(propertyValue string, dataType string) (int32, error) {
	val, err := strconv.ParseInt(propertyValue, 10, 32)
	if err != nil {
		return -1, err
	}
	return int32(val), nil
}

// Verify if the capability value is of type integer.
func verifyPropertyValueIsBoolean(propertyValue string, dataType string) (bool, error) {
	val, err := strconv.ParseBool(propertyValue)
	if err != nil {
		return false, err
	}
	return val, nil
}
