/*
Copyright 2020 The Argoproj Authors.

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.
*/
package events

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/minio/minio-go/v7/pkg/notification"
	stripe "github.com/stripe/stripe-go"

	sqslib "github.com/aws/aws-sdk-go/service/sqs"
)

// AMQPEventData represents the event data generated by AMQP eventsource.
type AMQPEventData struct {
	// ContentType is the MIME content type
	ContentType string `json:"contentType"`
	// ContentEncoding is the MIME content encoding
	ContentEncoding string `json:"contentEncoding"`
	// Delivery mode can be either - non-persistent (1) or persistent (2)
	DeliveryMode int `json:"deliveryMode"`
	// Priority refers to the use - 0 to 9
	Priority int `json:"priority"`
	// CorrelationId is the correlation identifier
	CorrelationId string `json:"correlationId"`
	// ReplyTo is the address to reply to (ex: RPC)
	ReplyTo string `json:"replyTo"`
	// Expiration refers to message expiration spec
	Expiration string `json:"expiration"`
	// MessageId is message identifier
	MessageId string `json:"messageId"`
	// Timestamp refers to the message timestamp
	Timestamp string `json:"timestamp"`
	// Type refers to the message type name
	Type string `json:"type"`
	// AppId refers to the application id
	AppId string `json:"appId"`
	// Exchange is basic.publish exchange
	Exchange string `json:"exchange"`
	// RoutingKey is basic.publish routing key
	RoutingKey string `json:"routingKey"`
	// Body represents the messsage body
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// SNSEventData represents the event data generated by SNS eventsource.
// +k8s:openapi-gen=true
type SNSEventData struct {
	// Header is the http request header
	Header http.Header `json:"header"`
	// Body is http request body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// SQSEventData represents the event data generated by SQS eventsource.
// +k8s:openapi-gen=true
type SQSEventData struct {
	// A unique identifier for the message. A MessageId is considered unique across
	// all AWS accounts for an extended period of time.
	MessageId string `json:"messageId"`
	// Each message attribute consists of a Name, Type, and Value. For more information,
	// see Amazon SQS Message Attributes
	// (https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-attributes.html)
	// in the Amazon Simple Queue Service Developer Guide.
	MessageAttributes map[string]*sqslib.MessageAttributeValue `json:"messageAttributes"`
	// The message's contents (not URL-encoded).
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// AzureEventsHubEventData represents to the event data generated by Azure Events Hub eventsource.
// +k8s:openapi-gen=true
type AzureEventsHubEventData struct {
	// Id of the message
	Id string `json:"id"`
	// PartitionKey
	PartitionKey string `json:"partitionKey"`
	// Message body
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// AzureQueueStorageEventData represents the event data generated by AQS eventsource.
// +k8s:openapi-gen=true
type AzureQueueStorageEventData struct {
	// Body is the message body
	Body interface{} `json:"body"`
	// MessageID is the ID of the message
	MessageID string `json:"messageID"`
	// InsertionTime is the time the Message was inserted into the Queue.
	InsertionTime time.Time `json:"insertionTime"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

type AzureServiceBusEventData struct {
	// ApplicationProperties can be used to store custom metadata for a message
	ApplicationProperties map[string]interface{} `json:"applicationProperties"`
	// Message body
	Body interface{} `json:"body"`
	// ContentType is the MIME content type
	ContentType *string `json:"contentType"`
	// CorrelationID is the correlation identifier
	CorrelationID *string `json:"correlationID"`
	// EnqueuedTime is the time when the message was enqueued
	EnqueuedTime *time.Time `json:"enqueuedTime"`
	// ID of the message
	MessageID string `json:"messageID"`
	// ReplyTo is an application-defined value specify a reply path to the receiver of the message
	ReplyTo *string `json:"replyTo"`
	// SequenceNumber is a unique number assigned to a message by Service Bus
	SequenceNumber *int64 `json:"sequenceNumber"`
	// Subject enables an application to indicate the purpose of the message, similar to an email subject line
	Subject *string `json:"subject"`
	// Metadata holds the user defined metadata which will passed along the event payload
	Metadata map[string]string `json:"metadata,omitempty"`
}

// BitbucketEventData represents the event data generated by the Bitbucket Server eventsource.
type BitbucketEventData struct {
	// Headers from the Bitbucket Server http request.
	Headers http.Header `json:"headers"`
	// Body represents the message body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// BitbucketServerEventData represents the event data generated by the Bitbucket Server eventsource.
type BitbucketServerEventData struct {
	// Headers from the Bitbucket Server http request.
	Headers http.Header `json:"headers"`
	// Body represents the message body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// CalendarEventData represents the event data generated by the Calendar eventsource.
// +k8s:openapi-gen=true
type CalendarEventData struct {
	// EventTime is time at which event occurred
	EventTime string `json:"eventTime"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// EmitterEventData represents the event data generated by the Emitter eventsource.
type EmitterEventData struct {
	// Topic name
	Topic string `json:"topic"`
	// Body represents the message body
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// PubSubEventData represents the event data generated by the GCP PubSub eventsource.
type PubSubEventData struct {
	// ID of the message
	ID string `json:"id"`
	// Body is the actual data in the message.
	Body interface{} `json:"body"`
	// Attributes represents the key-value pairs the current message
	// is labelled with.
	Attributes map[string]string `json:"attributes"`
	// The time at which the message was published.
	PublishTime string `json:"publishTime"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// GerritEventData represents the event data generated by the Gerrit eventsource.
type GerritEventData struct {
	// Headers from the Gerrit http request.
	Headers http.Header `json:"headers"`
	// Body represents the message body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// GithubEventData represents the event data generated by the GitHub eventsource.
type GithubEventData struct {
	// Headers from the GitHub http request.
	Headers http.Header `json:"headers"`
	// Body represents the message body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// GitLabEventData represents the event data generated by the GitLab eventsource.
type GitLabEventData struct {
	// Headers from the Gitlab http request.
	Headers http.Header `json:"headers"`
	// Body represents the message body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// KafkaEventData represents the event data generated by the Kafka eventsource.
type KafkaEventData struct {
	// Topic refers to the Kafka topic
	Topic string `json:"topic"`
	// Key refers to the Kafka key
	Key string `json:"key"`
	// Partition refers to the Kafka partition
	Partition int `json:"partition"`
	// Body refers to the message value
	Body interface{} `json:"body"`
	// Timestamp of the message
	Timestamp string `json:"timestamp"`
	// Headers refers to the message headers
	Headers map[string]string `json:"headers"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// MinioEventData represents the event data generated by the Minio eventsource.
type MinioEventData struct {
	Notification []notification.Event `json:"notification"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// MQTTEventData represents the event data generated by the MQTT eventsource.
type MQTTEventData struct {
	// Topic refers to the MQTT topic name.
	Topic string `json:"topic"`
	// MessageID is the unique ID for the message
	MessageID int `json:"messageId"`
	// Body is the message payload.
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// NATSEventData represents the event data generated by the NATS eventsource.
type NATSEventData struct {
	// Name of the subject.
	Subject string `json:"subject"`
	// Message data.
	Body interface{} `json:"body"`
	// Header represents the optional Header for a NATS message, based on the implementation of http.Header.
	Header map[string][]string `json:"header,omitempty"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// NSQEventData represents the event data generated by the NSQ eventsource.
type NSQEventData struct {
	// Body is the message data.
	Body interface{} `json:"body"`
	// Timestamp of the message.
	Timestamp string `json:"timestamp"`
	// NSQDAddress is the address of the nsq host.
	NSQDAddress string `json:"nsqdAddress"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// RedisEventData represents the event data generated by the Redis eventsource.
type RedisEventData struct {
	// Subscription channel.
	Channel string `json:"channel"`
	// Message pattern
	Pattern string `json:"pattern"`
	// Message body
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// RedisStreamEventData represents the event data generated by the Redis eventsource.
type RedisStreamEventData struct {
	// Source redis stream name.
	Stream string `json:"stream"`
	// Message Id
	Id string `json:"message_id"`
	// Message body
	Values map[string]interface{} `json:"values"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// ResourceEventData represents the event data generated by the Resource eventsource.
type ResourceEventData struct {
	// EventType of the type of the event.
	EventType string `json:"type"`
	// Resource body.
	Body *json.RawMessage `json:"body"`
	// Prior state of the resource body (if it exists)
	OldBody *json.RawMessage `json:"oldBody"`
	// Resource group name.
	Group string `json:"group"`
	// Resource version.
	Version string `json:"version"`
	// Resource name.
	Resource string `json:"resource"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// WebhookEventData represents the event data generated by the Webhook eventsource.
type WebhookEventData struct {
	// Header is the http request header
	Header http.Header `json:"header"`
	// Body is http request body
	Body *json.RawMessage `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// PulsarEventData represents the event data generated by the Pulsar eventsource.
type PulsarEventData struct {
	// Key of the message
	Key string `json:"key"`
	// Publish time of the message in UTC
	PublishTime string `json:"publishTime"`
	// Body refers to the message payload
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// StorageGridEventData represents the event data generated by the StorageGrid eventsource.
type StorageGridEventData struct {
	Notification *StorageGridNotification `json:"notification"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// StorageGridNotification is the bucket notification received from storage grid
type StorageGridNotification struct {
	Action  string `json:"Action"`
	Message struct {
		Records []struct {
			EventVersion string    `json:"eventVersion"`
			EventSource  string    `json:"storageGridEventSource"`
			EventTime    time.Time `json:"eventTime"`
			EventName    string    `json:"eventName"`
			UserIdentity struct {
				PrincipalID string `json:"principalId"`
			} `json:"userIdentity"`
			RequestParameters struct {
				SourceIPAddress string `json:"sourceIPAddress"`
			} `json:"requestParameters"`
			ResponseElements struct {
				XAmzRequestID string `json:"x-amz-request-id"`
			} `json:"responseElements"`
			S3 struct {
				S3SchemaVersion string `json:"s3SchemaVersion"`
				ConfigurationID string `json:"configurationId"`
				Bucket          struct {
					Name          string `json:"name"`
					OwnerIdentity struct {
						PrincipalID string `json:"principalId"`
					} `json:"ownerIdentity"`
					Arn string `json:"arn"`
				} `json:"bucket"`
				Object struct {
					Key       string `json:"key"`
					Size      int    `json:"size"`
					ETag      string `json:"eTag"`
					Sequencer string `json:"sequencer"`
				} `json:"object"`
			} `json:"s3"`
		} `json:"Records"`
	} `json:"Message"`
	TopicArn string `json:"TopicArn"`
	Version  string `json:"Version"`
}

// StripeEventData represents the event data generated by the Stripe eventsource.
type StripeEventData struct {
	Event *stripe.Event `json:"event"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// GenericEventData represents the event data generated by the generic eventsource.
type GenericEventData struct {
	// Body refers to the message payload
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}

// MNSEventData represents the event data generated by AlibabaCloud MNS eventsource.
type MNSEventData struct {
	// A unique identifier for the message. A MessageId is considered unique across
	// all AlibabaCloud accounts for an extended period of time.
	MessageId string `json:"messageId"`
	// Each message attribute consists of a Name, Type, and Value. For more information,
	// see AlibabaCloud MNS Message Attributes
	// (https://help.aliyun.com/zh/mns/developer-reference/basic-concepts-queue?spm=a2c4g.11186623.0.0.49955b99DhT3lH)
	Body interface{} `json:"body"`
	// Metadata holds the user defined metadata which will passed along the event payload.
	Metadata map[string]string `json:"metadata,omitempty"`
}
