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

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

package azblob

import (
	"context"
	"fmt"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type serviceClient struct {
	endpoint string
	pl       runtime.Pipeline
}

// newServiceClient creates a new instance of serviceClient with the specified values.
// endpoint - The URL of the service account, container, or blob that is the target of the desired operation.
// pl - the pipeline used for sending requests and handling responses.
func newServiceClient(endpoint string, pl runtime.Pipeline) *serviceClient {
	client := &serviceClient{
		endpoint: endpoint,
		pl:       pl,
	}
	return client
}

// FilterBlobs - The Filter Blobs operation enables callers to list blobs across all containers whose tags match a given search
// expression. Filter blobs searches across all containers within a storage account but can
// be scoped within the expression to a single container.
// If the operation fails it returns an *azcore.ResponseError type.
// options - serviceClientFilterBlobsOptions contains the optional parameters for the serviceClient.FilterBlobs method.
func (client *serviceClient) FilterBlobs(ctx context.Context, options *serviceClientFilterBlobsOptions) (serviceClientFilterBlobsResponse, error) {
	req, err := client.filterBlobsCreateRequest(ctx, options)
	if err != nil {
		return serviceClientFilterBlobsResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientFilterBlobsResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusOK) {
		return serviceClientFilterBlobsResponse{}, runtime.NewResponseError(resp)
	}
	return client.filterBlobsHandleResponse(resp)
}

// filterBlobsCreateRequest creates the FilterBlobs request.
func (client *serviceClient) filterBlobsCreateRequest(ctx context.Context, options *serviceClientFilterBlobsOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("comp", "blobs")
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	if options != nil && options.Where != nil {
		reqQP.Set("where", *options.Where)
	}
	if options != nil && options.Marker != nil {
		reqQP.Set("marker", *options.Marker)
	}
	if options != nil && options.Maxresults != nil {
		reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, nil
}

// filterBlobsHandleResponse handles the FilterBlobs response.
func (client *serviceClient) filterBlobsHandleResponse(resp *http.Response) (serviceClientFilterBlobsResponse, error) {
	result := serviceClientFilterBlobsResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	if val := resp.Header.Get("Date"); val != "" {
		date, err := time.Parse(time.RFC1123, val)
		if err != nil {
			return serviceClientFilterBlobsResponse{}, err
		}
		result.Date = &date
	}
	if err := runtime.UnmarshalAsXML(resp, &result.FilterBlobSegment); err != nil {
		return serviceClientFilterBlobsResponse{}, err
	}
	return result, nil
}

// GetAccountInfo - Returns the sku name and account kind
// If the operation fails it returns an *azcore.ResponseError type.
// options - serviceClientGetAccountInfoOptions contains the optional parameters for the serviceClient.GetAccountInfo method.
func (client *serviceClient) GetAccountInfo(ctx context.Context, options *serviceClientGetAccountInfoOptions) (serviceClientGetAccountInfoResponse, error) {
	req, err := client.getAccountInfoCreateRequest(ctx, options)
	if err != nil {
		return serviceClientGetAccountInfoResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientGetAccountInfoResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusOK) {
		return serviceClientGetAccountInfoResponse{}, runtime.NewResponseError(resp)
	}
	return client.getAccountInfoHandleResponse(resp)
}

// getAccountInfoCreateRequest creates the GetAccountInfo request.
func (client *serviceClient) getAccountInfoCreateRequest(ctx context.Context, options *serviceClientGetAccountInfoOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("restype", "account")
	reqQP.Set("comp", "properties")
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	req.Raw().Header.Set("Accept", "application/xml")
	return req, nil
}

// getAccountInfoHandleResponse handles the GetAccountInfo response.
func (client *serviceClient) getAccountInfoHandleResponse(resp *http.Response) (serviceClientGetAccountInfoResponse, error) {
	result := serviceClientGetAccountInfoResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	if val := resp.Header.Get("Date"); val != "" {
		date, err := time.Parse(time.RFC1123, val)
		if err != nil {
			return serviceClientGetAccountInfoResponse{}, err
		}
		result.Date = &date
	}
	if val := resp.Header.Get("x-ms-sku-name"); val != "" {
		result.SKUName = (*SKUName)(&val)
	}
	if val := resp.Header.Get("x-ms-account-kind"); val != "" {
		result.AccountKind = (*AccountKind)(&val)
	}
	if val := resp.Header.Get("x-ms-is-hns-enabled"); val != "" {
		isHierarchicalNamespaceEnabled, err := strconv.ParseBool(val)
		if err != nil {
			return serviceClientGetAccountInfoResponse{}, err
		}
		result.IsHierarchicalNamespaceEnabled = &isHierarchicalNamespaceEnabled
	}
	return result, nil
}

// GetProperties - gets the properties of a storage account's Blob service, including properties for Storage Analytics and
// CORS (Cross-Origin Resource Sharing) rules.
// If the operation fails it returns an *azcore.ResponseError type.
// options - serviceClientGetPropertiesOptions contains the optional parameters for the serviceClient.GetProperties method.
func (client *serviceClient) GetProperties(ctx context.Context, options *serviceClientGetPropertiesOptions) (serviceClientGetPropertiesResponse, error) {
	req, err := client.getPropertiesCreateRequest(ctx, options)
	if err != nil {
		return serviceClientGetPropertiesResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientGetPropertiesResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusOK) {
		return serviceClientGetPropertiesResponse{}, runtime.NewResponseError(resp)
	}
	return client.getPropertiesHandleResponse(resp)
}

// getPropertiesCreateRequest creates the GetProperties request.
func (client *serviceClient) getPropertiesCreateRequest(ctx context.Context, options *serviceClientGetPropertiesOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("restype", "service")
	reqQP.Set("comp", "properties")
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, nil
}

// getPropertiesHandleResponse handles the GetProperties response.
func (client *serviceClient) getPropertiesHandleResponse(resp *http.Response) (serviceClientGetPropertiesResponse, error) {
	result := serviceClientGetPropertiesResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	if err := runtime.UnmarshalAsXML(resp, &result.StorageServiceProperties); err != nil {
		return serviceClientGetPropertiesResponse{}, err
	}
	return result, nil
}

// GetStatistics - Retrieves statistics related to replication for the Blob service. It is only available on the secondary
// location endpoint when read-access geo-redundant replication is enabled for the storage account.
// If the operation fails it returns an *azcore.ResponseError type.
// options - serviceClientGetStatisticsOptions contains the optional parameters for the serviceClient.GetStatistics method.
func (client *serviceClient) GetStatistics(ctx context.Context, options *serviceClientGetStatisticsOptions) (serviceClientGetStatisticsResponse, error) {
	req, err := client.getStatisticsCreateRequest(ctx, options)
	if err != nil {
		return serviceClientGetStatisticsResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientGetStatisticsResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusOK) {
		return serviceClientGetStatisticsResponse{}, runtime.NewResponseError(resp)
	}
	return client.getStatisticsHandleResponse(resp)
}

// getStatisticsCreateRequest creates the GetStatistics request.
func (client *serviceClient) getStatisticsCreateRequest(ctx context.Context, options *serviceClientGetStatisticsOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("restype", "service")
	reqQP.Set("comp", "stats")
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, nil
}

// getStatisticsHandleResponse handles the GetStatistics response.
func (client *serviceClient) getStatisticsHandleResponse(resp *http.Response) (serviceClientGetStatisticsResponse, error) {
	result := serviceClientGetStatisticsResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	if val := resp.Header.Get("Date"); val != "" {
		date, err := time.Parse(time.RFC1123, val)
		if err != nil {
			return serviceClientGetStatisticsResponse{}, err
		}
		result.Date = &date
	}
	if err := runtime.UnmarshalAsXML(resp, &result.StorageServiceStats); err != nil {
		return serviceClientGetStatisticsResponse{}, err
	}
	return result, nil
}

// GetUserDelegationKey - Retrieves a user delegation key for the Blob service. This is only a valid operation when using
// bearer token authentication.
// If the operation fails it returns an *azcore.ResponseError type.
// keyInfo - Key information
// options - serviceClientGetUserDelegationKeyOptions contains the optional parameters for the serviceClient.GetUserDelegationKey
// method.
func (client *serviceClient) GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, options *serviceClientGetUserDelegationKeyOptions) (serviceClientGetUserDelegationKeyResponse, error) {
	req, err := client.getUserDelegationKeyCreateRequest(ctx, keyInfo, options)
	if err != nil {
		return serviceClientGetUserDelegationKeyResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientGetUserDelegationKeyResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusOK) {
		return serviceClientGetUserDelegationKeyResponse{}, runtime.NewResponseError(resp)
	}
	return client.getUserDelegationKeyHandleResponse(resp)
}

// getUserDelegationKeyCreateRequest creates the GetUserDelegationKey request.
func (client *serviceClient) getUserDelegationKeyCreateRequest(ctx context.Context, keyInfo KeyInfo, options *serviceClientGetUserDelegationKeyOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("restype", "service")
	reqQP.Set("comp", "userdelegationkey")
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, runtime.MarshalAsXML(req, keyInfo)
}

// getUserDelegationKeyHandleResponse handles the GetUserDelegationKey response.
func (client *serviceClient) getUserDelegationKeyHandleResponse(resp *http.Response) (serviceClientGetUserDelegationKeyResponse, error) {
	result := serviceClientGetUserDelegationKeyResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	if val := resp.Header.Get("Date"); val != "" {
		date, err := time.Parse(time.RFC1123, val)
		if err != nil {
			return serviceClientGetUserDelegationKeyResponse{}, err
		}
		result.Date = &date
	}
	if err := runtime.UnmarshalAsXML(resp, &result.UserDelegationKey); err != nil {
		return serviceClientGetUserDelegationKeyResponse{}, err
	}
	return result, nil
}

// ListContainersSegment - The List Containers Segment operation returns a list of the containers under the specified account
// If the operation fails it returns an *azcore.ResponseError type.
// options - serviceClientListContainersSegmentOptions contains the optional parameters for the serviceClient.ListContainersSegment
// method.
func (client *serviceClient) ListContainersSegment(options *serviceClientListContainersSegmentOptions) *serviceClientListContainersSegmentPager {
	return &serviceClientListContainersSegmentPager{
		client: client,
		requester: func(ctx context.Context) (*policy.Request, error) {
			return client.listContainersSegmentCreateRequest(ctx, options)
		},
		advancer: func(ctx context.Context, resp serviceClientListContainersSegmentResponse) (*policy.Request, error) {
			return runtime.NewRequest(ctx, http.MethodGet, *resp.ListContainersSegmentResponse.NextMarker)
		},
	}
}

// listContainersSegmentCreateRequest creates the ListContainersSegment request.
func (client *serviceClient) listContainersSegmentCreateRequest(ctx context.Context, options *serviceClientListContainersSegmentOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("comp", "list")
	if options != nil && options.Prefix != nil {
		reqQP.Set("prefix", *options.Prefix)
	}
	if options != nil && options.Marker != nil {
		reqQP.Set("marker", *options.Marker)
	}
	if options != nil && options.Maxresults != nil {
		reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10))
	}
	if options != nil && options.Include != nil {
		reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ","))
	}
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, nil
}

// listContainersSegmentHandleResponse handles the ListContainersSegment response.
func (client *serviceClient) listContainersSegmentHandleResponse(resp *http.Response) (serviceClientListContainersSegmentResponse, error) {
	result := serviceClientListContainersSegmentResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	if err := runtime.UnmarshalAsXML(resp, &result.ListContainersSegmentResponse); err != nil {
		return serviceClientListContainersSegmentResponse{}, err
	}
	return result, nil
}

// SetProperties - Sets properties for a storage account's Blob service endpoint, including properties for Storage Analytics
// and CORS (Cross-Origin Resource Sharing) rules
// If the operation fails it returns an *azcore.ResponseError type.
// storageServiceProperties - The StorageService properties.
// options - serviceClientSetPropertiesOptions contains the optional parameters for the serviceClient.SetProperties method.
func (client *serviceClient) SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, options *serviceClientSetPropertiesOptions) (serviceClientSetPropertiesResponse, error) {
	req, err := client.setPropertiesCreateRequest(ctx, storageServiceProperties, options)
	if err != nil {
		return serviceClientSetPropertiesResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientSetPropertiesResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusAccepted) {
		return serviceClientSetPropertiesResponse{}, runtime.NewResponseError(resp)
	}
	return client.setPropertiesHandleResponse(resp)
}

// setPropertiesCreateRequest creates the SetProperties request.
func (client *serviceClient) setPropertiesCreateRequest(ctx context.Context, storageServiceProperties StorageServiceProperties, options *serviceClientSetPropertiesOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("restype", "service")
	reqQP.Set("comp", "properties")
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, runtime.MarshalAsXML(req, storageServiceProperties)
}

// setPropertiesHandleResponse handles the SetProperties response.
func (client *serviceClient) setPropertiesHandleResponse(resp *http.Response) (serviceClientSetPropertiesResponse, error) {
	result := serviceClientSetPropertiesResponse{RawResponse: resp}
	if val := resp.Header.Get("x-ms-client-request-id"); val != "" {
		result.ClientRequestID = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	return result, nil
}

// SubmitBatch - The Batch operation allows multiple API calls to be embedded into a single HTTP request.
// If the operation fails it returns an *azcore.ResponseError type.
// contentLength - The length of the request.
// multipartContentType - Required. The value of this header must be multipart/mixed with a batch boundary. Example header
// value: multipart/mixed; boundary=batch_
// body - Initial data
// options - serviceClientSubmitBatchOptions contains the optional parameters for the serviceClient.SubmitBatch method.
func (client *serviceClient) SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body io.ReadSeekCloser, options *serviceClientSubmitBatchOptions) (serviceClientSubmitBatchResponse, error) {
	req, err := client.submitBatchCreateRequest(ctx, contentLength, multipartContentType, body, options)
	if err != nil {
		return serviceClientSubmitBatchResponse{}, err
	}
	resp, err := client.pl.Do(req)
	if err != nil {
		return serviceClientSubmitBatchResponse{}, err
	}
	if !runtime.HasStatusCode(resp, http.StatusOK) {
		return serviceClientSubmitBatchResponse{}, runtime.NewResponseError(resp)
	}
	return client.submitBatchHandleResponse(resp)
}

// submitBatchCreateRequest creates the SubmitBatch request.
func (client *serviceClient) submitBatchCreateRequest(ctx context.Context, contentLength int64, multipartContentType string, body io.ReadSeekCloser, options *serviceClientSubmitBatchOptions) (*policy.Request, error) {
	req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint)
	if err != nil {
		return nil, err
	}
	reqQP := req.Raw().URL.Query()
	reqQP.Set("comp", "batch")
	if options != nil && options.Timeout != nil {
		reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10))
	}
	req.Raw().URL.RawQuery = reqQP.Encode()
	runtime.SkipBodyDownload(req)
	req.Raw().Header.Set("Content-Length", strconv.FormatInt(contentLength, 10))
	req.Raw().Header.Set("Content-Type", multipartContentType)
	req.Raw().Header.Set("x-ms-version", "2020-10-02")
	if options != nil && options.RequestID != nil {
		req.Raw().Header.Set("x-ms-client-request-id", *options.RequestID)
	}
	req.Raw().Header.Set("Accept", "application/xml")
	return req, runtime.MarshalAsXML(req, body)
}

// submitBatchHandleResponse handles the SubmitBatch response.
func (client *serviceClient) submitBatchHandleResponse(resp *http.Response) (serviceClientSubmitBatchResponse, error) {
	result := serviceClientSubmitBatchResponse{RawResponse: resp}
	if val := resp.Header.Get("Content-Type"); val != "" {
		result.ContentType = &val
	}
	if val := resp.Header.Get("x-ms-request-id"); val != "" {
		result.RequestID = &val
	}
	if val := resp.Header.Get("x-ms-version"); val != "" {
		result.Version = &val
	}
	return result, nil
}
