// Do not edit, this file was generated by github.com/apex/rpc.

package logs

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

// Alert represents configuration for performing alerting.
type Alert struct {
	// CreatedAt is a timestamp indicating when the alert was created. This field is read-only.
	CreatedAt time.Time `json:"created_at"`

	// Description is the description of the alert.
	Description string `json:"description"`

	// ID is the alert id. This field is read-only.
	ID string `json:"id"`

	// Interval is the interval in minutes for performing the alert.
	Interval int `json:"interval"`

	// Limit is the maximum number of events in the alert notification.
	Limit int `json:"limit"`

	// Muted is a boolean used ignore trigger and resolve notifications.
	Muted bool `json:"muted"`

	// Name is the name of the alert. This field is required.
	Name string `json:"name"`

	// NotificationID is the notification id for reporting alerts, when omitted the alert will not run. This field is required.
	NotificationID string `json:"notification_id"`

	// Operator is the operator used when comparing against the threshold. This field is required. Must be one of: ">", ">=", "<", "<=".
	Operator string `json:"operator"`

	// ProjectID is the associated project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the query performed by the alert. This field is required.
	Query string `json:"query"`

	// Severity is the severity of the alert. This field is required. Must be one of: "info", "notice", "error", "critical".
	Severity string `json:"severity"`

	// Threshold is the threshold for comparison against the selected operator.
	Threshold int `json:"threshold"`

	// UpdatedAt is a timestamp indicating when the alert was last updated. This field is read-only.
	UpdatedAt time.Time `json:"updated_at"`
}

// BooleanFieldStat represents a boolean field's stats.
type BooleanFieldStat struct {
	// Count is the number of times this field occurred in the sampled events.
	Count int `json:"count"`

	// Percent is the percentage of occurrences in the sampled events.
	Percent float64 `json:"percent"`

	// Value is the boolean value.
	Value bool `json:"value"`
}

// DiscoveredField represents a single discovered field.
type DiscoveredField struct {
	// Count is the number of times this field occurred in the sampled events.
	Count int `json:"count"`

	// Name is the field name.
	Name string `json:"name"`

	// Percent is the percentage of occurrences in the sampled events.
	Percent float64 `json:"percent"`

	// Type is the type of discovered field. Must be one of: "string", "number", "boolean".
	Type string `json:"type"`
}

// Event represents a single log event.
type Event struct {
	// Fields is the log fields.
	Fields map[string]interface{} `json:"fields"`

	// ID is the event id.
	ID string `json:"id"`

	// Level is the severity level. This field is required. Must be one of: "debug", "info", "notice", "warning", "error", "critical", "alert", "emergency".
	Level string `json:"level"`

	// Message is the log message. This field is required.
	Message string `json:"message"`

	// Timestamp is the creation timestamp.
	Timestamp time.Time `json:"timestamp"`
}

// InstanceConfig represents an instance's configuration.
type InstanceConfig struct {
	// ProjectID is the Google Cloud project id.
	ProjectID string `json:"project_id"`

	// Region is the Google Cloud region id.
	Region string `json:"region"`

	// TeamID is the Apex team id.
	TeamID string `json:"team_id"`
}

// Notification represents an alert notification.
type Notification struct {
	// CreatedAt is a timestamp indicating when the notification was created. This field is read-only.
	CreatedAt time.Time `json:"created_at"`

	// EmailAddresses is the receipients of the alert notifications.
	EmailAddresses []string `json:"email_addresses"`

	// ID is the notification id. This field is read-only.
	ID string `json:"id"`

	// Name is the name of the notification. This field is required.
	Name string `json:"name"`

	// PagerdutyServiceKey is the PagerDuty service key.
	PagerdutyServiceKey string `json:"pagerduty_service_key"`

	// ProjectID is the associated project id. This field is required.
	ProjectID string `json:"project_id"`

	// SlackChannel is the Slack channel name, otherwise the default for the webhook is used.
	SlackChannel string `json:"slack_channel"`

	// SlackWebhookURL is the Slack webhook URL.
	SlackWebhookURL string `json:"slack_webhook_url"`

	// SmsNumbers is the receipients of the alert notifications.
	SmsNumbers []string `json:"sms_numbers"`

	// Type is the type of notification. This field is required. Must be one of: "slack", "pagerduty", "email", "sms", "webhook".
	Type string `json:"type"`

	// UpdatedAt is a timestamp indicating when the notification was last updated. This field is read-only.
	UpdatedAt time.Time `json:"updated_at"`

	// WebhookURL is the webhook URL which receives the alert payloads.
	WebhookURL string `json:"webhook_url"`
}

// Project represents an isolated set of log events and alerts. A project can be created for each application, environment, or team within an organization depending on your preferences.
type Project struct {
	// CreatedAt is a timestamp indicating when the project was created. This field is read-only.
	CreatedAt time.Time `json:"created_at"`

	// Description is the project description.
	Description string `json:"description"`

	// ID is the project id. This field is read-only.
	ID string `json:"id"`

	// Location is the geographical location where the log events are stored. This field is required. Must be one of: "us-west2", "northamerica-northeast1", "us-east4", "southamerica-east1", "europe-north1", "europe-west2", "europe-west6", "asia-east2", "asia-south1", "asia-northeast2", "asia-east1", "asia-northeast1", "asia-southeast1", "australia-southeast1".
	Location string `json:"location"`

	// Mode is the storage mode, optimized for plain-text or structured logs. Both options support plain-text and structured logging, however, the structured mode shards on the `message` value, restricting its length to 1024 bytes. This field is required. Must be one of: "plain_text", "structured".
	Mode string `json:"mode"`

	// Name is the human-friendly project name. This field is required.
	Name string `json:"name"`

	// Retention is the retention of log events in days. When zero the logs do not expire.
	Retention int `json:"retention"`

	// UpdatedAt is a timestamp indicating when the project was last updated. This field is read-only.
	UpdatedAt time.Time `json:"updated_at"`
}

// QueryStats represents query statistics.
type QueryStats struct {
	// CacheHit is a boolean indicating if the query was cached.
	CacheHit bool `json:"cache_hit"`

	// Duration is the query duration in milliseconds.
	Duration int `json:"duration"`

	// TotalBytesBilled is the total number of bytes billed by the query.
	TotalBytesBilled int `json:"total_bytes_billed"`

	// TotalBytesProcessed is the total number of bytes processed by the query.
	TotalBytesProcessed int `json:"total_bytes_processed"`
}

// Search represents a saved search query.
type Search struct {
	// CreatedAt is a timestamp indicating when the saved search was created. This field is read-only.
	CreatedAt time.Time `json:"created_at"`

	// ID is the saved search id. This field is read-only.
	ID string `json:"id"`

	// Name is the name of the saved search. This field is required.
	Name string `json:"name"`

	// ProjectID is the associated project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the saved search query. This field is required.
	Query string `json:"query"`

	// UpdatedAt is a timestamp indicating when the saved search was last updated. This field is read-only.
	UpdatedAt time.Time `json:"updated_at"`
}

// StringFieldStat represents a string field's stats.
type StringFieldStat struct {
	// Count is the number of times this field occurred in the sampled events.
	Count int `json:"count"`

	// Percent is the percentage of occurrences in the sampled events.
	Percent float64 `json:"percent"`

	// Value is the string value.
	Value string `json:"value"`
}

// TimeseriesPoint represents a single point in a timeseries query.
type TimeseriesPoint struct {
	// Count is the number of events for this bucket.
	Count int `json:"count"`

	// Timestamp is the bucket timestamp.
	Timestamp time.Time `json:"timestamp"`
}

// Token represents an API token.
type Token struct {
	// CreatedAt is a timestamp indicating when the token was created. This field is read-only.
	CreatedAt time.Time `json:"created_at"`

	// Description is the description of the token.
	Description string `json:"description"`

	// ID is the token. This field is read-only.
	ID string `json:"id"`

	// LastUsedAt is a timestamp indicating when the token was last used. This field is read-only.
	LastUsedAt time.Time `json:"last_used_at"`

	// Scopes is available to this token, permitting access to read and write data. This field is required. Must be one of: "events:read", "events:write", "alerts:read", "alerts:write", "notifications:read", "notifications:write", "projects:read", "projects:write", "tokens:read", "tokens:write", "searches:read", "searches:write".
	Scopes []string `json:"scopes"`
}

// AddAlertInput params.
type AddAlertInput struct {
	// Alert is the alert. This field is required.
	Alert Alert `json:"alert"`
}

// AddAlertOutput params.
type AddAlertOutput struct {
	// ID is the alert id. This field is required.
	ID string `json:"id"`
}

// AddEventsInput params.
type AddEventsInput struct {
	// Events is the batch of events. This field is required.
	Events []Event `json:"events"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// AddNotificationInput params.
type AddNotificationInput struct {
	// Notification is the notification. This field is required.
	Notification Notification `json:"notification"`
}

// AddNotificationOutput params.
type AddNotificationOutput struct {
	// ID is the notification id. This field is required.
	ID string `json:"id"`
}

// AddProjectInput params.
type AddProjectInput struct {
	// Project is the project. This field is required.
	Project Project `json:"project"`
}

// AddProjectOutput params.
type AddProjectOutput struct {
	// ID is the project id. This field is required.
	ID string `json:"id"`
}

// AddSearchInput params.
type AddSearchInput struct {
	// Search is the saved search. This field is required.
	Search Search `json:"search"`
}

// AddSearchOutput params.
type AddSearchOutput struct {
	// ID is the saved search id. This field is required.
	ID string `json:"id"`
}

// AddTokenInput params.
type AddTokenInput struct {
	// Token is the token. This field is required.
	Token Token `json:"token"`
}

// AddTokenOutput params.
type AddTokenOutput struct {
	// ID is the token id.
	ID string `json:"id"`
}

// GetAlertInput params.
type GetAlertInput struct {
	// AlertID is the alert id. This field is required.
	AlertID string `json:"alert_id"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// GetAlertOutput params.
type GetAlertOutput struct {
	// Alert is the alert. This field is required.
	Alert Alert `json:"alert"`
}

// GetAlertsInput params.
type GetAlertsInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// GetAlertsOutput params.
type GetAlertsOutput struct {
	// Alerts is the alerts. This field is required.
	Alerts []Alert `json:"alerts"`
}

// GetBooleanFieldStatsInput params.
type GetBooleanFieldStatsInput struct {
	// Field is the field name. This field is required.
	Field string `json:"field"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// GetBooleanFieldStatsOutput params.
type GetBooleanFieldStatsOutput struct {
	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`

	// Values is the boolean values. This field is required.
	Values []BooleanFieldStat `json:"values"`
}

// GetCountInput params.
type GetCountInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// GetCountOutput params.
type GetCountOutput struct {
	// Count is the query result count. This field is required.
	Count int `json:"count"`

	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`
}

// GetDiscoveredFieldsInput params.
type GetDiscoveredFieldsInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// GetDiscoveredFieldsOutput params.
type GetDiscoveredFieldsOutput struct {
	// Fields is the fields discovered. This field is required.
	Fields []DiscoveredField `json:"fields"`

	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`
}

// GetInstanceConfigOutput params.
type GetInstanceConfigOutput struct {
	// Config is the instance configuration.
	Config InstanceConfig `json:"config"`
}

// GetNotificationInput params.
type GetNotificationInput struct {
	// NotificationID is the notification id. This field is required.
	NotificationID string `json:"notification_id"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// GetNotificationOutput params.
type GetNotificationOutput struct {
	// Notification is the notification. This field is required.
	Notification Notification `json:"notification"`
}

// GetNotificationsInput params.
type GetNotificationsInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// GetNotificationsOutput params.
type GetNotificationsOutput struct {
	// Notifications is the notifications. This field is required.
	Notifications []Notification `json:"notifications"`
}

// GetNumericFieldStatsInput params.
type GetNumericFieldStatsInput struct {
	// Field is the field name. This field is required.
	Field string `json:"field"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// GetNumericFieldStatsOutput params.
type GetNumericFieldStatsOutput struct {
	// Avg is the avg value. This field is required.
	Avg float64 `json:"avg"`

	// Max is The max value. This field is required.
	Max float64 `json:"max"`

	// Min is the min value. This field is required.
	Min float64 `json:"min"`

	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`
}

// GetProjectStatsInput params.
type GetProjectStatsInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// GetProjectStatsOutput params.
type GetProjectStatsOutput struct {
	// BytesTotal is the total number of bytes stored. This field is required.
	BytesTotal int `json:"bytes_total"`

	// EventsTotal is the total number of events stored. This field is required.
	EventsTotal int `json:"events_total"`
}

// GetProjectsOutput params.
type GetProjectsOutput struct {
	// Projects is the projects. This field is required.
	Projects []Project `json:"projects"`
}

// GetSearchesInput params.
type GetSearchesInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// GetSearchesOutput params.
type GetSearchesOutput struct {
	// Searches is the saved searches.
	Searches []Search `json:"searches"`
}

// GetStringFieldStatsInput params.
type GetStringFieldStatsInput struct {
	// Field is the field name. This field is required.
	Field string `json:"field"`

	// Limit is the maximum number of values to return.
	Limit int `json:"limit"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// GetStringFieldStatsOutput params.
type GetStringFieldStatsOutput struct {
	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`

	// Values is the string values. This field is required.
	Values []StringFieldStat `json:"values"`
}

// GetTimeseriesInput params.
type GetTimeseriesInput struct {
	// MaxPoints is the maxmimum number of datapoints to return. This field is required.
	MaxPoints int `json:"max_points"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// GetTimeseriesOutput params.
type GetTimeseriesOutput struct {
	// Points is the series. This field is required.
	Points []TimeseriesPoint `json:"points"`

	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`
}

// GetTokensOutput params.
type GetTokensOutput struct {
	// Tokens is the tokens.
	Tokens []Token `json:"tokens"`
}

// QueryInput params.
type QueryInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the SQL query string. This field is required.
	Query string `json:"query"`
}

// QueryOutput params.
type QueryOutput struct {
	// Results is the query results. This field is required.
	Results []map[string]interface{} `json:"results"`

	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`
}

// RemoveAlertInput params.
type RemoveAlertInput struct {
	// AlertID is the alert id. This field is required.
	AlertID string `json:"alert_id"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// RemoveNotificationInput params.
type RemoveNotificationInput struct {
	// NotificationID is the notification id. This field is required.
	NotificationID string `json:"notification_id"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// RemoveProjectInput params.
type RemoveProjectInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`
}

// RemoveSearchInput params.
type RemoveSearchInput struct {
	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// SearchID is the saved search id. This field is required.
	SearchID string `json:"search_id"`
}

// RemoveTokenInput params.
type RemoveTokenInput struct {
	// TokenID is the token id. This field is required.
	TokenID string `json:"token_id"`
}

// SearchInput params.
type SearchInput struct {
	// Limit is the maxmimum number of events to return.
	Limit int `json:"limit"`

	// Order is the query timestamp sort order. Must be one of: "ascending", "descending".
	Order string `json:"order"`

	// ProjectID is the project id. This field is required.
	ProjectID string `json:"project_id"`

	// Query is the search query string.
	Query string `json:"query"`

	// Start is the start timestamp, events before this time are not included. This field is required.
	Start time.Time `json:"start"`

	// Stop is the stop timestamp, events after this time are not included. This field is required.
	Stop time.Time `json:"stop"`
}

// SearchOutput params.
type SearchOutput struct {
	// Events is the query search results. This field is required.
	Events []Event `json:"events"`

	// Stats is the query statistics. This field is required.
	Stats QueryStats `json:"stats"`
}

// TestAlertInput params.
type TestAlertInput struct {
	// Alert is the alert. This field is required.
	Alert Alert `json:"alert"`
}

// UpdateAlertInput params.
type UpdateAlertInput struct {
	// Alert is the alert. This field is required.
	Alert Alert `json:"alert"`
}

// UpdateNotificationInput params.
type UpdateNotificationInput struct {
	// Notification is the notification. This field is required.
	Notification Notification `json:"notification"`
}

// UpdateProjectInput params.
type UpdateProjectInput struct {
	// Project is the project. This field is required.
	Project Project `json:"project"`
}

// UpdateSearchInput params.
type UpdateSearchInput struct {
	// Search is the saved search. This field is required.
	Search Search `json:"search"`
}

// Client is the API client.
type Client struct {
	// URL is the required API endpoint address.
	URL string

	// AuthToken is an optional authentication token.
	AuthToken string

	// HTTPClient is the client used for making requests, defaulting to http.DefaultClient.
	HTTPClient *http.Client
}

// AddAlert creates a new alert.
func (c *Client) AddAlert(in AddAlertInput) (*AddAlertOutput, error) {
	var out AddAlertOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "add_alert", in, &out)
}

// AddEvents ingests a batch of events.
func (c *Client) AddEvents(in AddEventsInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "add_events", in, nil)
}

// AddNotification creates a new notification.
func (c *Client) AddNotification(in AddNotificationInput) (*AddNotificationOutput, error) {
	var out AddNotificationOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "add_notification", in, &out)
}

// AddProject creates a new project.
func (c *Client) AddProject(in AddProjectInput) (*AddProjectOutput, error) {
	var out AddProjectOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "add_project", in, &out)
}

// AddSearch creates a new saved search.
func (c *Client) AddSearch(in AddSearchInput) (*AddSearchOutput, error) {
	var out AddSearchOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "add_search", in, &out)
}

// AddToken creates a new token.
func (c *Client) AddToken(in AddTokenInput) (*AddTokenOutput, error) {
	var out AddTokenOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "add_token", in, &out)
}

// GetAlert returns an alert.
func (c *Client) GetAlert(in GetAlertInput) (*GetAlertOutput, error) {
	var out GetAlertOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_alert", in, &out)
}

// GetAlerts returns all alerts in a project.
func (c *Client) GetAlerts(in GetAlertsInput) (*GetAlertsOutput, error) {
	var out GetAlertsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_alerts", in, &out)
}

// GetBooleanFieldStats returns field statistics for a boolean field.
func (c *Client) GetBooleanFieldStats(in GetBooleanFieldStatsInput) (*GetBooleanFieldStatsOutput, error) {
	var out GetBooleanFieldStatsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_boolean_field_stats", in, &out)
}

// GetCount performs a search query against the log events, returning the number of matches.
func (c *Client) GetCount(in GetCountInput) (*GetCountOutput, error) {
	var out GetCountOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_count", in, &out)
}

// GetDiscoveredFields returns fields discovered in the provided time range.
func (c *Client) GetDiscoveredFields(in GetDiscoveredFieldsInput) (*GetDiscoveredFieldsOutput, error) {
	var out GetDiscoveredFieldsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_discovered_fields", in, &out)
}

// GetInstanceConfig returns instance configuration.
func (c *Client) GetInstanceConfig() (*GetInstanceConfigOutput, error) {
	var out GetInstanceConfigOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_instance_config", nil, &out)
}

// GetNotification returns a notification.
func (c *Client) GetNotification(in GetNotificationInput) (*GetNotificationOutput, error) {
	var out GetNotificationOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_notification", in, &out)
}

// GetNotifications returns all notifications.
func (c *Client) GetNotifications(in GetNotificationsInput) (*GetNotificationsOutput, error) {
	var out GetNotificationsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_notifications", in, &out)
}

// GetNumericFieldStats returns field statistics for a numeric field.
func (c *Client) GetNumericFieldStats(in GetNumericFieldStatsInput) (*GetNumericFieldStatsOutput, error) {
	var out GetNumericFieldStatsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_numeric_field_stats", in, &out)
}

// GetProjectStats returns project statistics.
func (c *Client) GetProjectStats(in GetProjectStatsInput) (*GetProjectStatsOutput, error) {
	var out GetProjectStatsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_project_stats", in, &out)
}

// GetProjects returns all projects.
func (c *Client) GetProjects() (*GetProjectsOutput, error) {
	var out GetProjectsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_projects", nil, &out)
}

// GetSearches returns all saved searches in a project.
func (c *Client) GetSearches(in GetSearchesInput) (*GetSearchesOutput, error) {
	var out GetSearchesOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_searches", in, &out)
}

// GetStringFieldStats returns field statistics for a string field.
func (c *Client) GetStringFieldStats(in GetStringFieldStatsInput) (*GetStringFieldStatsOutput, error) {
	var out GetStringFieldStatsOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_string_field_stats", in, &out)
}

// GetTimeseries returns a timeseries of event counts in the provided time range.
func (c *Client) GetTimeseries(in GetTimeseriesInput) (*GetTimeseriesOutput, error) {
	var out GetTimeseriesOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_timeseries", in, &out)
}

// GetTokens returns all tokens.
func (c *Client) GetTokens() (*GetTokensOutput, error) {
	var out GetTokensOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "get_tokens", nil, &out)
}

// Query performs a SQL query against the log events.
func (c *Client) Query(in QueryInput) (*QueryOutput, error) {
	var out QueryOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "query", in, &out)
}

// RemoveAlert removes an alert.
func (c *Client) RemoveAlert(in RemoveAlertInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "remove_alert", in, nil)
}

// RemoveNotification removes a notification.
func (c *Client) RemoveNotification(in RemoveNotificationInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "remove_notification", in, nil)
}

// RemoveProject removes a project.
func (c *Client) RemoveProject(in RemoveProjectInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "remove_project", in, nil)
}

// RemoveSearch removes a saved search.
func (c *Client) RemoveSearch(in RemoveSearchInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "remove_search", in, nil)
}

// RemoveToken removes a token.
func (c *Client) RemoveToken(in RemoveTokenInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "remove_token", in, nil)
}

// Search performs a search query against the log events.
func (c *Client) Search(in SearchInput) (*SearchOutput, error) {
	var out SearchOutput
	return &out, call(c.HTTPClient, c.AuthToken, c.URL, "search", in, &out)
}

// TestAlert test the alert configuration.
func (c *Client) TestAlert(in TestAlertInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "test_alert", in, nil)
}

// UpdateAlert updates an alert.
func (c *Client) UpdateAlert(in UpdateAlertInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "update_alert", in, nil)
}

// UpdateNotification updates a notification.
func (c *Client) UpdateNotification(in UpdateNotificationInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "update_notification", in, nil)
}

// UpdateProject updates a project.
func (c *Client) UpdateProject(in UpdateProjectInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "update_project", in, nil)
}

// UpdateSearch updates a saved search.
func (c *Client) UpdateSearch(in UpdateSearchInput) error {
	return call(c.HTTPClient, c.AuthToken, c.URL, "update_search", in, nil)
}

// ErrInvalidScheme is returned when HTTP is used instead of HTTPS.
var ErrInvalidScheme = errors.New("Client.URL must be HTTPS, not HTTP")

// Error is an error returned by the client.
type Error struct {
	Status     string
	StatusCode int
	Type       string
	Message    string
}

// Error implementation.
func (e Error) Error() string {
	if e.Type == "" {
		return fmt.Sprintf("%s: %d", e.Status, e.StatusCode)
	}
	return fmt.Sprintf("%s: %s", e.Type, e.Message)
}

// call implementation.
func call(client *http.Client, authToken, endpoint, method string, in, out interface{}) error {
	var body io.Reader

	// parse the URL
	u, err := url.Parse(endpoint)
	if err != nil {
		return fmt.Errorf("parsing url: %w", err)
	}

	// ensure HTTPS
	if u.Scheme == "http" {
		return ErrInvalidScheme
	}

	// default client
	if client == nil {
		client = http.DefaultClient
	}

	// input params
	if in != nil {
		var buf bytes.Buffer
		err := json.NewEncoder(&buf).Encode(in)
		if err != nil {
			return fmt.Errorf("encoding: %w", err)
		}
		body = &buf
	}

	// POST request
	req, err := http.NewRequest("POST", endpoint+"/"+method, body)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")

	// auth token
	if authToken != "" {
		req.Header.Set("Authorization", "Bearer "+authToken)
	}

	// response
	res, err := client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()

	// error
	if res.StatusCode >= 300 {
		var e Error
		if res.Header.Get("Content-Type") == "application/json" {
			if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
				return err
			}
		}
		e.Status = http.StatusText(res.StatusCode)
		e.StatusCode = res.StatusCode
		return e
	}

	// output params
	if out != nil {
		err = json.NewDecoder(res.Body).Decode(out)
		if err != nil {
			return err
		}
	}

	return nil
}
