package storagecache

// 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.

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

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

// APIOperation REST API operation description: see
// https://github.com/Azure/azure-rest-api-specs/blob/master/documentation/openapi-authoring-automated-guidelines.md#r3023-operationsapiimplementation
type APIOperation struct {
	// Display - The object that represents the operation.
	Display *APIOperationDisplay `json:"display,omitempty"`
	// Name - Operation name: {provider}/{resource}/{operation}
	Name *string `json:"name,omitempty"`
}

// APIOperationDisplay the object that represents the operation.
type APIOperationDisplay struct {
	// Operation - Operation type: Read, write, delete, etc.
	Operation *string `json:"operation,omitempty"`
	// Provider - Service provider: Microsoft.StorageCache
	Provider *string `json:"provider,omitempty"`
	// Resource - Resource on which the operation is performed: cache, etc.
	Resource *string `json:"resource,omitempty"`
}

// APIOperationListResult result of the request to list Resource Provider operations. It contains a list of
// operations and a URL link to get the next set of results.
type APIOperationListResult struct {
	autorest.Response `json:"-"`
	// NextLink - URL to get the next set of operation list results if there are any.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - List of Resource Provider operations supported by the Microsoft.StorageCache resource provider.
	Value *[]APIOperation `json:"value,omitempty"`
}

// APIOperationListResultIterator provides access to a complete listing of APIOperation values.
type APIOperationListResultIterator struct {
	i    int
	page APIOperationListResultPage
}

// 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 *APIOperationListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/APIOperationListResultIterator.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 *APIOperationListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

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

// Creates a new instance of the APIOperationListResultIterator type.
func NewAPIOperationListResultIterator(page APIOperationListResultPage) APIOperationListResultIterator {
	return APIOperationListResultIterator{page: page}
}

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

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

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

// APIOperationListResultPage contains a page of APIOperation values.
type APIOperationListResultPage struct {
	fn   func(context.Context, APIOperationListResult) (APIOperationListResult, error)
	aolr APIOperationListResult
}

// 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 *APIOperationListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/APIOperationListResultPage.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.aolr)
		if err != nil {
			return err
		}
		page.aolr = 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 *APIOperationListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

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

// Response returns the raw server response from the last page request.
func (page APIOperationListResultPage) Response() APIOperationListResult {
	return page.aolr
}

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

// Creates a new instance of the APIOperationListResultPage type.
func NewAPIOperationListResultPage(cur APIOperationListResult, getNextPage func(context.Context, APIOperationListResult) (APIOperationListResult, error)) APIOperationListResultPage {
	return APIOperationListResultPage{
		fn:   getNextPage,
		aolr: cur,
	}
}

// Cache a cache instance.  Follows Azure Resource Manager standards:
// https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/resource-api-reference.md
type Cache struct {
	autorest.Response `json:"-"`
	// Tags - ARM tags as name/value pairs.
	Tags interface{} `json:"tags,omitempty"`
	// ID - READ-ONLY; Fully qualified URL of the cache.
	ID *string `json:"id,omitempty"`
	// Location - Region name string.
	Location *string `json:"location,omitempty"`
	// Name - READ-ONLY; Name of cache.
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; Type for the cache; Microsoft.StorageCache/Cache
	Type *string `json:"type,omitempty"`
	// CacheProperties - Properties for the cache.
	*CacheProperties `json:"properties,omitempty"`
	// Sku - Sku for the cache.
	Sku *CacheSku `json:"sku,omitempty"`
}

// MarshalJSON is the custom marshaler for Cache.
func (c Cache) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if c.Tags != nil {
		objectMap["tags"] = c.Tags
	}
	if c.Location != nil {
		objectMap["location"] = c.Location
	}
	if c.CacheProperties != nil {
		objectMap["properties"] = c.CacheProperties
	}
	if c.Sku != nil {
		objectMap["sku"] = c.Sku
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for Cache struct.
func (c *Cache) 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 "tags":
			if v != nil {
				var tags interface{}
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				c.Tags = tags
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				c.ID = &ID
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				c.Location = &location
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				c.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				c.Type = &typeVar
			}
		case "properties":
			if v != nil {
				var cacheProperties CacheProperties
				err = json.Unmarshal(*v, &cacheProperties)
				if err != nil {
					return err
				}
				c.CacheProperties = &cacheProperties
			}
		case "sku":
			if v != nil {
				var sku CacheSku
				err = json.Unmarshal(*v, &sku)
				if err != nil {
					return err
				}
				c.Sku = &sku
			}
		}
	}

	return nil
}

// CacheHealth an indication of cache health.  Gives more information about health than just that related
// to provisioning.
type CacheHealth struct {
	// State - List of cache health states. Possible values include: 'Unknown', 'Healthy', 'Degraded', 'Down', 'Transitioning', 'Stopping', 'Stopped', 'Upgrading', 'Flushing'
	State HealthStateType `json:"state,omitempty"`
	// StatusDescription - Describes explanation of state.
	StatusDescription *string `json:"statusDescription,omitempty"`
}

// CacheProperties properties for the cache.
type CacheProperties struct {
	// CacheSizeGB - The size of this cache's cache, in GB.
	CacheSizeGB *int32 `json:"cacheSizeGB,omitempty"`
	// Health - READ-ONLY; Health of the cache.
	Health *CacheHealth `json:"health,omitempty"`
	// MountAddresses - READ-ONLY; Array of IP addresses that can be used by clients mounting this Cache.
	MountAddresses *[]string `json:"mountAddresses,omitempty"`
	// ProvisioningState - ARM provisioning state, see https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#provisioningstate-property. Possible values include: 'Succeeded', 'Failed', 'Cancelled', 'Creating', 'Deleting', 'Updating'
	ProvisioningState ProvisioningStateType `json:"provisioningState,omitempty"`
	// Subnet - Subnet used for the cache.
	Subnet *string `json:"subnet,omitempty"`
	// UpgradeStatus - Upgrade status of the cache.
	UpgradeStatus *CacheUpgradeStatus `json:"upgradeStatus,omitempty"`
}

// MarshalJSON is the custom marshaler for CacheProperties.
func (c CacheProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if c.CacheSizeGB != nil {
		objectMap["cacheSizeGB"] = c.CacheSizeGB
	}
	if c.ProvisioningState != "" {
		objectMap["provisioningState"] = c.ProvisioningState
	}
	if c.Subnet != nil {
		objectMap["subnet"] = c.Subnet
	}
	if c.UpgradeStatus != nil {
		objectMap["upgradeStatus"] = c.UpgradeStatus
	}
	return json.Marshal(objectMap)
}

// CachesCreateFuture an abstraction for monitoring and retrieving the results of a long-running operation.
type CachesCreateFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(CachesClient) (Cache, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *CachesCreateFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for CachesCreateFuture.Result.
func (future *CachesCreateFuture) result(client CachesClient) (c Cache, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.CachesCreateFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		c.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.CachesCreateFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if c.Response.Response, err = future.GetResult(sender); err == nil && c.Response.Response.StatusCode != http.StatusNoContent {
		c, err = client.CreateResponder(c.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.CachesCreateFuture", "Result", c.Response.Response, "Failure responding to request")
		}
	}
	return
}

// CachesDeleteFuture an abstraction for monitoring and retrieving the results of a long-running operation.
type CachesDeleteFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(CachesClient) (SetObject, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *CachesDeleteFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for CachesDeleteFuture.Result.
func (future *CachesDeleteFuture) result(client CachesClient) (so SetObject, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.CachesDeleteFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		so.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.CachesDeleteFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if so.Response.Response, err = future.GetResult(sender); err == nil && so.Response.Response.StatusCode != http.StatusNoContent {
		so, err = client.DeleteResponder(so.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.CachesDeleteFuture", "Result", so.Response.Response, "Failure responding to request")
		}
	}
	return
}

// CachesFlushFuture an abstraction for monitoring and retrieving the results of a long-running operation.
type CachesFlushFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(CachesClient) (SetObject, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *CachesFlushFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for CachesFlushFuture.Result.
func (future *CachesFlushFuture) result(client CachesClient) (so SetObject, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.CachesFlushFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		so.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.CachesFlushFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if so.Response.Response, err = future.GetResult(sender); err == nil && so.Response.Response.StatusCode != http.StatusNoContent {
		so, err = client.FlushResponder(so.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.CachesFlushFuture", "Result", so.Response.Response, "Failure responding to request")
		}
	}
	return
}

// CacheSku sku for the cache.
type CacheSku struct {
	// Name - Sku name for this cache.
	Name *string `json:"name,omitempty"`
}

// CachesListResult result of the request to list caches. It contains a list of caches and a URL link to
// get the next set of results.
type CachesListResult struct {
	autorest.Response `json:"-"`
	// NextLink - URL to get the next set of cache list results if there are any.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - List of caches.
	Value *[]Cache `json:"value,omitempty"`
}

// CachesListResultIterator provides access to a complete listing of Cache values.
type CachesListResultIterator struct {
	i    int
	page CachesListResultPage
}

// 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 *CachesListResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/CachesListResultIterator.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 *CachesListResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

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

// Creates a new instance of the CachesListResultIterator type.
func NewCachesListResultIterator(page CachesListResultPage) CachesListResultIterator {
	return CachesListResultIterator{page: page}
}

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

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

// cachesListResultPreparer prepares a request to retrieve the next set of results.
// It returns nil if no more results exist.
func (clr CachesListResult) cachesListResultPreparer(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)))
}

// CachesListResultPage contains a page of Cache values.
type CachesListResultPage struct {
	fn  func(context.Context, CachesListResult) (CachesListResult, error)
	clr CachesListResult
}

// 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 *CachesListResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/CachesListResultPage.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 *CachesListResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

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

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

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

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

// CachesStartFuture an abstraction for monitoring and retrieving the results of a long-running operation.
type CachesStartFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(CachesClient) (SetObject, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *CachesStartFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for CachesStartFuture.Result.
func (future *CachesStartFuture) result(client CachesClient) (so SetObject, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.CachesStartFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		so.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.CachesStartFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if so.Response.Response, err = future.GetResult(sender); err == nil && so.Response.Response.StatusCode != http.StatusNoContent {
		so, err = client.StartResponder(so.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.CachesStartFuture", "Result", so.Response.Response, "Failure responding to request")
		}
	}
	return
}

// CachesStopFuture an abstraction for monitoring and retrieving the results of a long-running operation.
type CachesStopFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(CachesClient) (SetObject, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *CachesStopFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for CachesStopFuture.Result.
func (future *CachesStopFuture) result(client CachesClient) (so SetObject, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.CachesStopFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		so.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.CachesStopFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if so.Response.Response, err = future.GetResult(sender); err == nil && so.Response.Response.StatusCode != http.StatusNoContent {
		so, err = client.StopResponder(so.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.CachesStopFuture", "Result", so.Response.Response, "Failure responding to request")
		}
	}
	return
}

// CachesUpgradeFirmwareFuture an abstraction for monitoring and retrieving the results of a long-running
// operation.
type CachesUpgradeFirmwareFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(CachesClient) (SetObject, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *CachesUpgradeFirmwareFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for CachesUpgradeFirmwareFuture.Result.
func (future *CachesUpgradeFirmwareFuture) result(client CachesClient) (so SetObject, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.CachesUpgradeFirmwareFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		so.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.CachesUpgradeFirmwareFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if so.Response.Response, err = future.GetResult(sender); err == nil && so.Response.Response.StatusCode != http.StatusNoContent {
		so, err = client.UpgradeFirmwareResponder(so.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.CachesUpgradeFirmwareFuture", "Result", so.Response.Response, "Failure responding to request")
		}
	}
	return
}

// CacheUpgradeStatus properties describing the software upgrade state of the cache
type CacheUpgradeStatus struct {
	// CurrentFirmwareVersion - READ-ONLY; Version string of the firmware currently installed on this cache.
	CurrentFirmwareVersion *string `json:"currentFirmwareVersion,omitempty"`
	// FirmwareUpdateStatus - READ-ONLY; True if there is a firmware update ready to install on this cache.  The firmware will automatically be installed after firmwareUpdateDeadline if not triggered earlier via the upgrade operation. Possible values include: 'Available', 'Unavailable'
	FirmwareUpdateStatus FirmwareStatusType `json:"firmwareUpdateStatus,omitempty"`
	// FirmwareUpdateDeadline - READ-ONLY; Time at which the pending firmware update will automatically be installed on the cache.
	FirmwareUpdateDeadline *date.Time `json:"firmwareUpdateDeadline,omitempty"`
	// LastFirmwareUpdate - READ-ONLY; Time of the last successful firmware update.
	LastFirmwareUpdate *date.Time `json:"lastFirmwareUpdate,omitempty"`
	// PendingFirmwareVersion - READ-ONLY; When firmwareUpdateAvailable is true, this field holds the version string for the update.
	PendingFirmwareVersion *string `json:"pendingFirmwareVersion,omitempty"`
}

// MarshalJSON is the custom marshaler for CacheUpgradeStatus.
func (cus CacheUpgradeStatus) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// ClfsTarget storage container for use as a CLFS StorageTarget.
type ClfsTarget struct {
	// Target - URL of storage container.
	Target *string `json:"target,omitempty"`
}

// CloudError an error response.
type CloudError struct {
	// Error - The body of the error.
	Error *CloudErrorBody `json:"error,omitempty"`
}

// CloudErrorBody an error response.
type CloudErrorBody struct {
	// Code - An identifier for the error. Codes are invariant and are intended to be consumed programmatically.
	Code *string `json:"code,omitempty"`
	// Details - A list of additional details about the error.
	Details *[]CloudErrorBody `json:"details,omitempty"`
	// Message - A message describing the error, intended to be suitable for display in a user interface.
	Message *string `json:"message,omitempty"`
	// Target - The target of the particular error. For example, the name of the property in error.
	Target *string `json:"target,omitempty"`
}

// NamespaceJunction a namespace junction.
type NamespaceJunction struct {
	// NamespacePath - Namespace path on a cache for a storage target.
	NamespacePath *string `json:"namespacePath,omitempty"`
	// TargetPath - Path in storage target to which namespacePath points.
	TargetPath *string `json:"targetPath,omitempty"`
	// NfsExport - NFS export where targetPath exists.
	NfsExport *string `json:"nfsExport,omitempty"`
}

// Nfs3Target an NFS mount point for use as a StorageTarget.
type Nfs3Target struct {
	// Target - IP or name of an NFS Storage Target host, ie: 10.0.44.44
	Target *string `json:"target,omitempty"`
	// UsageModel - Identifies the primary usage model to be used for this storage target.   GET choices from .../usageModels
	UsageModel *string `json:"usageModel,omitempty"`
}

// ResourceSku a resource SKU
type ResourceSku struct {
	// ResourceType - READ-ONLY; The type of resource the sku applies to.
	ResourceType *string `json:"resourceType,omitempty"`
	// Capabilities - A list of capabilities of this SKU, such as throughput or ops/sec
	Capabilities *[]ResourceSkuCapabilities `json:"capabilities,omitempty"`
	// Locations - READ-ONLY; The set of locations that the SKU is available. This will be supported and registered Azure Geo Regions (e.g. West US, East US, Southeast Asia, etc.).
	Locations *[]string `json:"locations,omitempty"`
	// LocationInfo - The set of locations that the SKU is available.
	LocationInfo *[]ResourceSkuLocationInfo `json:"locationInfo,omitempty"`
	// Name - The name of this sku.
	Name *string `json:"name,omitempty"`
	// Restrictions - The restrictions because of which SKU cannot be used. This is empty if there are no restrictions.
	Restrictions *[]Restriction `json:"restrictions,omitempty"`
}

// MarshalJSON is the custom marshaler for ResourceSku.
func (rs ResourceSku) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if rs.Capabilities != nil {
		objectMap["capabilities"] = rs.Capabilities
	}
	if rs.LocationInfo != nil {
		objectMap["locationInfo"] = rs.LocationInfo
	}
	if rs.Name != nil {
		objectMap["name"] = rs.Name
	}
	if rs.Restrictions != nil {
		objectMap["restrictions"] = rs.Restrictions
	}
	return json.Marshal(objectMap)
}

// ResourceSkuCapabilities a resource SKU capability.
type ResourceSkuCapabilities struct {
	// Name - Name of a capability, such as ops/sec
	Name *string `json:"name,omitempty"`
	// Value - Quantity, if the capability is measured by quantity
	Value *string `json:"value,omitempty"`
}

// ResourceSkuLocationInfo resource SKU location information.
type ResourceSkuLocationInfo struct {
	// Location - Location where this Sku is available
	Location *string `json:"location,omitempty"`
	// Zones - Zones if any.
	Zones *[]string `json:"zones,omitempty"`
}

// ResourceSkusResult the response from the List Cache SKUs operation.
type ResourceSkusResult struct {
	autorest.Response `json:"-"`
	// NextLink - The uri to fetch the next page of cache Skus.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - READ-ONLY; The list of skus available for the subscription.
	Value *[]ResourceSku `json:"value,omitempty"`
}

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

// ResourceSkusResultIterator provides access to a complete listing of ResourceSku values.
type ResourceSkusResultIterator struct {
	i    int
	page ResourceSkusResultPage
}

// 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 *ResourceSkusResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/ResourceSkusResultIterator.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 *ResourceSkusResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

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

// Creates a new instance of the ResourceSkusResultIterator type.
func NewResourceSkusResultIterator(page ResourceSkusResultPage) ResourceSkusResultIterator {
	return ResourceSkusResultIterator{page: page}
}

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

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

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

// ResourceSkusResultPage contains a page of ResourceSku values.
type ResourceSkusResultPage struct {
	fn  func(context.Context, ResourceSkusResult) (ResourceSkusResult, error)
	rsr ResourceSkusResult
}

// 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 *ResourceSkusResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/ResourceSkusResultPage.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.rsr)
		if err != nil {
			return err
		}
		page.rsr = 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 *ResourceSkusResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

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

// Response returns the raw server response from the last page request.
func (page ResourceSkusResultPage) Response() ResourceSkusResult {
	return page.rsr
}

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

// Creates a new instance of the ResourceSkusResultPage type.
func NewResourceSkusResultPage(cur ResourceSkusResult, getNextPage func(context.Context, ResourceSkusResult) (ResourceSkusResult, error)) ResourceSkusResultPage {
	return ResourceSkusResultPage{
		fn:  getNextPage,
		rsr: cur,
	}
}

// Restriction the restriction because of which SKU cannot be used.
type Restriction struct {
	// Type - READ-ONLY; The type of restrictions. As of now only possible value for this is location.
	Type *string `json:"type,omitempty"`
	// Values - READ-ONLY; The value of restrictions. If the restriction type is set to location. This would be different locations where the SKU is restricted.
	Values *[]string `json:"values,omitempty"`
	// ReasonCode - The reason for the restriction. As of now this can be "QuotaId" or "NotAvailableForSubscription". Quota Id is set when the SKU has requiredQuotas parameter as the subscription does not belong to that quota. The "NotAvailableForSubscription" is related to capacity at DC. Possible values include: 'QuotaID', 'NotAvailableForSubscription'
	ReasonCode ReasonCode `json:"reasonCode,omitempty"`
}

// MarshalJSON is the custom marshaler for Restriction.
func (r Restriction) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if r.ReasonCode != "" {
		objectMap["reasonCode"] = r.ReasonCode
	}
	return json.Marshal(objectMap)
}

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

// StorageTarget a storage system being cached by a Cache.
type StorageTarget struct {
	autorest.Response `json:"-"`
	// Name - READ-ONLY; A fully qualified URL.
	Name *string `json:"name,omitempty"`
	// ID - READ-ONLY; Resource Id
	ID *string `json:"id,omitempty"`
	// Type - READ-ONLY; Type for the storage target; Microsoft.StorageCache/Cache/StorageTarget
	Type *string `json:"type,omitempty"`
	// StorageTargetProperties - Properties of the storage target.
	*StorageTargetProperties `json:"properties,omitempty"`
}

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

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

	return nil
}

// StorageTargetProperties properties of the storage target.
type StorageTargetProperties struct {
	// Junctions - List of cache namespace to target namespace associations.
	Junctions *[]NamespaceJunction `json:"junctions,omitempty"`
	// TargetType - Type for storage target. Possible values include: 'StorageTargetTypeNfs3', 'StorageTargetTypeClfs', 'StorageTargetTypeUnknown'
	TargetType StorageTargetType `json:"targetType,omitempty"`
	// ProvisioningState - ARM provisioning state, see https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#provisioningstate-property. Possible values include: 'Succeeded', 'Failed', 'Cancelled', 'Creating', 'Deleting', 'Updating'
	ProvisioningState ProvisioningStateType `json:"provisioningState,omitempty"`
	// Nfs3 - Properties when nfs3 target.
	Nfs3 *Nfs3Target `json:"nfs3,omitempty"`
	// Clfs - Properties when clfs target.
	Clfs *ClfsTarget `json:"clfs,omitempty"`
	// Unknown - Properties when unknown target.
	Unknown *UnknownTarget `json:"unknown,omitempty"`
}

// StorageTargetsCreateFuture an abstraction for monitoring and retrieving the results of a long-running
// operation.
type StorageTargetsCreateFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(StorageTargetsClient) (StorageTarget, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *StorageTargetsCreateFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for StorageTargetsCreateFuture.Result.
func (future *StorageTargetsCreateFuture) result(client StorageTargetsClient) (st StorageTarget, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.StorageTargetsCreateFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		st.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.StorageTargetsCreateFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if st.Response.Response, err = future.GetResult(sender); err == nil && st.Response.Response.StatusCode != http.StatusNoContent {
		st, err = client.CreateResponder(st.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.StorageTargetsCreateFuture", "Result", st.Response.Response, "Failure responding to request")
		}
	}
	return
}

// StorageTargetsDeleteFuture an abstraction for monitoring and retrieving the results of a long-running
// operation.
type StorageTargetsDeleteFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(StorageTargetsClient) (SetObject, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *StorageTargetsDeleteFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for StorageTargetsDeleteFuture.Result.
func (future *StorageTargetsDeleteFuture) result(client StorageTargetsClient) (so SetObject, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "storagecache.StorageTargetsDeleteFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		so.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("storagecache.StorageTargetsDeleteFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if so.Response.Response, err = future.GetResult(sender); err == nil && so.Response.Response.StatusCode != http.StatusNoContent {
		so, err = client.DeleteResponder(so.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "storagecache.StorageTargetsDeleteFuture", "Result", so.Response.Response, "Failure responding to request")
		}
	}
	return
}

// StorageTargetsResult a list of storage targets.
type StorageTargetsResult struct {
	autorest.Response `json:"-"`
	// NextLink - The uri to fetch the next page of storage targets.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - The list of storage targets defined for the cache.
	Value *[]StorageTarget `json:"value,omitempty"`
}

// StorageTargetsResultIterator provides access to a complete listing of StorageTarget values.
type StorageTargetsResultIterator struct {
	i    int
	page StorageTargetsResultPage
}

// 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 *StorageTargetsResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/StorageTargetsResultIterator.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 *StorageTargetsResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

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

// Creates a new instance of the StorageTargetsResultIterator type.
func NewStorageTargetsResultIterator(page StorageTargetsResultPage) StorageTargetsResultIterator {
	return StorageTargetsResultIterator{page: page}
}

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

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

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

// StorageTargetsResultPage contains a page of StorageTarget values.
type StorageTargetsResultPage struct {
	fn  func(context.Context, StorageTargetsResult) (StorageTargetsResult, error)
	str StorageTargetsResult
}

// 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 *StorageTargetsResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/StorageTargetsResultPage.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.str)
		if err != nil {
			return err
		}
		page.str = 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 *StorageTargetsResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

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

// Response returns the raw server response from the last page request.
func (page StorageTargetsResultPage) Response() StorageTargetsResult {
	return page.str
}

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

// Creates a new instance of the StorageTargetsResultPage type.
func NewStorageTargetsResultPage(cur StorageTargetsResult, getNextPage func(context.Context, StorageTargetsResult) (StorageTargetsResult, error)) StorageTargetsResultPage {
	return StorageTargetsResultPage{
		fn:  getNextPage,
		str: cur,
	}
}

// UnknownTarget storage container for use as a Unknown StorageTarget.
type UnknownTarget struct {
	// UnknownMap - Dictionary of string->string pairs containing information about the StorageTarget.
	UnknownMap map[string]*string `json:"unknownMap"`
}

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

// UsageModel a usage model.
type UsageModel struct {
	// Display - Localized information describing this usage model.
	Display *UsageModelDisplay `json:"display,omitempty"`
	// ModelName - Non localized keyword naming this usage model.
	ModelName *string `json:"modelName,omitempty"`
	// TargetType - The type of Storage Target to which this model is applicable (only nfs for now)
	TargetType *string `json:"targetType,omitempty"`
}

// UsageModelDisplay localized information describing this usage model.
type UsageModelDisplay struct {
	// Description - String to display for this usage model.
	Description *string `json:"description,omitempty"`
}

// UsageModelsResult a list of cache usage models.
type UsageModelsResult struct {
	autorest.Response `json:"-"`
	// NextLink - The uri to fetch the next page of cache usage models.
	NextLink *string `json:"nextLink,omitempty"`
	// Value - The list of usage models available for the subscription.
	Value *[]UsageModel `json:"value,omitempty"`
}

// UsageModelsResultIterator provides access to a complete listing of UsageModel values.
type UsageModelsResultIterator struct {
	i    int
	page UsageModelsResultPage
}

// 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 *UsageModelsResultIterator) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/UsageModelsResultIterator.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 *UsageModelsResultIterator) Next() error {
	return iter.NextWithContext(context.Background())
}

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

// Creates a new instance of the UsageModelsResultIterator type.
func NewUsageModelsResultIterator(page UsageModelsResultPage) UsageModelsResultIterator {
	return UsageModelsResultIterator{page: page}
}

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

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

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

// UsageModelsResultPage contains a page of UsageModel values.
type UsageModelsResultPage struct {
	fn  func(context.Context, UsageModelsResult) (UsageModelsResult, error)
	umr UsageModelsResult
}

// 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 *UsageModelsResultPage) NextWithContext(ctx context.Context) (err error) {
	if tracing.IsEnabled() {
		ctx = tracing.StartSpan(ctx, fqdn+"/UsageModelsResultPage.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.umr)
		if err != nil {
			return err
		}
		page.umr = 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 *UsageModelsResultPage) Next() error {
	return page.NextWithContext(context.Background())
}

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

// Response returns the raw server response from the last page request.
func (page UsageModelsResultPage) Response() UsageModelsResult {
	return page.umr
}

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

// Creates a new instance of the UsageModelsResultPage type.
func NewUsageModelsResultPage(cur UsageModelsResult, getNextPage func(context.Context, UsageModelsResult) (UsageModelsResult, error)) UsageModelsResultPage {
	return UsageModelsResultPage{
		fn:  getNextPage,
		umr: cur,
	}
}
