// Package insights implements the Azure ARM Insights service API version v1.
//
// Composite Swagger for Application Insights Data Client
package insights

// Copyright (c) Microsoft and contributors.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

import (
	"context"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/Azure/go-autorest/autorest/validation"
	"net/http"
)

const (
	// DefaultBaseURI is the default URI used for the service Insights
	DefaultBaseURI = "https://api.applicationinsights.io/v1"
)

// BaseClient is the base client for Insights.
type BaseClient struct {
	autorest.Client
	BaseURI string
	AppID   string
}

// New creates an instance of the BaseClient client.
func New(appID string) BaseClient {
	return NewWithBaseURI(DefaultBaseURI, appID)
}

// NewWithBaseURI creates an instance of the BaseClient client.
func NewWithBaseURI(baseURI string, appID string) BaseClient {
	return BaseClient{
		Client:  autorest.NewClientWithUserAgent(UserAgent()),
		BaseURI: baseURI,
		AppID:   appID,
	}
}

// GetEvent gets the data for a single event
// Parameters:
// eventType - the type of events to query; either a standard event type (`traces`, `customEvents`,
// `pageViews`, `requests`, `dependencies`, `exceptions`, `availabilityResults`) or `$all` to query across all
// event types.
// eventID - ID of event.
// timespan - optional. The timespan over which to retrieve events. This is an ISO8601 time period value.  This
// timespan is applied in addition to any that are specified in the Odata expression.
func (client BaseClient) GetEvent(ctx context.Context, eventType EventType, eventID string, timespan *string) (result EventsResults, err error) {
	req, err := client.GetEventPreparer(ctx, eventType, eventID, timespan)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEvent", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetEventSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEvent", resp, "Failure sending request")
		return
	}

	result, err = client.GetEventResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEvent", resp, "Failure responding to request")
	}

	return
}

// GetEventPreparer prepares the GetEvent request.
func (client BaseClient) GetEventPreparer(ctx context.Context, eventType EventType, eventID string, timespan *string) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId":     autorest.Encode("path", client.AppID),
		"eventId":   autorest.Encode("path", eventID),
		"eventType": autorest.Encode("path", eventType),
	}

	queryParameters := map[string]interface{}{}
	if timespan != nil {
		queryParameters["timespan"] = autorest.Encode("query", *timespan)
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/events/{eventType}/{eventId}", pathParameters),
		autorest.WithQueryParameters(queryParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetEventSender sends the GetEvent request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetEventSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetEventResponder handles the response to the GetEvent request. The method always
// closes the http.Response Body.
func (client BaseClient) GetEventResponder(resp *http.Response) (result EventsResults, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetEvents executes an OData query for events
// Parameters:
// eventType - the type of events to query; either a standard event type (`traces`, `customEvents`,
// `pageViews`, `requests`, `dependencies`, `exceptions`, `availabilityResults`) or `$all` to query across all
// event types.
// timespan - optional. The timespan over which to retrieve events. This is an ISO8601 time period value.  This
// timespan is applied in addition to any that are specified in the Odata expression.
// filter - an expression used to filter the returned events
// search - a free-text search expression to match for whether a particular event should be returned
// orderby - a comma-separated list of properties with \"asc\" (the default) or \"desc\" to control the order
// of returned events
// selectParameter - limits the properties to just those requested on each returned event
// skip - the number of items to skip over before returning events
// top - the number of events to return
// formatParameter - format for the returned events
// count - request a count of matching items included with the returned events
// apply - an expression used for aggregation over returned events
func (client BaseClient) GetEvents(ctx context.Context, eventType EventType, timespan *string, filter string, search string, orderby string, selectParameter string, skip *int32, top *int32, formatParameter string, count *bool, apply string) (result EventsResults, err error) {
	req, err := client.GetEventsPreparer(ctx, eventType, timespan, filter, search, orderby, selectParameter, skip, top, formatParameter, count, apply)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEvents", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetEventsSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEvents", resp, "Failure sending request")
		return
	}

	result, err = client.GetEventsResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEvents", resp, "Failure responding to request")
	}

	return
}

// GetEventsPreparer prepares the GetEvents request.
func (client BaseClient) GetEventsPreparer(ctx context.Context, eventType EventType, timespan *string, filter string, search string, orderby string, selectParameter string, skip *int32, top *int32, formatParameter string, count *bool, apply string) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId":     autorest.Encode("path", client.AppID),
		"eventType": autorest.Encode("path", eventType),
	}

	queryParameters := map[string]interface{}{}
	if timespan != nil {
		queryParameters["timespan"] = autorest.Encode("query", *timespan)
	}
	if len(filter) > 0 {
		queryParameters["$filter"] = autorest.Encode("query", filter)
	}
	if len(search) > 0 {
		queryParameters["$search"] = autorest.Encode("query", search)
	}
	if len(orderby) > 0 {
		queryParameters["$orderby"] = autorest.Encode("query", orderby)
	}
	if len(selectParameter) > 0 {
		queryParameters["$select"] = autorest.Encode("query", selectParameter)
	}
	if skip != nil {
		queryParameters["$skip"] = autorest.Encode("query", *skip)
	}
	if top != nil {
		queryParameters["$top"] = autorest.Encode("query", *top)
	}
	if len(formatParameter) > 0 {
		queryParameters["$format"] = autorest.Encode("query", formatParameter)
	}
	if count != nil {
		queryParameters["$count"] = autorest.Encode("query", *count)
	}
	if len(apply) > 0 {
		queryParameters["$apply"] = autorest.Encode("query", apply)
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/events/{eventType}", pathParameters),
		autorest.WithQueryParameters(queryParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetEventsSender sends the GetEvents request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetEventsSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetEventsResponder handles the response to the GetEvents request. The method always
// closes the http.Response Body.
func (client BaseClient) GetEventsResponder(resp *http.Response) (result EventsResults, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetEventsMetadataOData gets OData EDMX metadata describing the event data model
func (client BaseClient) GetEventsMetadataOData(ctx context.Context) (result SetObject, err error) {
	req, err := client.GetEventsMetadataODataPreparer(ctx)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEventsMetadataOData", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetEventsMetadataODataSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEventsMetadataOData", resp, "Failure sending request")
		return
	}

	result, err = client.GetEventsMetadataODataResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetEventsMetadataOData", resp, "Failure responding to request")
	}

	return
}

// GetEventsMetadataODataPreparer prepares the GetEventsMetadataOData request.
func (client BaseClient) GetEventsMetadataODataPreparer(ctx context.Context) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId": autorest.Encode("path", client.AppID),
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/events/$metadata", pathParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetEventsMetadataODataSender sends the GetEventsMetadataOData request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetEventsMetadataODataSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetEventsMetadataODataResponder handles the response to the GetEventsMetadataOData request. The method always
// closes the http.Response Body.
func (client BaseClient) GetEventsMetadataODataResponder(resp *http.Response) (result SetObject, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result.Value),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetMetric gets data for a single metric.
// Parameters:
// metricID - ID of the metric. This is either a standard AI metric, or an application-specific custom metric.
// timespan - the timespan over which to retrieve metric values. This is an ISO8601 time period value. If
// timespan is omitted, a default time range of `PT12H` ("last 12 hours") is used. The actual timespan that is
// queried may be adjusted by the server based. In all cases, the actual time span used for the query is
// included in the response.
// interval - the time interval to use when retrieving metric values. This is an ISO8601 duration. If interval
// is omitted, the metric value is aggregated across the entire timespan. If interval is supplied, the server
// may adjust the interval to a more appropriate size based on the timespan used for the query. In all cases,
// the actual interval used for the query is included in the response.
// aggregation - the aggregation to use when computing the metric values. To retrieve more than one aggregation
// at a time, separate them with a comma. If no aggregation is specified, then the default aggregation for the
// metric is used.
// segment - the name of the dimension to segment the metric values by. This dimension must be applicable to
// the metric you are retrieving. To segment by more than one dimension at a time, separate them with a comma
// (,). In this case, the metric data will be segmented in the order the dimensions are listed in the
// parameter.
// top - the number of segments to return.  This value is only valid when segment is specified.
// orderby - the aggregation function and direction to sort the segments by.  This value is only valid when
// segment is specified.
// filter - an expression used to filter the results.  This value should be a valid OData filter expression
// where the keys of each clause should be applicable dimensions for the metric you are retrieving.
func (client BaseClient) GetMetric(ctx context.Context, metricID string, timespan *string, interval *string, aggregation []string, segment []string, top *int32, orderby string, filter string) (result MetricsResult, err error) {
	if err := validation.Validate([]validation.Validation{
		{TargetValue: aggregation,
			Constraints: []validation.Constraint{{Target: "aggregation", Name: validation.Null, Rule: false,
				Chain: []validation.Constraint{{Target: "aggregation", Name: validation.MinItems, Rule: 1, Chain: nil}}}}},
		{TargetValue: segment,
			Constraints: []validation.Constraint{{Target: "segment", Name: validation.Null, Rule: false,
				Chain: []validation.Constraint{{Target: "segment", Name: validation.MinItems, Rule: 1, Chain: nil}}}}}}); err != nil {
		return result, validation.NewError("insights.BaseClient", "GetMetric", err.Error())
	}

	req, err := client.GetMetricPreparer(ctx, metricID, timespan, interval, aggregation, segment, top, orderby, filter)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetric", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetMetricSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetric", resp, "Failure sending request")
		return
	}

	result, err = client.GetMetricResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetric", resp, "Failure responding to request")
	}

	return
}

// GetMetricPreparer prepares the GetMetric request.
func (client BaseClient) GetMetricPreparer(ctx context.Context, metricID string, timespan *string, interval *string, aggregation []string, segment []string, top *int32, orderby string, filter string) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId":    autorest.Encode("path", client.AppID),
		"metricId": autorest.Encode("path", metricID),
	}

	queryParameters := map[string]interface{}{}
	if timespan != nil {
		queryParameters["timespan"] = autorest.Encode("query", *timespan)
	}
	if interval != nil {
		queryParameters["interval"] = autorest.Encode("query", *interval)
	}
	if aggregation != nil && len(aggregation) > 0 {
		queryParameters["aggregation"] = autorest.Encode("query", aggregation, ",")
	}
	if segment != nil && len(segment) > 0 {
		queryParameters["segment"] = autorest.Encode("query", segment, ",")
	}
	if top != nil {
		queryParameters["top"] = autorest.Encode("query", *top)
	}
	if len(orderby) > 0 {
		queryParameters["orderby"] = autorest.Encode("query", orderby)
	}
	if len(filter) > 0 {
		queryParameters["filter"] = autorest.Encode("query", filter)
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/metrics/{metricId}", pathParameters),
		autorest.WithQueryParameters(queryParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetMetricSender sends the GetMetric request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetMetricSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetMetricResponder handles the response to the GetMetric request. The method always
// closes the http.Response Body.
func (client BaseClient) GetMetricResponder(resp *http.Response) (result MetricsResult, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetMetrics gets metric values for multiple metrics
// Parameters:
// body - the batched metrics query.
func (client BaseClient) GetMetrics(ctx context.Context, body []MetricsPostBodySchema) (result ListMetricsResultsItem, err error) {
	if err := validation.Validate([]validation.Validation{
		{TargetValue: body,
			Constraints: []validation.Constraint{{Target: "body", Name: validation.Null, Rule: true, Chain: nil}}}}); err != nil {
		return result, validation.NewError("insights.BaseClient", "GetMetrics", err.Error())
	}

	req, err := client.GetMetricsPreparer(ctx, body)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetrics", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetMetricsSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetrics", resp, "Failure sending request")
		return
	}

	result, err = client.GetMetricsResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetrics", resp, "Failure responding to request")
	}

	return
}

// GetMetricsPreparer prepares the GetMetrics request.
func (client BaseClient) GetMetricsPreparer(ctx context.Context, body []MetricsPostBodySchema) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId": autorest.Encode("path", client.AppID),
	}

	preparer := autorest.CreatePreparer(
		autorest.AsContentType("application/json; charset=utf-8"),
		autorest.AsPost(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/metrics", pathParameters),
		autorest.WithJSON(body))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetMetricsSender sends the GetMetrics request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetMetricsSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetMetricsResponder handles the response to the GetMetrics request. The method always
// closes the http.Response Body.
func (client BaseClient) GetMetricsResponder(resp *http.Response) (result ListMetricsResultsItem, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result.Value),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetMetricsMetadata gets metadata describing the available metrics
func (client BaseClient) GetMetricsMetadata(ctx context.Context) (result SetObject, err error) {
	req, err := client.GetMetricsMetadataPreparer(ctx)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetricsMetadata", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetMetricsMetadataSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetricsMetadata", resp, "Failure sending request")
		return
	}

	result, err = client.GetMetricsMetadataResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetMetricsMetadata", resp, "Failure responding to request")
	}

	return
}

// GetMetricsMetadataPreparer prepares the GetMetricsMetadata request.
func (client BaseClient) GetMetricsMetadataPreparer(ctx context.Context) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId": autorest.Encode("path", client.AppID),
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/metrics/metadata", pathParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetMetricsMetadataSender sends the GetMetricsMetadata request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetMetricsMetadataSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetMetricsMetadataResponder handles the response to the GetMetricsMetadata request. The method always
// closes the http.Response Body.
func (client BaseClient) GetMetricsMetadataResponder(resp *http.Response) (result SetObject, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result.Value),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetQuery executes an Analytics query for data
// Parameters:
// query - the Analytics query. Learn more about the [Analytics query
// syntax](https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/)
// timespan - optional. The timespan over which to query data. This is an ISO8601 time period value.  This
// timespan is applied in addition to any that are specified in the query expression.
func (client BaseClient) GetQuery(ctx context.Context, query string, timespan *string) (result QueryResults, err error) {
	req, err := client.GetQueryPreparer(ctx, query, timespan)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetQuery", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetQuerySender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetQuery", resp, "Failure sending request")
		return
	}

	result, err = client.GetQueryResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetQuery", resp, "Failure responding to request")
	}

	return
}

// GetQueryPreparer prepares the GetQuery request.
func (client BaseClient) GetQueryPreparer(ctx context.Context, query string, timespan *string) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId": autorest.Encode("path", client.AppID),
	}

	queryParameters := map[string]interface{}{
		"query": autorest.Encode("query", query),
	}
	if timespan != nil {
		queryParameters["timespan"] = autorest.Encode("query", *timespan)
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/query", pathParameters),
		autorest.WithQueryParameters(queryParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetQuerySender sends the GetQuery request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetQuerySender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetQueryResponder handles the response to the GetQuery request. The method always
// closes the http.Response Body.
func (client BaseClient) GetQueryResponder(resp *http.Response) (result QueryResults, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// GetQuerySchema gets Analytics query schema describing the data model
func (client BaseClient) GetQuerySchema(ctx context.Context) (result QueryResults, err error) {
	req, err := client.GetQuerySchemaPreparer(ctx)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetQuerySchema", nil, "Failure preparing request")
		return
	}

	resp, err := client.GetQuerySchemaSender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetQuerySchema", resp, "Failure sending request")
		return
	}

	result, err = client.GetQuerySchemaResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "GetQuerySchema", resp, "Failure responding to request")
	}

	return
}

// GetQuerySchemaPreparer prepares the GetQuerySchema request.
func (client BaseClient) GetQuerySchemaPreparer(ctx context.Context) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId": autorest.Encode("path", client.AppID),
	}

	preparer := autorest.CreatePreparer(
		autorest.AsGet(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/query/schema", pathParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// GetQuerySchemaSender sends the GetQuerySchema request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) GetQuerySchemaSender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// GetQuerySchemaResponder handles the response to the GetQuerySchema request. The method always
// closes the http.Response Body.
func (client BaseClient) GetQuerySchemaResponder(resp *http.Response) (result QueryResults, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}

// Query executes an Analytics query for data. [Here](/documentation/2-Using-the-API/Query) is an example for using
// POST with an Analytics query.
// Parameters:
// body - the Analytics query. Learn more about the [Analytics query
// syntax](https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/)
// timespan - optional. The timespan over which to query data. This is an ISO8601 time period value.  This
// timespan is applied in addition to any that are specified in the query expression.
func (client BaseClient) Query(ctx context.Context, body QueryBody, timespan *string) (result QueryResults, err error) {
	if err := validation.Validate([]validation.Validation{
		{TargetValue: body,
			Constraints: []validation.Constraint{{Target: "body.Query", Name: validation.Null, Rule: true, Chain: nil}}}}); err != nil {
		return result, validation.NewError("insights.BaseClient", "Query", err.Error())
	}

	req, err := client.QueryPreparer(ctx, body, timespan)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "Query", nil, "Failure preparing request")
		return
	}

	resp, err := client.QuerySender(req)
	if err != nil {
		result.Response = autorest.Response{Response: resp}
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "Query", resp, "Failure sending request")
		return
	}

	result, err = client.QueryResponder(resp)
	if err != nil {
		err = autorest.NewErrorWithError(err, "insights.BaseClient", "Query", resp, "Failure responding to request")
	}

	return
}

// QueryPreparer prepares the Query request.
func (client BaseClient) QueryPreparer(ctx context.Context, body QueryBody, timespan *string) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"appId": autorest.Encode("path", client.AppID),
	}

	queryParameters := map[string]interface{}{}
	if timespan != nil {
		queryParameters["timespan"] = autorest.Encode("query", *timespan)
	}

	preparer := autorest.CreatePreparer(
		autorest.AsContentType("application/json; charset=utf-8"),
		autorest.AsPost(),
		autorest.WithBaseURL(client.BaseURI),
		autorest.WithPathParameters("/apps/{appId}/query", pathParameters),
		autorest.WithJSON(body),
		autorest.WithQueryParameters(queryParameters))
	return preparer.Prepare((&http.Request{}).WithContext(ctx))
}

// QuerySender sends the Query request. The method will close the
// http.Response Body if it receives an error.
func (client BaseClient) QuerySender(req *http.Request) (*http.Response, error) {
	return autorest.SendWithSender(client, req,
		autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
}

// QueryResponder handles the response to the Query request. The method always
// closes the http.Response Body.
func (client BaseClient) QueryResponder(resp *http.Response) (result QueryResults, err error) {
	err = autorest.Respond(
		resp,
		client.ByInspecting(),
		azure.WithErrorUnlessStatusCode(http.StatusOK),
		autorest.ByUnmarshallingJSON(&result),
		autorest.ByClosing())
	result.Response = autorest.Response{Response: resp}
	return
}
