//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.
// DO NOT EDIT.

package armcommerce

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

// MarshalJSON implements the json.Marshaller interface for type ErrorResponse.
func (e ErrorResponse) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "code", e.Code)
	populate(objectMap, "message", e.Message)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type ErrorResponse.
func (e *ErrorResponse) 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", e, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "code":
			err = unpopulate(val, "Code", &e.Code)
			delete(rawMsg, key)
		case "message":
			err = unpopulate(val, "Message", &e.Message)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", e, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type InfoField.
func (i InfoField) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "project", i.Project)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type InfoField.
func (i *InfoField) 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 "project":
			err = unpopulate(val, "Project", &i.Project)
			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 MeterInfo.
func (m MeterInfo) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populateTimeRFC3339(objectMap, "EffectiveDate", m.EffectiveDate)
	populate(objectMap, "IncludedQuantity", m.IncludedQuantity)
	populate(objectMap, "MeterCategory", m.MeterCategory)
	populate(objectMap, "MeterId", m.MeterID)
	populate(objectMap, "MeterName", m.MeterName)
	populate(objectMap, "MeterRates", m.MeterRates)
	populate(objectMap, "MeterRegion", m.MeterRegion)
	populate(objectMap, "MeterSubCategory", m.MeterSubCategory)
	populate(objectMap, "MeterTags", m.MeterTags)
	populate(objectMap, "Unit", m.Unit)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type MeterInfo.
func (m *MeterInfo) 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", m, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "EffectiveDate":
			err = unpopulateTimeRFC3339(val, "EffectiveDate", &m.EffectiveDate)
			delete(rawMsg, key)
		case "IncludedQuantity":
			err = unpopulate(val, "IncludedQuantity", &m.IncludedQuantity)
			delete(rawMsg, key)
		case "MeterCategory":
			err = unpopulate(val, "MeterCategory", &m.MeterCategory)
			delete(rawMsg, key)
		case "MeterId":
			err = unpopulate(val, "MeterID", &m.MeterID)
			delete(rawMsg, key)
		case "MeterName":
			err = unpopulate(val, "MeterName", &m.MeterName)
			delete(rawMsg, key)
		case "MeterRates":
			err = unpopulate(val, "MeterRates", &m.MeterRates)
			delete(rawMsg, key)
		case "MeterRegion":
			err = unpopulate(val, "MeterRegion", &m.MeterRegion)
			delete(rawMsg, key)
		case "MeterSubCategory":
			err = unpopulate(val, "MeterSubCategory", &m.MeterSubCategory)
			delete(rawMsg, key)
		case "MeterTags":
			err = unpopulate(val, "MeterTags", &m.MeterTags)
			delete(rawMsg, key)
		case "Unit":
			err = unpopulate(val, "Unit", &m.Unit)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", m, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type MonetaryCommitment.
func (m MonetaryCommitment) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populateTimeRFC3339(objectMap, "EffectiveDate", m.EffectiveDate)
	populate(objectMap, "ExcludedMeterIds", m.ExcludedMeterIDs)
	objectMap["Name"] = OfferTermInfoMonetaryCommitment
	populate(objectMap, "TieredDiscount", m.TieredDiscount)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type MonetaryCommitment.
func (m *MonetaryCommitment) 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", m, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "EffectiveDate":
			err = unpopulateTimeRFC3339(val, "EffectiveDate", &m.EffectiveDate)
			delete(rawMsg, key)
		case "ExcludedMeterIds":
			err = unpopulate(val, "ExcludedMeterIDs", &m.ExcludedMeterIDs)
			delete(rawMsg, key)
		case "Name":
			err = unpopulate(val, "Name", &m.Name)
			delete(rawMsg, key)
		case "TieredDiscount":
			err = unpopulate(val, "TieredDiscount", &m.TieredDiscount)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", m, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type MonetaryCredit.
func (m MonetaryCredit) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "Credit", m.Credit)
	populateTimeRFC3339(objectMap, "EffectiveDate", m.EffectiveDate)
	populate(objectMap, "ExcludedMeterIds", m.ExcludedMeterIDs)
	objectMap["Name"] = OfferTermInfoMonetaryCredit
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type MonetaryCredit.
func (m *MonetaryCredit) 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", m, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "Credit":
			err = unpopulate(val, "Credit", &m.Credit)
			delete(rawMsg, key)
		case "EffectiveDate":
			err = unpopulateTimeRFC3339(val, "EffectiveDate", &m.EffectiveDate)
			delete(rawMsg, key)
		case "ExcludedMeterIds":
			err = unpopulate(val, "ExcludedMeterIDs", &m.ExcludedMeterIDs)
			delete(rawMsg, key)
		case "Name":
			err = unpopulate(val, "Name", &m.Name)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", m, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type OfferTermInfoAutoGenerated.
func (o OfferTermInfoAutoGenerated) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populateTimeRFC3339(objectMap, "EffectiveDate", o.EffectiveDate)
	objectMap["Name"] = o.Name
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type OfferTermInfoAutoGenerated.
func (o *OfferTermInfoAutoGenerated) 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", o, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "EffectiveDate":
			err = unpopulateTimeRFC3339(val, "EffectiveDate", &o.EffectiveDate)
			delete(rawMsg, key)
		case "Name":
			err = unpopulate(val, "Name", &o.Name)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", o, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type RateCardQueryParameters.
func (r RateCardQueryParameters) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "Currency", r.Currency)
	populate(objectMap, "Locale", r.Locale)
	populate(objectMap, "OfferDurableId", r.OfferDurableID)
	populate(objectMap, "RegionInfo", r.RegionInfo)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type RateCardQueryParameters.
func (r *RateCardQueryParameters) 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", r, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "Currency":
			err = unpopulate(val, "Currency", &r.Currency)
			delete(rawMsg, key)
		case "Locale":
			err = unpopulate(val, "Locale", &r.Locale)
			delete(rawMsg, key)
		case "OfferDurableId":
			err = unpopulate(val, "OfferDurableID", &r.OfferDurableID)
			delete(rawMsg, key)
		case "RegionInfo":
			err = unpopulate(val, "RegionInfo", &r.RegionInfo)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", r, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type RecurringCharge.
func (r RecurringCharge) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populateTimeRFC3339(objectMap, "EffectiveDate", r.EffectiveDate)
	objectMap["Name"] = OfferTermInfoRecurringCharge
	populate(objectMap, "RecurringCharge", r.RecurringCharge)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type RecurringCharge.
func (r *RecurringCharge) 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", r, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "EffectiveDate":
			err = unpopulateTimeRFC3339(val, "EffectiveDate", &r.EffectiveDate)
			delete(rawMsg, key)
		case "Name":
			err = unpopulate(val, "Name", &r.Name)
			delete(rawMsg, key)
		case "RecurringCharge":
			err = unpopulate(val, "RecurringCharge", &r.RecurringCharge)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", r, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type ResourceRateCardInfo.
func (r ResourceRateCardInfo) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "Currency", r.Currency)
	populate(objectMap, "IsTaxIncluded", r.IsTaxIncluded)
	populate(objectMap, "Locale", r.Locale)
	populate(objectMap, "Meters", r.Meters)
	populate(objectMap, "OfferTerms", r.OfferTerms)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type ResourceRateCardInfo.
func (r *ResourceRateCardInfo) 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", r, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "Currency":
			err = unpopulate(val, "Currency", &r.Currency)
			delete(rawMsg, key)
		case "IsTaxIncluded":
			err = unpopulate(val, "IsTaxIncluded", &r.IsTaxIncluded)
			delete(rawMsg, key)
		case "Locale":
			err = unpopulate(val, "Locale", &r.Locale)
			delete(rawMsg, key)
		case "Meters":
			err = unpopulate(val, "Meters", &r.Meters)
			delete(rawMsg, key)
		case "OfferTerms":
			r.OfferTerms, err = unmarshalOfferTermInfoAutoGeneratedClassificationArray(val)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", r, err)
		}
	}
	return nil
}

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

// UnmarshalJSON implements the json.Unmarshaller interface for type UsageAggregation.
func (u *UsageAggregation) 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", u, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "id":
			err = unpopulate(val, "ID", &u.ID)
			delete(rawMsg, key)
		case "name":
			err = unpopulate(val, "Name", &u.Name)
			delete(rawMsg, key)
		case "properties":
			err = unpopulate(val, "Properties", &u.Properties)
			delete(rawMsg, key)
		case "type":
			err = unpopulate(val, "Type", &u.Type)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", u, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type UsageAggregationListResult.
func (u UsageAggregationListResult) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "nextLink", u.NextLink)
	populate(objectMap, "value", u.Value)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type UsageAggregationListResult.
func (u *UsageAggregationListResult) 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", u, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "nextLink":
			err = unpopulate(val, "NextLink", &u.NextLink)
			delete(rawMsg, key)
		case "value":
			err = unpopulate(val, "Value", &u.Value)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", u, err)
		}
	}
	return nil
}

// MarshalJSON implements the json.Marshaller interface for type UsageSample.
func (u UsageSample) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]any)
	populate(objectMap, "infoFields", u.InfoFields)
	populate(objectMap, "instanceData", u.InstanceData)
	populate(objectMap, "meterCategory", u.MeterCategory)
	populate(objectMap, "meterId", u.MeterID)
	populate(objectMap, "meterName", u.MeterName)
	populate(objectMap, "meterRegion", u.MeterRegion)
	populate(objectMap, "meterSubCategory", u.MeterSubCategory)
	populate(objectMap, "quantity", u.Quantity)
	populate(objectMap, "subscriptionId", u.SubscriptionID)
	populate(objectMap, "unit", u.Unit)
	populateTimeRFC3339(objectMap, "usageEndTime", u.UsageEndTime)
	populateTimeRFC3339(objectMap, "usageStartTime", u.UsageStartTime)
	return json.Marshal(objectMap)
}

// UnmarshalJSON implements the json.Unmarshaller interface for type UsageSample.
func (u *UsageSample) 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", u, err)
	}
	for key, val := range rawMsg {
		var err error
		switch key {
		case "infoFields":
			err = unpopulate(val, "InfoFields", &u.InfoFields)
			delete(rawMsg, key)
		case "instanceData":
			err = unpopulate(val, "InstanceData", &u.InstanceData)
			delete(rawMsg, key)
		case "meterCategory":
			err = unpopulate(val, "MeterCategory", &u.MeterCategory)
			delete(rawMsg, key)
		case "meterId":
			err = unpopulate(val, "MeterID", &u.MeterID)
			delete(rawMsg, key)
		case "meterName":
			err = unpopulate(val, "MeterName", &u.MeterName)
			delete(rawMsg, key)
		case "meterRegion":
			err = unpopulate(val, "MeterRegion", &u.MeterRegion)
			delete(rawMsg, key)
		case "meterSubCategory":
			err = unpopulate(val, "MeterSubCategory", &u.MeterSubCategory)
			delete(rawMsg, key)
		case "quantity":
			err = unpopulate(val, "Quantity", &u.Quantity)
			delete(rawMsg, key)
		case "subscriptionId":
			err = unpopulate(val, "SubscriptionID", &u.SubscriptionID)
			delete(rawMsg, key)
		case "unit":
			err = unpopulate(val, "Unit", &u.Unit)
			delete(rawMsg, key)
		case "usageEndTime":
			err = unpopulateTimeRFC3339(val, "UsageEndTime", &u.UsageEndTime)
			delete(rawMsg, key)
		case "usageStartTime":
			err = unpopulateTimeRFC3339(val, "UsageStartTime", &u.UsageStartTime)
			delete(rawMsg, key)
		}
		if err != nil {
			return fmt.Errorf("unmarshalling type %T: %v", u, err)
		}
	}
	return nil
}

func populate(m map[string]any, k string, v any) {
	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 any) 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
}
