package advisor

// Copyright (c) Microsoft and contributors.  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.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

import (
	"context"
	"encoding/json"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/date"
	"github.com/Azure/go-autorest/autorest/to"
	"github.com/Azure/go-autorest/tracing"
	"github.com/gofrs/uuid"
	"net/http"
)

// The package's fully qualified name.
const fqdn = "github.com/Azure/azure-sdk-for-go/services/advisor/mgmt/2020-01-01/advisor"

// ArmErrorResponse ...
type ArmErrorResponse struct {
	Error *ARMErrorResponseBody `json:"error,omitempty"`
}

// ARMErrorResponseBody ARM error response body.
type ARMErrorResponseBody struct {
	// Message - Gets or sets the string that describes the error in detail and provides debugging information.
	Message *string `json:"message,omitempty"`
	// Code - Gets or sets the string that can be used to programmatically identify the error.
	Code *string `json:"code,omitempty"`
}

// ConfigData the Advisor configuration data structure.
type ConfigData struct {
	autorest.Response `json:"-"`
	// ConfigDataProperties - The Advisor configuration data structure.
	*ConfigDataProperties `json:"properties,omitempty"`
	// ID - READ-ONLY; The resource ID.
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource.
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ConfigData.
func (cd ConfigData) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if cd.ConfigDataProperties != nil {
		objectMap["properties"] = cd.ConfigDataProperties
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ConfigData struct.
func (cd *ConfigData) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var configDataProperties ConfigDataProperties
				err = json.Unmarshal(*v, &configDataProperties)
				if err != nil {
					return err
				}
				cd.ConfigDataProperties = &configDataProperties
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				cd.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				cd.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				cd.Type = &typeVar
			}
		}
	}

	return nil
}

// ConfigDataProperties configuration data properties
type ConfigDataProperties struct {
	// Exclude - Exclude the resource from Advisor evaluations. Valid values: False (default) or True.
	Exclude *bool `json:"exclude,omitempty"`
	// LowCPUThreshold - Minimum percentage threshold for Advisor low CPU utilization evaluation. Valid only for subscriptions. Valid values: 5 (default), 10, 15 or 20. Possible values include: 'Five', 'OneZero', 'OneFive', 'TwoZero'
	LowCPUThreshold CPUThreshold `json:"lowCpuThreshold,omitempty"`
	// Digests - Advisor digest configuration. Valid only for subscriptions
	Digests *[]DigestConfig `json:"digests,omitempty"`
}

// ConfigurationListResult the list of Advisor configurations.
type ConfigurationListResult struct {
	autorest.Response `json:"-"`
	// Value - The list of configurations.
	Value *[]ConfigData `json:"value,omitempty"`
	// NextLink - The link used to get the next page of configurations.
	NextLink *string `json:"nextLink,omitempty"`
}

// ConfigurationListResultIterator provides access to a complete listing of ConfigData values.
type ConfigurationListResultIterator struct {
	i    int
	page ConfigurationListResultPage
}

// NextWithContext advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
func (iter *ConfigurationListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/ConfigurationListResultIterator.NextWithContext")
		defer func() {
			sc := -1
			if iter.Response().Response.Response != nil {
				sc = iter.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err = iter.page.NextWithContext(ctx)
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// Next advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (iter *ConfigurationListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter ConfigurationListResultIterator) NotDone() bool {
	return iter.page.NotDone() && iter.i < len(iter.page.Values())
}

// Response returns the raw server response from the last page request.
func (iter ConfigurationListResultIterator) Response() ConfigurationListResult {
	return iter.page.Response()
}

// Value returns the current value or a zero-initialized value if the
// iterator has advanced beyond the end of the collection.
func (iter ConfigurationListResultIterator) Value() ConfigData {
	if !iter.page.NotDone() {
		return ConfigData{}
	}
	return iter.page.Values()[iter.i]
}

// Creates a new instance of the ConfigurationListResultIterator type.
func NewConfigurationListResultIterator(page ConfigurationListResultPage) ConfigurationListResultIterator {
	return ConfigurationListResultIterator{page: page}
}

// IsEmpty returns true if the ListResult contains no values.
func (clr ConfigurationListResult) IsEmpty() bool {
	return clr.Value == nil || len(*clr.Value) == 0
}

// hasNextLink returns true if the NextLink is not empty.
func (clr ConfigurationListResult) hasNextLink() bool {
	return clr.NextLink != nil && len(*clr.NextLink) != 0
}

// configurationListResultPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (clr ConfigurationListResult) configurationListResultPreparer(ctx context.Context) (*http.Request, error) {
	if !clr.hasNextLink() {
		return nil, nil
	}
	return autorest.Prepare((&http.Request{}).WithContext(ctx),
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(clr.NextLink)))
}

// ConfigurationListResultPage contains a page of ConfigData values.
type ConfigurationListResultPage struct {
	fn  func(context.Context, ConfigurationListResult) (ConfigurationListResult, error)
	clr ConfigurationListResult
}

// NextWithContext advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
func (page *ConfigurationListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/ConfigurationListResultPage.NextWithContext")
		defer func() {
			sc := -1
			if page.Response().Response.Response != nil {
				sc = page.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	for {
		next, err := page.fn(ctx, page.clr)
		if err != nil {
			return err
		}
		page.clr = next
		if !next.hasNextLink() || !next.IsEmpty() {
			break
		}
	}
	return nil
}

// Next advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (page *ConfigurationListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

// NotDone returns true if the page enumeration should be started or is not yet complete.
func (page ConfigurationListResultPage) NotDone() bool {
	return !page.clr.IsEmpty()
}

// Response returns the raw server response from the last page request.
func (page ConfigurationListResultPage) Response() ConfigurationListResult {
	return page.clr
}

// Values returns the slice of values for the current page or nil if there are no values.
func (page ConfigurationListResultPage) Values() []ConfigData {
	if page.clr.IsEmpty() {
		return nil
	}
	return *page.clr.Value
}

// Creates a new instance of the ConfigurationListResultPage type.
func NewConfigurationListResultPage(cur ConfigurationListResult, getNextPage func(context.Context, ConfigurationListResult) (ConfigurationListResult, error)) ConfigurationListResultPage {
	return ConfigurationListResultPage{
		fn:  getNextPage,
		clr: cur,
	}
}

// DigestConfig advisor Digest configuration entity
type DigestConfig struct {
	// Name - Name of digest configuration. Value is case-insensitive and must be unique within a subscription.
	Name *string `json:"name,omitempty"`
	// ActionGroupResourceID - Action group resource id used by digest.
	ActionGroupResourceID *string `json:"actionGroupResourceId,omitempty"`
	// Frequency - Frequency that digest will be triggered, in days. Value must be between 7 and 30 days inclusive.
	Frequency *int32 `json:"frequency,omitempty"`
	// Categories - Categories to send digest for. If categories are not provided, then digest will be sent for all categories.
	Categories *[]Category `json:"categories,omitempty"`
	// Language - Language for digest content body. Value must be ISO 639-1 code for one of Azure portal supported languages. Otherwise, it will be converted into one. Default value is English (en).
	Language *string `json:"language,omitempty"`
	// State - State of digest configuration. Possible values include: 'Active', 'Disabled'
	State DigestConfigState `json:"state,omitempty"`
}

// MetadataEntity the metadata entity contract.
type MetadataEntity struct {
	// ID - The resource Id of the metadata entity.
	ID *string `json:"id,omitempty"`
	// Type - The type of the metadata entity.
	Type *string `json:"type,omitempty"`
	// Name - The name of the metadata entity.
	Name *string `json:"name,omitempty"`
	// MetadataEntityProperties - The metadata entity properties.
	*MetadataEntityProperties `json:"properties,omitempty"`
}

// MarshalJSON is the custom marshaler for MetadataEntity.
func (me MetadataEntity) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if me.ID != nil {
		objectMap["id"] = me.ID
	}
	if me.Type != nil {
		objectMap["type"] = me.Type
	}
	if me.Name != nil {
		objectMap["name"] = me.Name
	}
	if me.MetadataEntityProperties != nil {
		objectMap["properties"] = me.MetadataEntityProperties
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for MetadataEntity struct.
func (me *MetadataEntity) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				me.ID = &ID
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				me.Type = &typeVar
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				me.Name = &name
			}
		case "properties":
			if v != nil {
				var metadataEntityProperties MetadataEntityProperties
				err = json.Unmarshal(*v, &metadataEntityProperties)
				if err != nil {
					return err
				}
				me.MetadataEntityProperties = &metadataEntityProperties
			}
		}
	}

	return nil
}

// MetadataEntityListResult the list of metadata entities
type MetadataEntityListResult struct {
	autorest.Response `json:"-"`
	// Value - The list of metadata entities.
	Value *[]MetadataEntity `json:"value,omitempty"`
	// NextLink - The link used to get the next page of metadata.
	NextLink *string `json:"nextLink,omitempty"`
}

// MetadataEntityListResultIterator provides access to a complete listing of MetadataEntity values.
type MetadataEntityListResultIterator struct {
	i    int
	page MetadataEntityListResultPage
}

// NextWithContext advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
func (iter *MetadataEntityListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/MetadataEntityListResultIterator.NextWithContext")
		defer func() {
			sc := -1
			if iter.Response().Response.Response != nil {
				sc = iter.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err = iter.page.NextWithContext(ctx)
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// Next advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (iter *MetadataEntityListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter MetadataEntityListResultIterator) NotDone() bool {
	return iter.page.NotDone() && iter.i < len(iter.page.Values())
}

// Response returns the raw server response from the last page request.
func (iter MetadataEntityListResultIterator) Response() MetadataEntityListResult {
	return iter.page.Response()
}

// Value returns the current value or a zero-initialized value if the
// iterator has advanced beyond the end of the collection.
func (iter MetadataEntityListResultIterator) Value() MetadataEntity {
	if !iter.page.NotDone() {
		return MetadataEntity{}
	}
	return iter.page.Values()[iter.i]
}

// Creates a new instance of the MetadataEntityListResultIterator type.
func NewMetadataEntityListResultIterator(page MetadataEntityListResultPage) MetadataEntityListResultIterator {
	return MetadataEntityListResultIterator{page: page}
}

// IsEmpty returns true if the ListResult contains no values.
func (melr MetadataEntityListResult) IsEmpty() bool {
	return melr.Value == nil || len(*melr.Value) == 0
}

// hasNextLink returns true if the NextLink is not empty.
func (melr MetadataEntityListResult) hasNextLink() bool {
	return melr.NextLink != nil && len(*melr.NextLink) != 0
}

// metadataEntityListResultPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (melr MetadataEntityListResult) metadataEntityListResultPreparer(ctx context.Context) (*http.Request, error) {
	if !melr.hasNextLink() {
		return nil, nil
	}
	return autorest.Prepare((&http.Request{}).WithContext(ctx),
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(melr.NextLink)))
}

// MetadataEntityListResultPage contains a page of MetadataEntity values.
type MetadataEntityListResultPage struct {
	fn   func(context.Context, MetadataEntityListResult) (MetadataEntityListResult, error)
	melr MetadataEntityListResult
}

// NextWithContext advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
func (page *MetadataEntityListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/MetadataEntityListResultPage.NextWithContext")
		defer func() {
			sc := -1
			if page.Response().Response.Response != nil {
				sc = page.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	for {
		next, err := page.fn(ctx, page.melr)
		if err != nil {
			return err
		}
		page.melr = next
		if !next.hasNextLink() || !next.IsEmpty() {
			break
		}
	}
	return nil
}

// Next advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (page *MetadataEntityListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

// NotDone returns true if the page enumeration should be started or is not yet complete.
func (page MetadataEntityListResultPage) NotDone() bool {
	return !page.melr.IsEmpty()
}

// Response returns the raw server response from the last page request.
func (page MetadataEntityListResultPage) Response() MetadataEntityListResult {
	return page.melr
}

// Values returns the slice of values for the current page or nil if there are no values.
func (page MetadataEntityListResultPage) Values() []MetadataEntity {
	if page.melr.IsEmpty() {
		return nil
	}
	return *page.melr.Value
}

// Creates a new instance of the MetadataEntityListResultPage type.
func NewMetadataEntityListResultPage(cur MetadataEntityListResult, getNextPage func(context.Context, MetadataEntityListResult) (MetadataEntityListResult, error)) MetadataEntityListResultPage {
	return MetadataEntityListResultPage{
		fn:   getNextPage,
		melr: cur,
	}
}

// MetadataEntityProperties the metadata entity properties
type MetadataEntityProperties struct {
	// DisplayName - The display name.
	DisplayName *string `json:"displayName,omitempty"`
	// DependsOn - The list of keys on which this entity depends on.
	DependsOn *[]string `json:"dependsOn,omitempty"`
	// ApplicableScenarios - The list of scenarios applicable to this metadata entity.
	ApplicableScenarios *[]Scenario `json:"applicableScenarios,omitempty"`
	// SupportedValues - The list of supported values.
	SupportedValues *[]MetadataSupportedValueDetail `json:"supportedValues,omitempty"`
}

// MetadataSupportedValueDetail the metadata supported value detail.
type MetadataSupportedValueDetail struct {
	// ID - The id.
	ID *string `json:"id,omitempty"`
	// DisplayName - The display name.
	DisplayName *string `json:"displayName,omitempty"`
}

// OperationDisplayInfo the operation supported by Advisor.
type OperationDisplayInfo struct {
	// Description - The description of the operation.
	Description *string `json:"description,omitempty"`
	// Operation - The action that users can perform, based on their permission level.
	Operation *string `json:"operation,omitempty"`
	// Provider - Service provider: Microsoft Advisor.
	Provider *string `json:"provider,omitempty"`
	// Resource - Resource on which the operation is performed.
	Resource *string `json:"resource,omitempty"`
}

// OperationEntity the operation supported by Advisor.
type OperationEntity struct {
	// Name - Operation name: {provider}/{resource}/{operation}.
	Name *string `json:"name,omitempty"`
	// Display - The operation supported by Advisor.
	Display *OperationDisplayInfo `json:"display,omitempty"`
}

// OperationEntityListResult the list of Advisor operations.
type OperationEntityListResult struct {
	autorest.Response `json:"-"`
	// NextLink - The link used to get the next page of operations.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - The list of operations.
	Value *[]OperationEntity `json:"value,omitempty"`
}

// OperationEntityListResultIterator provides access to a complete listing of OperationEntity values.
type OperationEntityListResultIterator struct {
	i    int
	page OperationEntityListResultPage
}

// NextWithContext advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
func (iter *OperationEntityListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/OperationEntityListResultIterator.NextWithContext")
		defer func() {
			sc := -1
			if iter.Response().Response.Response != nil {
				sc = iter.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err = iter.page.NextWithContext(ctx)
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// Next advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (iter *OperationEntityListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter OperationEntityListResultIterator) NotDone() bool {
	return iter.page.NotDone() && iter.i < len(iter.page.Values())
}

// Response returns the raw server response from the last page request.
func (iter OperationEntityListResultIterator) Response() OperationEntityListResult {
	return iter.page.Response()
}

// Value returns the current value or a zero-initialized value if the
// iterator has advanced beyond the end of the collection.
func (iter OperationEntityListResultIterator) Value() OperationEntity {
	if !iter.page.NotDone() {
		return OperationEntity{}
	}
	return iter.page.Values()[iter.i]
}

// Creates a new instance of the OperationEntityListResultIterator type.
func NewOperationEntityListResultIterator(page OperationEntityListResultPage) OperationEntityListResultIterator {
	return OperationEntityListResultIterator{page: page}
}

// IsEmpty returns true if the ListResult contains no values.
func (oelr OperationEntityListResult) IsEmpty() bool {
	return oelr.Value == nil || len(*oelr.Value) == 0
}

// hasNextLink returns true if the NextLink is not empty.
func (oelr OperationEntityListResult) hasNextLink() bool {
	return oelr.NextLink != nil && len(*oelr.NextLink) != 0
}

// operationEntityListResultPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (oelr OperationEntityListResult) operationEntityListResultPreparer(ctx context.Context) (*http.Request, error) {
	if !oelr.hasNextLink() {
		return nil, nil
	}
	return autorest.Prepare((&http.Request{}).WithContext(ctx),
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(oelr.NextLink)))
}

// OperationEntityListResultPage contains a page of OperationEntity values.
type OperationEntityListResultPage struct {
	fn   func(context.Context, OperationEntityListResult) (OperationEntityListResult, error)
	oelr OperationEntityListResult
}

// NextWithContext advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
func (page *OperationEntityListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/OperationEntityListResultPage.NextWithContext")
		defer func() {
			sc := -1
			if page.Response().Response.Response != nil {
				sc = page.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	for {
		next, err := page.fn(ctx, page.oelr)
		if err != nil {
			return err
		}
		page.oelr = next
		if !next.hasNextLink() || !next.IsEmpty() {
			break
		}
	}
	return nil
}

// Next advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (page *OperationEntityListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

// NotDone returns true if the page enumeration should be started or is not yet complete.
func (page OperationEntityListResultPage) NotDone() bool {
	return !page.oelr.IsEmpty()
}

// Response returns the raw server response from the last page request.
func (page OperationEntityListResultPage) Response() OperationEntityListResult {
	return page.oelr
}

// Values returns the slice of values for the current page or nil if there are no values.
func (page OperationEntityListResultPage) Values() []OperationEntity {
	if page.oelr.IsEmpty() {
		return nil
	}
	return *page.oelr.Value
}

// Creates a new instance of the OperationEntityListResultPage type.
func NewOperationEntityListResultPage(cur OperationEntityListResult, getNextPage func(context.Context, OperationEntityListResult) (OperationEntityListResult, error)) OperationEntityListResultPage {
	return OperationEntityListResultPage{
		fn:   getNextPage,
		oelr: cur,
	}
}

// RecommendationProperties the properties of the recommendation.
type RecommendationProperties struct {
	// Category - The category of the recommendation. Possible values include: 'HighAvailability', 'Security', 'Performance', 'Cost', 'OperationalExcellence'
	Category Category `json:"category,omitempty"`
	// Impact - The business impact of the recommendation. Possible values include: 'High', 'Medium', 'Low'
	Impact Impact `json:"impact,omitempty"`
	// ImpactedField - The resource type identified by Advisor.
	ImpactedField *string `json:"impactedField,omitempty"`
	// ImpactedValue - The resource identified by Advisor.
	ImpactedValue *string `json:"impactedValue,omitempty"`
	// LastUpdated - The most recent time that Advisor checked the validity of the recommendation.
	LastUpdated *date.Time `json:"lastUpdated,omitempty"`
	// Metadata - The recommendation metadata.
	Metadata map[string]interface{} `json:"metadata"`
	// RecommendationTypeID - The recommendation-type GUID.
	RecommendationTypeID *string `json:"recommendationTypeId,omitempty"`
	// Risk - The potential risk of not implementing the recommendation. Possible values include: 'Error', 'Warning', 'None'
	Risk Risk `json:"risk,omitempty"`
	// ShortDescription - A summary of the recommendation.
	ShortDescription *ShortDescription `json:"shortDescription,omitempty"`
	// SuppressionIds - The list of snoozed and dismissed rules for the recommendation.
	SuppressionIds *[]uuid.UUID `json:"suppressionIds,omitempty"`
	// ExtendedProperties - Extended properties
	ExtendedProperties map[string]*string `json:"extendedProperties"`
	// ResourceMetadata - Metadata of resource that was assessed
	ResourceMetadata *ResourceMetadata `json:"resourceMetadata,omitempty"`
}

// MarshalJSON is the custom marshaler for RecommendationProperties.
func (rp RecommendationProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if rp.Category != "" {
		objectMap["category"] = rp.Category
	}
	if rp.Impact != "" {
		objectMap["impact"] = rp.Impact
	}
	if rp.ImpactedField != nil {
		objectMap["impactedField"] = rp.ImpactedField
	}
	if rp.ImpactedValue != nil {
		objectMap["impactedValue"] = rp.ImpactedValue
	}
	if rp.LastUpdated != nil {
		objectMap["lastUpdated"] = rp.LastUpdated
	}
	if rp.Metadata != nil {
		objectMap["metadata"] = rp.Metadata
	}
	if rp.RecommendationTypeID != nil {
		objectMap["recommendationTypeId"] = rp.RecommendationTypeID
	}
	if rp.Risk != "" {
		objectMap["risk"] = rp.Risk
	}
	if rp.ShortDescription != nil {
		objectMap["shortDescription"] = rp.ShortDescription
	}
	if rp.SuppressionIds != nil {
		objectMap["suppressionIds"] = rp.SuppressionIds
	}
	if rp.ExtendedProperties != nil {
		objectMap["extendedProperties"] = rp.ExtendedProperties
	}
	if rp.ResourceMetadata != nil {
		objectMap["resourceMetadata"] = rp.ResourceMetadata
	}
	return json.Marshal(objectMap)
}

// Resource an Azure resource.
type Resource struct {
	// ID - READ-ONLY; The resource ID.
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource.
	Type *string `json:"type,omitempty"`
}

// ResourceMetadata recommendation resource metadata
type ResourceMetadata struct {
	// ResourceID - Azure resource Id of the assessed resource
	ResourceID *string `json:"resourceId,omitempty"`
	// Source - Source from which recommendation is generated
	Source *string `json:"source,omitempty"`
}

// ResourceRecommendationBase advisor Recommendation.
type ResourceRecommendationBase struct {
	autorest.Response `json:"-"`
	// RecommendationProperties - The properties of the recommendation.
	*RecommendationProperties `json:"properties,omitempty"`
	// ID - READ-ONLY; The resource ID.
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource.
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ResourceRecommendationBase.
func (rrb ResourceRecommendationBase) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if rrb.RecommendationProperties != nil {
		objectMap["properties"] = rrb.RecommendationProperties
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ResourceRecommendationBase struct.
func (rrb *ResourceRecommendationBase) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var recommendationProperties RecommendationProperties
				err = json.Unmarshal(*v, &recommendationProperties)
				if err != nil {
					return err
				}
				rrb.RecommendationProperties = &recommendationProperties
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				rrb.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				rrb.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				rrb.Type = &typeVar
			}
		}
	}

	return nil
}

// ResourceRecommendationBaseListResult the list of Advisor recommendations.
type ResourceRecommendationBaseListResult struct {
	autorest.Response `json:"-"`
	// NextLink - The link used to get the next page of recommendations.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - The list of recommendations.
	Value *[]ResourceRecommendationBase `json:"value,omitempty"`
}

// ResourceRecommendationBaseListResultIterator provides access to a complete listing of
// ResourceRecommendationBase values.
type ResourceRecommendationBaseListResultIterator struct {
	i    int
	page ResourceRecommendationBaseListResultPage
}

// NextWithContext advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
func (iter *ResourceRecommendationBaseListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/ResourceRecommendationBaseListResultIterator.NextWithContext")
		defer func() {
			sc := -1
			if iter.Response().Response.Response != nil {
				sc = iter.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err = iter.page.NextWithContext(ctx)
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// Next advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (iter *ResourceRecommendationBaseListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter ResourceRecommendationBaseListResultIterator) NotDone() bool {
	return iter.page.NotDone() && iter.i < len(iter.page.Values())
}

// Response returns the raw server response from the last page request.
func (iter ResourceRecommendationBaseListResultIterator) Response() ResourceRecommendationBaseListResult {
	return iter.page.Response()
}

// Value returns the current value or a zero-initialized value if the
// iterator has advanced beyond the end of the collection.
func (iter ResourceRecommendationBaseListResultIterator) Value() ResourceRecommendationBase {
	if !iter.page.NotDone() {
		return ResourceRecommendationBase{}
	}
	return iter.page.Values()[iter.i]
}

// Creates a new instance of the ResourceRecommendationBaseListResultIterator type.
func NewResourceRecommendationBaseListResultIterator(page ResourceRecommendationBaseListResultPage) ResourceRecommendationBaseListResultIterator {
	return ResourceRecommendationBaseListResultIterator{page: page}
}

// IsEmpty returns true if the ListResult contains no values.
func (rrblr ResourceRecommendationBaseListResult) IsEmpty() bool {
	return rrblr.Value == nil || len(*rrblr.Value) == 0
}

// hasNextLink returns true if the NextLink is not empty.
func (rrblr ResourceRecommendationBaseListResult) hasNextLink() bool {
	return rrblr.NextLink != nil && len(*rrblr.NextLink) != 0
}

// resourceRecommendationBaseListResultPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (rrblr ResourceRecommendationBaseListResult) resourceRecommendationBaseListResultPreparer(ctx context.Context) (*http.Request, error) {
	if !rrblr.hasNextLink() {
		return nil, nil
	}
	return autorest.Prepare((&http.Request{}).WithContext(ctx),
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(rrblr.NextLink)))
}

// ResourceRecommendationBaseListResultPage contains a page of ResourceRecommendationBase values.
type ResourceRecommendationBaseListResultPage struct {
	fn    func(context.Context, ResourceRecommendationBaseListResult) (ResourceRecommendationBaseListResult, error)
	rrblr ResourceRecommendationBaseListResult
}

// NextWithContext advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
func (page *ResourceRecommendationBaseListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/ResourceRecommendationBaseListResultPage.NextWithContext")
		defer func() {
			sc := -1
			if page.Response().Response.Response != nil {
				sc = page.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	for {
		next, err := page.fn(ctx, page.rrblr)
		if err != nil {
			return err
		}
		page.rrblr = next
		if !next.hasNextLink() || !next.IsEmpty() {
			break
		}
	}
	return nil
}

// Next advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (page *ResourceRecommendationBaseListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

// NotDone returns true if the page enumeration should be started or is not yet complete.
func (page ResourceRecommendationBaseListResultPage) NotDone() bool {
	return !page.rrblr.IsEmpty()
}

// Response returns the raw server response from the last page request.
func (page ResourceRecommendationBaseListResultPage) Response() ResourceRecommendationBaseListResult {
	return page.rrblr
}

// Values returns the slice of values for the current page or nil if there are no values.
func (page ResourceRecommendationBaseListResultPage) Values() []ResourceRecommendationBase {
	if page.rrblr.IsEmpty() {
		return nil
	}
	return *page.rrblr.Value
}

// Creates a new instance of the ResourceRecommendationBaseListResultPage type.
func NewResourceRecommendationBaseListResultPage(cur ResourceRecommendationBaseListResult, getNextPage func(context.Context, ResourceRecommendationBaseListResult) (ResourceRecommendationBaseListResult, error)) ResourceRecommendationBaseListResultPage {
	return ResourceRecommendationBaseListResultPage{
		fn:    getNextPage,
		rrblr: cur,
	}
}

// SetObject ...
type SetObject struct {
	autorest.Response `json:"-"`
	Value             interface{} `json:"value,omitempty"`
}

// ShortDescription a summary of the recommendation.
type ShortDescription struct {
	// Problem - The issue or opportunity identified by the recommendation.
	Problem *string `json:"problem,omitempty"`
	// Solution - The remediation action suggested by the recommendation.
	Solution *string `json:"solution,omitempty"`
}

// SuppressionContract the details of the snoozed or dismissed rule; for example, the duration, name, and
// GUID associated with the rule.
type SuppressionContract struct {
	autorest.Response `json:"-"`
	// SuppressionProperties - The properties of the suppression.
	*SuppressionProperties `json:"properties,omitempty"`
	// ID - READ-ONLY; The resource ID.
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource.
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for SuppressionContract.
func (sc SuppressionContract) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if sc.SuppressionProperties != nil {
		objectMap["properties"] = sc.SuppressionProperties
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for SuppressionContract struct.
func (sc *SuppressionContract) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var suppressionProperties SuppressionProperties
				err = json.Unmarshal(*v, &suppressionProperties)
				if err != nil {
					return err
				}
				sc.SuppressionProperties = &suppressionProperties
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				sc.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				sc.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				sc.Type = &typeVar
			}
		}
	}

	return nil
}

// SuppressionContractListResult the list of Advisor suppressions.
type SuppressionContractListResult struct {
	autorest.Response `json:"-"`
	// NextLink - The link used to get the next page of suppressions.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - The list of suppressions.
	Value *[]SuppressionContract `json:"value,omitempty"`
}

// SuppressionContractListResultIterator provides access to a complete listing of SuppressionContract
// values.
type SuppressionContractListResultIterator struct {
	i    int
	page SuppressionContractListResultPage
}

// NextWithContext advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
func (iter *SuppressionContractListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/SuppressionContractListResultIterator.NextWithContext")
		defer func() {
			sc := -1
			if iter.Response().Response.Response != nil {
				sc = iter.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err = iter.page.NextWithContext(ctx)
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// Next advances to the next value.  If there was an error making
// the request the iterator does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (iter *SuppressionContractListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter SuppressionContractListResultIterator) NotDone() bool {
	return iter.page.NotDone() && iter.i < len(iter.page.Values())
}

// Response returns the raw server response from the last page request.
func (iter SuppressionContractListResultIterator) Response() SuppressionContractListResult {
	return iter.page.Response()
}

// Value returns the current value or a zero-initialized value if the
// iterator has advanced beyond the end of the collection.
func (iter SuppressionContractListResultIterator) Value() SuppressionContract {
	if !iter.page.NotDone() {
		return SuppressionContract{}
	}
	return iter.page.Values()[iter.i]
}

// Creates a new instance of the SuppressionContractListResultIterator type.
func NewSuppressionContractListResultIterator(page SuppressionContractListResultPage) SuppressionContractListResultIterator {
	return SuppressionContractListResultIterator{page: page}
}

// IsEmpty returns true if the ListResult contains no values.
func (sclr SuppressionContractListResult) IsEmpty() bool {
	return sclr.Value == nil || len(*sclr.Value) == 0
}

// hasNextLink returns true if the NextLink is not empty.
func (sclr SuppressionContractListResult) hasNextLink() bool {
	return sclr.NextLink != nil && len(*sclr.NextLink) != 0
}

// suppressionContractListResultPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (sclr SuppressionContractListResult) suppressionContractListResultPreparer(ctx context.Context) (*http.Request, error) {
	if !sclr.hasNextLink() {
		return nil, nil
	}
	return autorest.Prepare((&http.Request{}).WithContext(ctx),
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(sclr.NextLink)))
}

// SuppressionContractListResultPage contains a page of SuppressionContract values.
type SuppressionContractListResultPage struct {
	fn   func(context.Context, SuppressionContractListResult) (SuppressionContractListResult, error)
	sclr SuppressionContractListResult
}

// NextWithContext advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
func (page *SuppressionContractListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/SuppressionContractListResultPage.NextWithContext")
		defer func() {
			sc := -1
			if page.Response().Response.Response != nil {
				sc = page.Response().Response.Response.StatusCode
			}
			tracing.EndSpan(ctx, sc, err)
		}()
	}
	for {
		next, err := page.fn(ctx, page.sclr)
		if err != nil {
			return err
		}
		page.sclr = next
		if !next.hasNextLink() || !next.IsEmpty() {
			break
		}
	}
	return nil
}

// Next advances to the next page of values.  If there was an error making
// the request the page does not advance and the error is returned.
// Deprecated: Use NextWithContext() instead.
func (page *SuppressionContractListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

// NotDone returns true if the page enumeration should be started or is not yet complete.
func (page SuppressionContractListResultPage) NotDone() bool {
	return !page.sclr.IsEmpty()
}

// Response returns the raw server response from the last page request.
func (page SuppressionContractListResultPage) Response() SuppressionContractListResult {
	return page.sclr
}

// Values returns the slice of values for the current page or nil if there are no values.
func (page SuppressionContractListResultPage) Values() []SuppressionContract {
	if page.sclr.IsEmpty() {
		return nil
	}
	return *page.sclr.Value
}

// Creates a new instance of the SuppressionContractListResultPage type.
func NewSuppressionContractListResultPage(cur SuppressionContractListResult, getNextPage func(context.Context, SuppressionContractListResult) (SuppressionContractListResult, error)) SuppressionContractListResultPage {
	return SuppressionContractListResultPage{
		fn:   getNextPage,
		sclr: cur,
	}
}

// SuppressionProperties the properties of the suppression.
type SuppressionProperties struct {
	// SuppressionID - The GUID of the suppression.
	SuppressionID *string `json:"suppressionId,omitempty"`
	// TTL - The duration for which the suppression is valid.
	TTL *string `json:"ttl,omitempty"`
	// ExpirationTimeStamp - READ-ONLY; Gets or sets the expiration time stamp.
	ExpirationTimeStamp *date.Time `json:"expirationTimeStamp,omitempty"`
}

// MarshalJSON is the custom marshaler for SuppressionProperties.
func (sp SuppressionProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if sp.SuppressionID != nil {
		objectMap["suppressionId"] = sp.SuppressionID
	}
	if sp.TTL != nil {
		objectMap["ttl"] = sp.TTL
	}
	return json.Marshal(objectMap)
}
