//go:build go1.18
// +build go1.18

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

package armscvmm

import (
	"encoding/json"
	"fmt"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
	"reflect"
)

// MarshalJSON implements the json.Marshaller interface for type AvailabilitySet.
func (a AvailabilitySet) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "extendedLocation", a.ExtendedLocation)
	populate(objectMap, "id", a.ID)
	populate(objectMap, "location", a.Location)
	populate(objectMap, "name", a.Name)
	populate(objectMap, "properties", a.Properties)
	populate(objectMap, "systemData", a.SystemData)
	populate(objectMap, "tags", a.Tags)
	populate(objectMap, "type", a.Type)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type Cloud.
func (c Cloud) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "extendedLocation", c.ExtendedLocation)
	populate(objectMap, "id", c.ID)
	populate(objectMap, "location", c.Location)
	populate(objectMap, "name", c.Name)
	populate(objectMap, "properties", c.Properties)
	populate(objectMap, "systemData", c.SystemData)
	populate(objectMap, "tags", c.Tags)
	populate(objectMap, "type", c.Type)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type CloudInventoryItem.
func (c CloudInventoryItem) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "inventoryItemName", c.InventoryItemName)
	objectMap["inventoryType"] = InventoryTypeCloud
	populate(objectMap, "managedResourceId", c.ManagedResourceID)
	populate(objectMap, "provisioningState", c.ProvisioningState)
	populate(objectMap, "uuid", c.UUID)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type CloudInventoryItem.
func (c *CloudInventoryItem) UnmarshalJSON(data []byte) error {
	var rawMsg map[string]json.RawMessage
	if err := json.Unmarshal(data, &rawMsg); err != nil {
		return fmt.Errorf("unmarshalling type %T: %v", c, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "inventoryItemName":
			err = unpopulate(val, "InventoryItemName", &c.InventoryItemName)
			delete(rawMsg, key)
		case "inventoryType":
			err = unpopulate(val, "InventoryType", &c.InventoryType)
			delete(rawMsg, key)
		case "managedResourceId":
			err = unpopulate(val, "ManagedResourceID", &c.ManagedResourceID)
			delete(rawMsg, key)
		case "provisioningState":
			err = unpopulate(val, "ProvisioningState", &c.ProvisioningState)
			delete(rawMsg, key)
		case "uuid":
			err = unpopulate(val, "UUID", &c.UUID)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", c, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type CloudProperties.
func (c CloudProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "cloudCapacity", c.CloudCapacity)
	populate(objectMap, "cloudName", c.CloudName)
	populate(objectMap, "inventoryItemId", c.InventoryItemID)
	populate(objectMap, "provisioningState", c.ProvisioningState)
	populate(objectMap, "storageQoSPolicies", c.StorageQoSPolicies)
	populate(objectMap, "uuid", c.UUID)
	populate(objectMap, "vmmServerId", c.VmmServerID)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type InventoryItem.
func (i InventoryItem) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "id", i.ID)
	populate(objectMap, "kind", i.Kind)
	populate(objectMap, "name", i.Name)
	populate(objectMap, "properties", i.Properties)
	populate(objectMap, "systemData", i.SystemData)
	populate(objectMap, "type", i.Type)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type InventoryItem.
func (i *InventoryItem) UnmarshalJSON(data []byte) error {
	var rawMsg map[string]json.RawMessage
	if err := json.Unmarshal(data, &rawMsg); err != nil {
		return fmt.Errorf("unmarshalling type %T: %v", i, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "id":
			err = unpopulate(val, "ID", &i.ID)
			delete(rawMsg, key)
		case "kind":
			err = unpopulate(val, "Kind", &i.Kind)
			delete(rawMsg, key)
		case "name":
			err = unpopulate(val, "Name", &i.Name)
			delete(rawMsg, key)
		case "properties":
			i.Properties, err = unmarshalInventoryItemPropertiesClassification(val)
			delete(rawMsg, key)
		case "systemData":
			err = unpopulate(val, "SystemData", &i.SystemData)
			delete(rawMsg, key)
		case "type":
			err = unpopulate(val, "Type", &i.Type)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", i, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type NetworkInterfaces.
func (n NetworkInterfaces) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "displayName", n.DisplayName)
	populate(objectMap, "ipv4AddressType", n.IPv4AddressType)
	populate(objectMap, "ipv4Addresses", n.IPv4Addresses)
	populate(objectMap, "ipv6AddressType", n.IPv6AddressType)
	populate(objectMap, "ipv6Addresses", n.IPv6Addresses)
	populate(objectMap, "macAddress", n.MacAddress)
	populate(objectMap, "macAddressType", n.MacAddressType)
	populate(objectMap, "name", n.Name)
	populate(objectMap, "networkName", n.NetworkName)
	populate(objectMap, "nicId", n.NicID)
	populate(objectMap, "virtualNetworkId", n.VirtualNetworkID)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type NetworkProfile.
func (n NetworkProfile) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "networkInterfaces", n.NetworkInterfaces)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type NetworkProfileUpdate.
func (n NetworkProfileUpdate) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "networkInterfaces", n.NetworkInterfaces)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type ResourcePatch.
func (r ResourcePatch) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "tags", r.Tags)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type StorageProfile.
func (s StorageProfile) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "disks", s.Disks)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type StorageProfileUpdate.
func (s StorageProfileUpdate) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "disks", s.Disks)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type SystemData.
func (s SystemData) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populateTimeRFC3339(objectMap, "createdAt", s.CreatedAt)
	populate(objectMap, "createdBy", s.CreatedBy)
	populate(objectMap, "createdByType", s.CreatedByType)
	populateTimeRFC3339(objectMap, "lastModifiedAt", s.LastModifiedAt)
	populate(objectMap, "lastModifiedBy", s.LastModifiedBy)
	populate(objectMap, "lastModifiedByType", s.LastModifiedByType)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type SystemData.
func (s *SystemData) UnmarshalJSON(data []byte) error {
	var rawMsg map[string]json.RawMessage
	if err := json.Unmarshal(data, &rawMsg); err != nil {
		return fmt.Errorf("unmarshalling type %T: %v", s, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "createdAt":
			err = unpopulateTimeRFC3339(val, "CreatedAt", &s.CreatedAt)
			delete(rawMsg, key)
		case "createdBy":
			err = unpopulate(val, "CreatedBy", &s.CreatedBy)
			delete(rawMsg, key)
		case "createdByType":
			err = unpopulate(val, "CreatedByType", &s.CreatedByType)
			delete(rawMsg, key)
		case "lastModifiedAt":
			err = unpopulateTimeRFC3339(val, "LastModifiedAt", &s.LastModifiedAt)
			delete(rawMsg, key)
		case "lastModifiedBy":
			err = unpopulate(val, "LastModifiedBy", &s.LastModifiedBy)
			delete(rawMsg, key)
		case "lastModifiedByType":
			err = unpopulate(val, "LastModifiedByType", &s.LastModifiedByType)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", s, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type VMMServer.
func (v VMMServer) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "extendedLocation", v.ExtendedLocation)
	populate(objectMap, "id", v.ID)
	populate(objectMap, "location", v.Location)
	populate(objectMap, "name", v.Name)
	populate(objectMap, "properties", v.Properties)
	populate(objectMap, "systemData", v.SystemData)
	populate(objectMap, "tags", v.Tags)
	populate(objectMap, "type", v.Type)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachine.
func (v VirtualMachine) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "extendedLocation", v.ExtendedLocation)
	populate(objectMap, "id", v.ID)
	populate(objectMap, "location", v.Location)
	populate(objectMap, "name", v.Name)
	populate(objectMap, "properties", v.Properties)
	populate(objectMap, "systemData", v.SystemData)
	populate(objectMap, "tags", v.Tags)
	populate(objectMap, "type", v.Type)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineInventoryItem.
func (v VirtualMachineInventoryItem) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "cloud", v.Cloud)
	populate(objectMap, "ipAddresses", v.IPAddresses)
	populate(objectMap, "inventoryItemName", v.InventoryItemName)
	objectMap["inventoryType"] = InventoryTypeVirtualMachine
	populate(objectMap, "managedResourceId", v.ManagedResourceID)
	populate(objectMap, "osName", v.OSName)
	populate(objectMap, "osType", v.OSType)
	populate(objectMap, "powerState", v.PowerState)
	populate(objectMap, "provisioningState", v.ProvisioningState)
	populate(objectMap, "uuid", v.UUID)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type VirtualMachineInventoryItem.
func (v *VirtualMachineInventoryItem) UnmarshalJSON(data []byte) error {
	var rawMsg map[string]json.RawMessage
	if err := json.Unmarshal(data, &rawMsg); err != nil {
		return fmt.Errorf("unmarshalling type %T: %v", v, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "cloud":
			err = unpopulate(val, "Cloud", &v.Cloud)
			delete(rawMsg, key)
		case "ipAddresses":
			err = unpopulate(val, "IPAddresses", &v.IPAddresses)
			delete(rawMsg, key)
		case "inventoryItemName":
			err = unpopulate(val, "InventoryItemName", &v.InventoryItemName)
			delete(rawMsg, key)
		case "inventoryType":
			err = unpopulate(val, "InventoryType", &v.InventoryType)
			delete(rawMsg, key)
		case "managedResourceId":
			err = unpopulate(val, "ManagedResourceID", &v.ManagedResourceID)
			delete(rawMsg, key)
		case "osName":
			err = unpopulate(val, "OSName", &v.OSName)
			delete(rawMsg, key)
		case "osType":
			err = unpopulate(val, "OSType", &v.OSType)
			delete(rawMsg, key)
		case "powerState":
			err = unpopulate(val, "PowerState", &v.PowerState)
			delete(rawMsg, key)
		case "provisioningState":
			err = unpopulate(val, "ProvisioningState", &v.ProvisioningState)
			delete(rawMsg, key)
		case "uuid":
			err = unpopulate(val, "UUID", &v.UUID)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", v, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineProperties.
func (v VirtualMachineProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "availabilitySets", v.AvailabilitySets)
	populate(objectMap, "checkpointType", v.CheckpointType)
	populate(objectMap, "checkpoints", v.Checkpoints)
	populate(objectMap, "cloudId", v.CloudID)
	populate(objectMap, "generation", v.Generation)
	populate(objectMap, "hardwareProfile", v.HardwareProfile)
	populate(objectMap, "inventoryItemId", v.InventoryItemID)
	populate(objectMap, "networkProfile", v.NetworkProfile)
	populate(objectMap, "osProfile", v.OSProfile)
	populate(objectMap, "powerState", v.PowerState)
	populate(objectMap, "provisioningState", v.ProvisioningState)
	populate(objectMap, "storageProfile", v.StorageProfile)
	populate(objectMap, "templateId", v.TemplateID)
	populate(objectMap, "uuid", v.UUID)
	populate(objectMap, "vmName", v.VMName)
	populate(objectMap, "vmmServerId", v.VmmServerID)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineTemplate.
func (v VirtualMachineTemplate) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "extendedLocation", v.ExtendedLocation)
	populate(objectMap, "id", v.ID)
	populate(objectMap, "location", v.Location)
	populate(objectMap, "name", v.Name)
	populate(objectMap, "properties", v.Properties)
	populate(objectMap, "systemData", v.SystemData)
	populate(objectMap, "tags", v.Tags)
	populate(objectMap, "type", v.Type)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineTemplateInventoryItem.
func (v VirtualMachineTemplateInventoryItem) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "cpuCount", v.CPUCount)
	populate(objectMap, "inventoryItemName", v.InventoryItemName)
	objectMap["inventoryType"] = InventoryTypeVirtualMachineTemplate
	populate(objectMap, "managedResourceId", v.ManagedResourceID)
	populate(objectMap, "memoryMB", v.MemoryMB)
	populate(objectMap, "osName", v.OSName)
	populate(objectMap, "osType", v.OSType)
	populate(objectMap, "provisioningState", v.ProvisioningState)
	populate(objectMap, "uuid", v.UUID)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type VirtualMachineTemplateInventoryItem.
func (v *VirtualMachineTemplateInventoryItem) UnmarshalJSON(data []byte) error {
	var rawMsg map[string]json.RawMessage
	if err := json.Unmarshal(data, &rawMsg); err != nil {
		return fmt.Errorf("unmarshalling type %T: %v", v, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "cpuCount":
			err = unpopulate(val, "CPUCount", &v.CPUCount)
			delete(rawMsg, key)
		case "inventoryItemName":
			err = unpopulate(val, "InventoryItemName", &v.InventoryItemName)
			delete(rawMsg, key)
		case "inventoryType":
			err = unpopulate(val, "InventoryType", &v.InventoryType)
			delete(rawMsg, key)
		case "managedResourceId":
			err = unpopulate(val, "ManagedResourceID", &v.ManagedResourceID)
			delete(rawMsg, key)
		case "memoryMB":
			err = unpopulate(val, "MemoryMB", &v.MemoryMB)
			delete(rawMsg, key)
		case "osName":
			err = unpopulate(val, "OSName", &v.OSName)
			delete(rawMsg, key)
		case "osType":
			err = unpopulate(val, "OSType", &v.OSType)
			delete(rawMsg, key)
		case "provisioningState":
			err = unpopulate(val, "ProvisioningState", &v.ProvisioningState)
			delete(rawMsg, key)
		case "uuid":
			err = unpopulate(val, "UUID", &v.UUID)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", v, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineTemplateProperties.
func (v VirtualMachineTemplateProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "cpuCount", v.CPUCount)
	populate(objectMap, "computerName", v.ComputerName)
	populate(objectMap, "disks", v.Disks)
	populate(objectMap, "dynamicMemoryEnabled", v.DynamicMemoryEnabled)
	populate(objectMap, "dynamicMemoryMaxMB", v.DynamicMemoryMaxMB)
	populate(objectMap, "dynamicMemoryMinMB", v.DynamicMemoryMinMB)
	populate(objectMap, "generation", v.Generation)
	populate(objectMap, "inventoryItemId", v.InventoryItemID)
	populate(objectMap, "isCustomizable", v.IsCustomizable)
	populate(objectMap, "isHighlyAvailable", v.IsHighlyAvailable)
	populate(objectMap, "limitCpuForMigration", v.LimitCPUForMigration)
	populate(objectMap, "memoryMB", v.MemoryMB)
	populate(objectMap, "networkInterfaces", v.NetworkInterfaces)
	populate(objectMap, "osName", v.OSName)
	populate(objectMap, "osType", v.OSType)
	populate(objectMap, "provisioningState", v.ProvisioningState)
	populate(objectMap, "uuid", v.UUID)
	populate(objectMap, "vmmServerId", v.VmmServerID)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineUpdate.
func (v VirtualMachineUpdate) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "properties", v.Properties)
	populate(objectMap, "tags", v.Tags)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualMachineUpdateProperties.
func (v VirtualMachineUpdateProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "availabilitySets", v.AvailabilitySets)
	populate(objectMap, "hardwareProfile", v.HardwareProfile)
	populate(objectMap, "networkProfile", v.NetworkProfile)
	populate(objectMap, "storageProfile", v.StorageProfile)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualNetwork.
func (v VirtualNetwork) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "extendedLocation", v.ExtendedLocation)
	populate(objectMap, "id", v.ID)
	populate(objectMap, "location", v.Location)
	populate(objectMap, "name", v.Name)
	populate(objectMap, "properties", v.Properties)
	populate(objectMap, "systemData", v.SystemData)
	populate(objectMap, "tags", v.Tags)
	populate(objectMap, "type", v.Type)
	return json.Marshal(objectMap)
}

// MarshalJSON implements the json.Marshaller interface for type VirtualNetworkInventoryItem.
func (v VirtualNetworkInventoryItem) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	populate(objectMap, "inventoryItemName", v.InventoryItemName)
	objectMap["inventoryType"] = InventoryTypeVirtualNetwork
	populate(objectMap, "managedResourceId", v.ManagedResourceID)
	populate(objectMap, "provisioningState", v.ProvisioningState)
	populate(objectMap, "uuid", v.UUID)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type VirtualNetworkInventoryItem.
func (v *VirtualNetworkInventoryItem) UnmarshalJSON(data []byte) error {
	var rawMsg map[string]json.RawMessage
	if err := json.Unmarshal(data, &rawMsg); err != nil {
		return fmt.Errorf("unmarshalling type %T: %v", v, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "inventoryItemName":
			err = unpopulate(val, "InventoryItemName", &v.InventoryItemName)
			delete(rawMsg, key)
		case "inventoryType":
			err = unpopulate(val, "InventoryType", &v.InventoryType)
			delete(rawMsg, key)
		case "managedResourceId":
			err = unpopulate(val, "ManagedResourceID", &v.ManagedResourceID)
			delete(rawMsg, key)
		case "provisioningState":
			err = unpopulate(val, "ProvisioningState", &v.ProvisioningState)
			delete(rawMsg, key)
		case "uuid":
			err = unpopulate(val, "UUID", &v.UUID)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", v, err)
		}
	}
	return nil
}

func populate(m map[string]interface{}, k string, v interface{}) {
	if v == nil {
		return
	} else if azcore.IsNullValue(v) {
		m[k] = nil
	} else if !reflect.ValueOf(v).IsNil() {
		m[k] = v
	}
}

func unpopulate(data json.RawMessage, fn string, v interface{}) error {
	if data == nil {
		return nil
	}
	if err := json.Unmarshal(data, v); err != nil {
		return fmt.Errorf("struct field %s: %v", fn, err)
	}
	return nil
}
