package azurestack

// 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 (
	"encoding/json"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/to"
	"net/http"
)

// ComputeRole enumerates the values for compute role.
type ComputeRole string

const (
	// IaaS ...
	IaaS ComputeRole = "IaaS"
	// None ...
	None ComputeRole = "None"
	// PaaS ...
	PaaS ComputeRole = "PaaS"
)

// PossibleComputeRoleValues returns an array of possible values for the ComputeRole const type.
func PossibleComputeRoleValues() []ComputeRole {
	return []ComputeRole{IaaS, None, PaaS}
}

// Location enumerates the values for location.
type Location string

const (
	// Global ...
	Global Location = "global"
)

// PossibleLocationValues returns an array of possible values for the Location const type.
func PossibleLocationValues() []Location {
	return []Location{Global}
}

// OperatingSystem enumerates the values for operating system.
type OperatingSystem string

const (
	// OperatingSystemLinux ...
	OperatingSystemLinux OperatingSystem = "Linux"
	// OperatingSystemNone ...
	OperatingSystemNone OperatingSystem = "None"
	// OperatingSystemWindows ...
	OperatingSystemWindows OperatingSystem = "Windows"
)

// PossibleOperatingSystemValues returns an array of possible values for the OperatingSystem const type.
func PossibleOperatingSystemValues() []OperatingSystem {
	return []OperatingSystem{OperatingSystemLinux, OperatingSystemNone, OperatingSystemWindows}
}

// ProvisioningState enumerates the values for provisioning state.
type ProvisioningState string

const (
	// Canceled ...
	Canceled ProvisioningState = "Canceled"
	// Creating ...
	Creating ProvisioningState = "Creating"
	// Failed ...
	Failed ProvisioningState = "Failed"
	// Succeeded ...
	Succeeded ProvisioningState = "Succeeded"
)

// PossibleProvisioningStateValues returns an array of possible values for the ProvisioningState const type.
func PossibleProvisioningStateValues() []ProvisioningState {
	return []ProvisioningState{Canceled, Creating, Failed, Succeeded}
}

// ActivationKeyResult the resource containing the Azure Stack activation key.
type ActivationKeyResult struct {
	autorest.Response `json:"-"`
	// ActivationKey - Azure Stack activation key.
	ActivationKey *string `json:"activationKey,omitempty"`
}

// CustomerSubscription customer subcription.
type CustomerSubscription struct {
	autorest.Response `json:"-"`
	// CustomerSubscriptionProperties - Customer subscription properties.
	*CustomerSubscriptionProperties `json:"properties,omitempty"`
	// ID - ID of the resource.
	ID *string `json:"id,omitempty"`
	// Name - Name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - Type of Resource.
	Type *string `json:"type,omitempty"`
	// Etag - The entity tag used for optimistic concurency when modifying the resource.
	Etag *string `json:"etag,omitempty"`
}

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

// UnmarshalJSON is the custom unmarshaler for CustomerSubscription struct.
func (cs *CustomerSubscription) 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 customerSubscriptionProperties CustomerSubscriptionProperties
				err = json.Unmarshal(*v, &customerSubscriptionProperties)
				if err != nil {
					return err
				}
				cs.CustomerSubscriptionProperties = &customerSubscriptionProperties
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				cs.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				cs.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				cs.Type = &typeVar
			}
		case "etag":
			if v != nil {
				var etag string
				err = json.Unmarshal(*v, &etag)
				if err != nil {
					return err
				}
				cs.Etag = &etag
			}
		}
	}

	return nil
}

// CustomerSubscriptionList pageable list of customer subscriptions.
type CustomerSubscriptionList struct {
	autorest.Response `json:"-"`
	// NextLink - URI to the next page.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - List of customer subscriptions.
	Value *[]CustomerSubscription `json:"value,omitempty"`
}

// CustomerSubscriptionListIterator provides access to a complete listing of CustomerSubscription values.
type CustomerSubscriptionListIterator struct {
	i    int
	page CustomerSubscriptionListPage
}

// Next 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 *CustomerSubscriptionListIterator) Next() error {
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err := iter.page.Next()
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter CustomerSubscriptionListIterator) 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 CustomerSubscriptionListIterator) Response() CustomerSubscriptionList {
	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 CustomerSubscriptionListIterator) Value() CustomerSubscription {
	if !iter.page.NotDone() {
		return CustomerSubscription{}
	}
	return iter.page.Values()[iter.i]
}

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

// customerSubscriptionListPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (csl CustomerSubscriptionList) customerSubscriptionListPreparer() (*http.Request, error) {
	if csl.NextLink == nil || len(to.String(csl.NextLink)) < 1 {
		return nil, nil
	}
	return autorest.Prepare(&http.Request{},
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(csl.NextLink)))
}

// CustomerSubscriptionListPage contains a page of CustomerSubscription values.
type CustomerSubscriptionListPage struct {
	fn  func(CustomerSubscriptionList) (CustomerSubscriptionList, error)
	csl CustomerSubscriptionList
}

// 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.
func (page *CustomerSubscriptionListPage) Next() error {
	next, err := page.fn(page.csl)
	if err != nil {
		return err
	}
	page.csl = next
	return nil
}

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

// Response returns the raw server response from the last page request.
func (page CustomerSubscriptionListPage) Response() CustomerSubscriptionList {
	return page.csl
}

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

// CustomerSubscriptionProperties customer subscription properties.
type CustomerSubscriptionProperties struct {
	// TenantID - Tenant Id.
	TenantID *string `json:"tenantId,omitempty"`
}

// DataDiskImage data disk image.
type DataDiskImage struct {
	// Lun - The LUN.
	Lun *int32 `json:"lun,omitempty"`
	// SourceBlobSasURI - SAS key for source blob.
	SourceBlobSasURI *string `json:"sourceBlobSasUri,omitempty"`
}

// Display contains the localized display information for this particular operation or action.
type Display struct {
	// Provider - The localized, friendly version of the resource provider name.
	Provider *string `json:"provider,omitempty"`
	// Resource - The localized, friendly version of the resource type related to this action or operation; the resource type should match the public documentation for the resource provider.
	Resource *string `json:"resource,omitempty"`
	// Operation - The localized, friendly name for the operation. Use the name as it will displayed to the user.
	Operation *string `json:"operation,omitempty"`
	// Description - The localized, friendly description for the operation. The description will be displayed to the user. It should be thorough and concise for used in both tooltips and detailed views.
	Description *string `json:"description,omitempty"`
}

// ErrorDetails the details of the error.
type ErrorDetails struct {
	// Code - Error code.
	Code *string `json:"code,omitempty"`
	// Message - Error message indicating why the operation failed.
	Message *string `json:"message,omitempty"`
	// Target - The target of the particular error.
	Target *string `json:"target,omitempty"`
}

// ErrorResponse error response indicates that the service is not able to process the incoming request. The reason
// is provided in the error message.
type ErrorResponse struct {
	// Error - The details of the error.
	Error *ErrorDetails `json:"error,omitempty"`
}

// ExtendedProduct extended description about the product required for installing it into Azure Stack.
type ExtendedProduct struct {
	autorest.Response `json:"-"`
	// GalleryPackageBlobSasURI - The URI to the .azpkg file that provides information required for showing product in the gallery.
	GalleryPackageBlobSasURI *string `json:"galleryPackageBlobSasUri,omitempty"`
	// ProductKind - Specifies the kind of the product (virtualMachine or virtualMachineExtension).
	ProductKind *string `json:"productKind,omitempty"`
	// ExtendedProductProperties - Specifies additional properties describing the product.
	*ExtendedProductProperties `json:"properties,omitempty"`
}

// MarshalJSON is the custom marshaler for ExtendedProduct.
func (ep ExtendedProduct) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if ep.GalleryPackageBlobSasURI != nil {
		objectMap["galleryPackageBlobSasUri"] = ep.GalleryPackageBlobSasURI
	}
	if ep.ProductKind != nil {
		objectMap["productKind"] = ep.ProductKind
	}
	if ep.ExtendedProductProperties != nil {
		objectMap["properties"] = ep.ExtendedProductProperties
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ExtendedProduct struct.
func (ep *ExtendedProduct) 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 "galleryPackageBlobSasUri":
			if v != nil {
				var galleryPackageBlobSasURI string
				err = json.Unmarshal(*v, &galleryPackageBlobSasURI)
				if err != nil {
					return err
				}
				ep.GalleryPackageBlobSasURI = &galleryPackageBlobSasURI
			}
		case "productKind":
			if v != nil {
				var productKind string
				err = json.Unmarshal(*v, &productKind)
				if err != nil {
					return err
				}
				ep.ProductKind = &productKind
			}
		case "properties":
			if v != nil {
				var extendedProductProperties ExtendedProductProperties
				err = json.Unmarshal(*v, &extendedProductProperties)
				if err != nil {
					return err
				}
				ep.ExtendedProductProperties = &extendedProductProperties
			}
		}
	}

	return nil
}

// ExtendedProductProperties product information.
type ExtendedProductProperties struct {
	// ComputeRole - Specifies kind of compute role inclided in the package. Possible values include: 'None', 'IaaS', 'PaaS'
	ComputeRole ComputeRole `json:"computeRole,omitempty"`
	// IsSystemExtension - Specifies if product is a Virtual Machine Extension.
	IsSystemExtension *bool `json:"isSystemExtension,omitempty"`
	// URI - Specifies a download location where content can be downloaded from.
	*URI `json:"sourceBlob,omitempty"`
	// SupportMultipleExtensions - Indicates if specified product supports multiple extensions.
	SupportMultipleExtensions *bool `json:"supportMultipleExtensions,omitempty"`
	// Version - Specifies product version.
	Version *string `json:"version,omitempty"`
	// VMOsType - Specifies operating system used by the product. Possible values include: 'OperatingSystemNone', 'OperatingSystemWindows', 'OperatingSystemLinux'
	VMOsType OperatingSystem `json:"vmOsType,omitempty"`
	// VMScaleSetEnabled - Indicates if virtual machine Scale Set is enabled in the specified product.
	VMScaleSetEnabled *bool `json:"vmScaleSetEnabled,omitempty"`
	// OsDiskImage - OS disk image used by product.
	OsDiskImage *OsDiskImage `json:"osDiskImage,omitempty"`
	// DataDiskImages - List of attached data disks.
	DataDiskImages *[]DataDiskImage `json:"dataDiskImages,omitempty"`
}

// MarshalJSON is the custom marshaler for ExtendedProductProperties.
func (epp ExtendedProductProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if epp.ComputeRole != "" {
		objectMap["computeRole"] = epp.ComputeRole
	}
	if epp.IsSystemExtension != nil {
		objectMap["isSystemExtension"] = epp.IsSystemExtension
	}
	if epp.URI != nil {
		objectMap["sourceBlob"] = epp.URI
	}
	if epp.SupportMultipleExtensions != nil {
		objectMap["supportMultipleExtensions"] = epp.SupportMultipleExtensions
	}
	if epp.Version != nil {
		objectMap["version"] = epp.Version
	}
	if epp.VMOsType != "" {
		objectMap["vmOsType"] = epp.VMOsType
	}
	if epp.VMScaleSetEnabled != nil {
		objectMap["vmScaleSetEnabled"] = epp.VMScaleSetEnabled
	}
	if epp.OsDiskImage != nil {
		objectMap["osDiskImage"] = epp.OsDiskImage
	}
	if epp.DataDiskImages != nil {
		objectMap["dataDiskImages"] = epp.DataDiskImages
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ExtendedProductProperties struct.
func (epp *ExtendedProductProperties) 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 "computeRole":
			if v != nil {
				var computeRole ComputeRole
				err = json.Unmarshal(*v, &computeRole)
				if err != nil {
					return err
				}
				epp.ComputeRole = computeRole
			}
		case "isSystemExtension":
			if v != nil {
				var isSystemExtension bool
				err = json.Unmarshal(*v, &isSystemExtension)
				if err != nil {
					return err
				}
				epp.IsSystemExtension = &isSystemExtension
			}
		case "sourceBlob":
			if v != nil {
				var URI URI
				err = json.Unmarshal(*v, &URI)
				if err != nil {
					return err
				}
				epp.URI = &URI
			}
		case "supportMultipleExtensions":
			if v != nil {
				var supportMultipleExtensions bool
				err = json.Unmarshal(*v, &supportMultipleExtensions)
				if err != nil {
					return err
				}
				epp.SupportMultipleExtensions = &supportMultipleExtensions
			}
		case "version":
			if v != nil {
				var version string
				err = json.Unmarshal(*v, &version)
				if err != nil {
					return err
				}
				epp.Version = &version
			}
		case "vmOsType":
			if v != nil {
				var VMOsType OperatingSystem
				err = json.Unmarshal(*v, &VMOsType)
				if err != nil {
					return err
				}
				epp.VMOsType = VMOsType
			}
		case "vmScaleSetEnabled":
			if v != nil {
				var VMScaleSetEnabled bool
				err = json.Unmarshal(*v, &VMScaleSetEnabled)
				if err != nil {
					return err
				}
				epp.VMScaleSetEnabled = &VMScaleSetEnabled
			}
		case "osDiskImage":
			if v != nil {
				var osDiskImage OsDiskImage
				err = json.Unmarshal(*v, &osDiskImage)
				if err != nil {
					return err
				}
				epp.OsDiskImage = &osDiskImage
			}
		case "dataDiskImages":
			if v != nil {
				var dataDiskImages []DataDiskImage
				err = json.Unmarshal(*v, &dataDiskImages)
				if err != nil {
					return err
				}
				epp.DataDiskImages = &dataDiskImages
			}
		}
	}

	return nil
}

// IconUris links to product icons.
type IconUris struct {
	// Large - URI to large icon.
	Large *string `json:"large,omitempty"`
	// Wide - URI to wide icon.
	Wide *string `json:"wide,omitempty"`
	// Medium - URI to medium icon.
	Medium *string `json:"medium,omitempty"`
	// Small - URI to small icon.
	Small *string `json:"small,omitempty"`
	// Hero - URI to hero icon.
	Hero *string `json:"hero,omitempty"`
}

// Operation describes the supported REST operation.
type Operation struct {
	// Name - The name of the operation being performed on this particular object.
	Name *string `json:"name,omitempty"`
	// Display - Contains the localized display information for this particular operation or action.
	Display *Display `json:"display,omitempty"`
	// Origin - The intended executor of the operation.
	Origin *string `json:"origin,omitempty"`
}

// OperationList list of Operations
type OperationList struct {
	autorest.Response `json:"-"`
	// Value - Array of operations
	Value *[]Operation `json:"value,omitempty"`
	// NextLink - URI to the next page of operations.
	NextLink *string `json:"nextLink,omitempty"`
}

// OperationListIterator provides access to a complete listing of Operation values.
type OperationListIterator struct {
	i    int
	page OperationListPage
}

// Next 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 *OperationListIterator) Next() error {
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err := iter.page.Next()
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter OperationListIterator) 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 OperationListIterator) Response() OperationList {
	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 OperationListIterator) Value() Operation {
	if !iter.page.NotDone() {
		return Operation{}
	}
	return iter.page.Values()[iter.i]
}

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

// operationListPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (ol OperationList) operationListPreparer() (*http.Request, error) {
	if ol.NextLink == nil || len(to.String(ol.NextLink)) < 1 {
		return nil, nil
	}
	return autorest.Prepare(&http.Request{},
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(ol.NextLink)))
}

// OperationListPage contains a page of Operation values.
type OperationListPage struct {
	fn func(OperationList) (OperationList, error)
	ol OperationList
}

// 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.
func (page *OperationListPage) Next() error {
	next, err := page.fn(page.ol)
	if err != nil {
		return err
	}
	page.ol = next
	return nil
}

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

// Response returns the raw server response from the last page request.
func (page OperationListPage) Response() OperationList {
	return page.ol
}

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

// OsDiskImage OS disk image.
type OsDiskImage struct {
	// OperatingSystem - OS operating system type. Possible values include: 'OperatingSystemNone', 'OperatingSystemWindows', 'OperatingSystemLinux'
	OperatingSystem OperatingSystem `json:"operatingSystem,omitempty"`
	// SourceBlobSasURI - SAS key for source blob.
	SourceBlobSasURI *string `json:"sourceBlobSasUri,omitempty"`
}

// Product product information.
type Product struct {
	autorest.Response `json:"-"`
	// ProductNestedProperties - Properties of the product resource.
	*ProductNestedProperties `json:"properties,omitempty"`
	// ID - ID of the resource.
	ID *string `json:"id,omitempty"`
	// Name - Name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - Type of Resource.
	Type *string `json:"type,omitempty"`
	// Etag - The entity tag used for optimistic concurency when modifying the resource.
	Etag *string `json:"etag,omitempty"`
}

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

// UnmarshalJSON is the custom unmarshaler for Product struct.
func (p *Product) 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 productNestedProperties ProductNestedProperties
				err = json.Unmarshal(*v, &productNestedProperties)
				if err != nil {
					return err
				}
				p.ProductNestedProperties = &productNestedProperties
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				p.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				p.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				p.Type = &typeVar
			}
		case "etag":
			if v != nil {
				var etag string
				err = json.Unmarshal(*v, &etag)
				if err != nil {
					return err
				}
				p.Etag = &etag
			}
		}
	}

	return nil
}

// ProductLink link with additional information about a product.
type ProductLink struct {
	// DisplayName - The description of the link.
	DisplayName *string `json:"displayName,omitempty"`
	// URI - The URI corresponding to the link.
	URI *string `json:"uri,omitempty"`
}

// ProductList pageable list of products.
type ProductList struct {
	autorest.Response `json:"-"`
	// NextLink - URI to the next page.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - List of products.
	Value *[]Product `json:"value,omitempty"`
}

// ProductListIterator provides access to a complete listing of Product values.
type ProductListIterator struct {
	i    int
	page ProductListPage
}

// Next 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 *ProductListIterator) Next() error {
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err := iter.page.Next()
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter ProductListIterator) 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 ProductListIterator) Response() ProductList {
	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 ProductListIterator) Value() Product {
	if !iter.page.NotDone() {
		return Product{}
	}
	return iter.page.Values()[iter.i]
}

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

// productListPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (pl ProductList) productListPreparer() (*http.Request, error) {
	if pl.NextLink == nil || len(to.String(pl.NextLink)) < 1 {
		return nil, nil
	}
	return autorest.Prepare(&http.Request{},
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(pl.NextLink)))
}

// ProductListPage contains a page of Product values.
type ProductListPage struct {
	fn func(ProductList) (ProductList, error)
	pl ProductList
}

// 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.
func (page *ProductListPage) Next() error {
	next, err := page.fn(page.pl)
	if err != nil {
		return err
	}
	page.pl = next
	return nil
}

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

// Response returns the raw server response from the last page request.
func (page ProductListPage) Response() ProductList {
	return page.pl
}

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

// ProductNestedProperties properties portion of the product resource.
type ProductNestedProperties struct {
	// DisplayName - The display name of the product.
	DisplayName *string `json:"displayName,omitempty"`
	// Description - The description of the product.
	Description *string `json:"description,omitempty"`
	// PublisherDisplayName - The user-friendly name of the product publisher.
	PublisherDisplayName *string `json:"publisherDisplayName,omitempty"`
	// PublisherIdentifier - Publisher identifier.
	PublisherIdentifier *string `json:"publisherIdentifier,omitempty"`
	// Offer - The offer representing the product.
	Offer *string `json:"offer,omitempty"`
	// OfferVersion - The version of the product offer.
	OfferVersion *string `json:"offerVersion,omitempty"`
	// Sku - The product SKU.
	Sku *string `json:"sku,omitempty"`
	// BillingPartNumber - The part number used for billing purposes.
	BillingPartNumber *string `json:"billingPartNumber,omitempty"`
	// VMExtensionType - The type of the Virtual Machine Extension.
	VMExtensionType *string `json:"vmExtensionType,omitempty"`
	// GalleryItemIdentity - The identifier of the gallery item corresponding to the product.
	GalleryItemIdentity *string `json:"galleryItemIdentity,omitempty"`
	// IconUris - Additional links available for this product.
	IconUris *IconUris `json:"iconUris,omitempty"`
	// Links - Additional links available for this product.
	Links *[]ProductLink `json:"links,omitempty"`
	// LegalTerms - The legal terms.
	LegalTerms *string `json:"legalTerms,omitempty"`
	// PrivacyPolicy - The privacy policy.
	PrivacyPolicy *string `json:"privacyPolicy,omitempty"`
	// PayloadLength - The length of product content.
	PayloadLength *int64 `json:"payloadLength,omitempty"`
	// ProductKind - The kind of the product (virtualMachine or virtualMachineExtension)
	ProductKind *string `json:"productKind,omitempty"`
	// ProductProperties - Additional properties for the product.
	ProductProperties *ProductProperties `json:"productProperties,omitempty"`
}

// ProductProperties additional properties of the product
type ProductProperties struct {
	// Version - The version.
	Version *string `json:"version,omitempty"`
}

// Registration registration information.
type Registration struct {
	autorest.Response `json:"-"`
	// RegistrationProperties - Registration resource.
	*RegistrationProperties `json:"properties,omitempty"`
	// ID - ID of the resource.
	ID *string `json:"id,omitempty"`
	// Name - Name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - Type of Resource.
	Type *string `json:"type,omitempty"`
	// Location - Location of the resource.
	Location *string `json:"location,omitempty"`
	// Tags - Custom tags for the resource.
	Tags map[string]*string `json:"tags"`
	// Etag - The entity tag used for optimistic concurency when modifying the resource.
	Etag *string `json:"etag,omitempty"`
}

// MarshalJSON is the custom marshaler for Registration.
func (r Registration) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if r.RegistrationProperties != nil {
		objectMap["properties"] = r.RegistrationProperties
	}
	if r.ID != nil {
		objectMap["id"] = r.ID
	}
	if r.Name != nil {
		objectMap["name"] = r.Name
	}
	if r.Type != nil {
		objectMap["type"] = r.Type
	}
	if r.Location != nil {
		objectMap["location"] = r.Location
	}
	if r.Tags != nil {
		objectMap["tags"] = r.Tags
	}
	if r.Etag != nil {
		objectMap["etag"] = r.Etag
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for Registration struct.
func (r *Registration) 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 registrationProperties RegistrationProperties
				err = json.Unmarshal(*v, &registrationProperties)
				if err != nil {
					return err
				}
				r.RegistrationProperties = &registrationProperties
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				r.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				r.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				r.Type = &typeVar
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				r.Location = &location
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				r.Tags = tags
			}
		case "etag":
			if v != nil {
				var etag string
				err = json.Unmarshal(*v, &etag)
				if err != nil {
					return err
				}
				r.Etag = &etag
			}
		}
	}

	return nil
}

// RegistrationList pageable list of registrations.
type RegistrationList struct {
	autorest.Response `json:"-"`
	// NextLink - URI to the next page.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - List of Registrations
	Value *[]Registration `json:"value,omitempty"`
}

// RegistrationListIterator provides access to a complete listing of Registration values.
type RegistrationListIterator struct {
	i    int
	page RegistrationListPage
}

// Next 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 *RegistrationListIterator) Next() error {
	iter.i++
	if iter.i < len(iter.page.Values()) {
		return nil
	}
	err := iter.page.Next()
	if err != nil {
		iter.i--
		return err
	}
	iter.i = 0
	return nil
}

// NotDone returns true if the enumeration should be started or is not yet complete.
func (iter RegistrationListIterator) 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 RegistrationListIterator) Response() RegistrationList {
	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 RegistrationListIterator) Value() Registration {
	if !iter.page.NotDone() {
		return Registration{}
	}
	return iter.page.Values()[iter.i]
}

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

// registrationListPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (rl RegistrationList) registrationListPreparer() (*http.Request, error) {
	if rl.NextLink == nil || len(to.String(rl.NextLink)) < 1 {
		return nil, nil
	}
	return autorest.Prepare(&http.Request{},
		autorest.AsJSON(),
		autorest.AsGet(),
		autorest.WithBaseURL(to.String(rl.NextLink)))
}

// RegistrationListPage contains a page of Registration values.
type RegistrationListPage struct {
	fn func(RegistrationList) (RegistrationList, error)
	rl RegistrationList
}

// 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.
func (page *RegistrationListPage) Next() error {
	next, err := page.fn(page.rl)
	if err != nil {
		return err
	}
	page.rl = next
	return nil
}

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

// Response returns the raw server response from the last page request.
func (page RegistrationListPage) Response() RegistrationList {
	return page.rl
}

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

// RegistrationParameter registration resource
type RegistrationParameter struct {
	// RegistrationParameterProperties - Properties of the Azure Stack registration resource
	*RegistrationParameterProperties `json:"properties,omitempty"`
	// Location - Location of the resource. Possible values include: 'Global'
	Location Location `json:"location,omitempty"`
}

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

// UnmarshalJSON is the custom unmarshaler for RegistrationParameter struct.
func (rp *RegistrationParameter) 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 registrationParameterProperties RegistrationParameterProperties
				err = json.Unmarshal(*v, &registrationParameterProperties)
				if err != nil {
					return err
				}
				rp.RegistrationParameterProperties = &registrationParameterProperties
			}
		case "location":
			if v != nil {
				var location Location
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				rp.Location = location
			}
		}
	}

	return nil
}

// RegistrationParameterProperties properties of the Azure Stack regstration resource
type RegistrationParameterProperties struct {
	// RegistrationToken - The token identifying registered Azure Stack
	RegistrationToken *string `json:"registrationToken,omitempty"`
}

// RegistrationProperties properties portion of the registration resource.
type RegistrationProperties struct {
	// ObjectID - The object identifier associated with the Azure Stack connecting to Azure.
	ObjectID *string `json:"objectId,omitempty"`
	// CloudID - The identifier of the registered Azure Stack.
	CloudID *string `json:"cloudId,omitempty"`
	// BillingModel - Specifies the billing mode for the Azure Stack registration.
	BillingModel *string `json:"billingModel,omitempty"`
}

// Resource base resource object.
type Resource struct {
	// ID - ID of the resource.
	ID *string `json:"id,omitempty"`
	// Name - Name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - Type of Resource.
	Type *string `json:"type,omitempty"`
	// Etag - The entity tag used for optimistic concurency when modifying the resource.
	Etag *string `json:"etag,omitempty"`
}

// TrackedResource base resource object.
type TrackedResource struct {
	// ID - ID of the resource.
	ID *string `json:"id,omitempty"`
	// Name - Name of the resource.
	Name *string `json:"name,omitempty"`
	// Type - Type of Resource.
	Type *string `json:"type,omitempty"`
	// Location - Location of the resource.
	Location *string `json:"location,omitempty"`
	// Tags - Custom tags for the resource.
	Tags map[string]*string `json:"tags"`
	// Etag - The entity tag used for optimistic concurency when modifying the resource.
	Etag *string `json:"etag,omitempty"`
}

// MarshalJSON is the custom marshaler for TrackedResource.
func (tr TrackedResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if tr.ID != nil {
		objectMap["id"] = tr.ID
	}
	if tr.Name != nil {
		objectMap["name"] = tr.Name
	}
	if tr.Type != nil {
		objectMap["type"] = tr.Type
	}
	if tr.Location != nil {
		objectMap["location"] = tr.Location
	}
	if tr.Tags != nil {
		objectMap["tags"] = tr.Tags
	}
	if tr.Etag != nil {
		objectMap["etag"] = tr.Etag
	}
	return json.Marshal(objectMap)
}

// URI the URI.
type URI struct {
	// URI - The URI.
	URI *string `json:"uri,omitempty"`
}

// VirtualMachineExtensionProductProperties product information.
type VirtualMachineExtensionProductProperties struct {
	// ComputeRole - Specifies kind of compute role inclided in the package. Possible values include: 'None', 'IaaS', 'PaaS'
	ComputeRole ComputeRole `json:"computeRole,omitempty"`
	// IsSystemExtension - Specifies if product is a Virtual Machine Extension.
	IsSystemExtension *bool `json:"isSystemExtension,omitempty"`
	// URI - Specifies a download location where content can be downloaded from.
	*URI `json:"sourceBlob,omitempty"`
	// SupportMultipleExtensions - Indicates if specified product supports multiple extensions.
	SupportMultipleExtensions *bool `json:"supportMultipleExtensions,omitempty"`
	// Version - Specifies product version.
	Version *string `json:"version,omitempty"`
	// VMOsType - Specifies operating system used by the product. Possible values include: 'OperatingSystemNone', 'OperatingSystemWindows', 'OperatingSystemLinux'
	VMOsType OperatingSystem `json:"vmOsType,omitempty"`
	// VMScaleSetEnabled - Indicates if virtual machine Scale Set is enabled in the specified product.
	VMScaleSetEnabled *bool `json:"vmScaleSetEnabled,omitempty"`
}

// MarshalJSON is the custom marshaler for VirtualMachineExtensionProductProperties.
func (vmepp VirtualMachineExtensionProductProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if vmepp.ComputeRole != "" {
		objectMap["computeRole"] = vmepp.ComputeRole
	}
	if vmepp.IsSystemExtension != nil {
		objectMap["isSystemExtension"] = vmepp.IsSystemExtension
	}
	if vmepp.URI != nil {
		objectMap["sourceBlob"] = vmepp.URI
	}
	if vmepp.SupportMultipleExtensions != nil {
		objectMap["supportMultipleExtensions"] = vmepp.SupportMultipleExtensions
	}
	if vmepp.Version != nil {
		objectMap["version"] = vmepp.Version
	}
	if vmepp.VMOsType != "" {
		objectMap["vmOsType"] = vmepp.VMOsType
	}
	if vmepp.VMScaleSetEnabled != nil {
		objectMap["vmScaleSetEnabled"] = vmepp.VMScaleSetEnabled
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for VirtualMachineExtensionProductProperties struct.
func (vmepp *VirtualMachineExtensionProductProperties) 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 "computeRole":
			if v != nil {
				var computeRole ComputeRole
				err = json.Unmarshal(*v, &computeRole)
				if err != nil {
					return err
				}
				vmepp.ComputeRole = computeRole
			}
		case "isSystemExtension":
			if v != nil {
				var isSystemExtension bool
				err = json.Unmarshal(*v, &isSystemExtension)
				if err != nil {
					return err
				}
				vmepp.IsSystemExtension = &isSystemExtension
			}
		case "sourceBlob":
			if v != nil {
				var URI URI
				err = json.Unmarshal(*v, &URI)
				if err != nil {
					return err
				}
				vmepp.URI = &URI
			}
		case "supportMultipleExtensions":
			if v != nil {
				var supportMultipleExtensions bool
				err = json.Unmarshal(*v, &supportMultipleExtensions)
				if err != nil {
					return err
				}
				vmepp.SupportMultipleExtensions = &supportMultipleExtensions
			}
		case "version":
			if v != nil {
				var version string
				err = json.Unmarshal(*v, &version)
				if err != nil {
					return err
				}
				vmepp.Version = &version
			}
		case "vmOsType":
			if v != nil {
				var VMOsType OperatingSystem
				err = json.Unmarshal(*v, &VMOsType)
				if err != nil {
					return err
				}
				vmepp.VMOsType = VMOsType
			}
		case "vmScaleSetEnabled":
			if v != nil {
				var VMScaleSetEnabled bool
				err = json.Unmarshal(*v, &VMScaleSetEnabled)
				if err != nil {
					return err
				}
				vmepp.VMScaleSetEnabled = &VMScaleSetEnabled
			}
		}
	}

	return nil
}

// VirtualMachineProductProperties product information.
type VirtualMachineProductProperties struct {
	// Version - Specifies product version.
	Version *string `json:"version,omitempty"`
	// OsDiskImage - OS disk image used by product.
	OsDiskImage *OsDiskImage `json:"osDiskImage,omitempty"`
	// DataDiskImages - List of attached data disks.
	DataDiskImages *[]DataDiskImage `json:"dataDiskImages,omitempty"`
}
