package chronograf

import "encoding/json"

// AlertNodes defines all possible kapacitor interactions with an alert.
type AlertNodes struct {
	IsStateChangesOnly bool          `json:"stateChangesOnly"` // IsStateChangesOnly will only send alerts on state changes.
	UseFlapping        bool          `json:"useFlapping"`      // UseFlapping enables flapping detection. Flapping occurs when a service or host changes state too frequently, resulting in a storm of problem and recovery notification
	Posts              []*Post       `json:"post"`             // HTTPPost  will post the JSON alert data to the specified URLs.
	TCPs               []*TCP        `json:"tcp"`              // TCP  will send the JSON alert data to the specified endpoint via TCP.
	Email              []*Email      `json:"email"`            // Email  will send alert data to the specified emails.
	Exec               []*Exec       `json:"exec"`             // Exec  will run shell commandss when an alert triggers
	Log                []*Log        `json:"log"`              // Log  will log JSON alert data to files in JSON lines format.
	VictorOps          []*VictorOps  `json:"victorOps"`        // VictorOps  will send alert to all VictorOps
	PagerDuty          []*PagerDuty  `json:"pagerDuty"`        // PagerDuty  will send alert to all PagerDuty
	PagerDuty2         []*PagerDuty  `json:"pagerDuty2"`       // PagerDuty2  will send alert to  PagerDuty v2
	Pushover           []*Pushover   `json:"pushover"`         // Pushover  will send alert to all Pushover
	Sensu              []*Sensu      `json:"sensu"`            // Sensu  will send alert to all Sensu
	Slack              []*Slack      `json:"slack"`            // Slack  will send alert to Slack
	Telegram           []*Telegram   `json:"telegram"`         // Telegram  will send alert to all Telegram
	Alerta             []*Alerta     `json:"alerta"`           // Alerta  will send alert to all Alerta
	OpsGenie           []*OpsGenie   `json:"opsGenie"`         // OpsGenie  will send alert to all OpsGenie
	OpsGenie2          []*OpsGenie   `json:"opsGenie2"`        // OpsGenie2  will send alert to all OpsGenie v2
	Talk               []*Talk       `json:"talk"`             // Talk will send alert to all Talk
	Kafka              []*Kafka      `json:"kafka"`            // Kafka will send alert to all Kafka
	ServiceNow         []*ServiceNow `json:"serviceNow"`       // ServiceNow alert options
	BigPanda           []*BigPanda   `json:"bigPanda"`         // BigPanda alert options
	Teams              []*Teams      `json:"teams"`            // Teams alert options
	Zenoss             []*Zenoss     `json:"zenoss"`           // Zenoss alert options
}

// Post will POST alerts to a destination URL
type Post struct {
	URL     string            `json:"url"`     // URL is the destination of the POST.
	Headers map[string]string `json:"headers"` // Headers are added to the output POST
}

// Log sends the output of the alert to a file
type Log struct {
	FilePath string `json:"filePath"` // Absolute path the the log file; it will be created if it does not exist.
}

// Alerta sends the output of the alert to an alerta service
type Alerta struct {
	Token       string   `json:"token"`       // Token is the authentication token that overrides the global configuration.
	Resource    string   `json:"resource"`    // Resource under alarm, deliberately not host-centric
	Event       string   `json:"event"`       // Event is the event name eg. NodeDown, QUEUE:LENGTH:EXCEEDED
	Environment string   `json:"environment"` // Environment is the effected environment; used to namespace the resource
	Group       string   `json:"group"`       // Group is an event group used to group events of similar type
	Value       string   `json:"value"`       // Value is the event value eg. 100%, Down, PingFail, 55ms, ORA-1664
	Origin      string   `json:"origin"`      // Origin is the name of monitoring component that generated the alert
	Service     []string `json:"service"`     // Service is the list of affected services
}

// Exec executes a shell command on an alert
type Exec struct {
	Command []string `json:"command"` // Command is the space separated command and args to execute.
}

// TCP sends the alert to the address
type TCP struct {
	Address string `json:"address"` // Endpoint is the Address and port to send the alert
}

// Email sends the alert to a list of email addresses
type Email struct {
	To []string `json:"to"` // ToList is the list of email recipients.
}

// VictorOps sends alerts to the victorops.com service
type VictorOps struct {
	RoutingKey string `json:"routingKey"` // RoutingKey is what is used to map the alert to a team
}

// PagerDuty sends alerts to the pagerduty.com service
type PagerDuty struct {
	ServiceKey string `json:"serviceKey"` // ServiceKey is the GUID of one of the "Generic API" integrations
}

// Sensu sends alerts to sensu or sensuapp.org
type Sensu struct {
	Source   string   `json:"source"`   // Source is the check source, used to create a proxy client for an external resource
	Handlers []string `json:"handlers"` // Handlers are Sensu event handlers are for taking action on events
}

// Pushover sends alerts to pushover.net
type Pushover struct {
	// UserKey is the User/Group key of your user (or you), viewable when logged
	// into the Pushover dashboard. Often referred to as USER_KEY
	// in the Pushover documentation.
	UserKey string `json:"userKey"`

	// Device is the users device name to send message directly to that device,
	// rather than all of a user's devices (multiple device names may
	// be separated by a comma)
	Device string `json:"device"`

	// Title is your message's title, otherwise your apps name is used
	Title string `json:"title"`

	// URL is a supplementary URL to show with your message
	URL string `json:"url"`

	// URLTitle is a title for your supplementary URL, otherwise just URL is shown
	URLTitle string `json:"urlTitle"`

	// Sound is the name of one of the sounds supported by the device clients to override
	// the user's default sound choice
	Sound string `json:"sound"`
}

// Slack sends alerts to a slack.com channel
type Slack struct {
	Channel   string `json:"channel"`   // Slack channel in which to post messages.
	Username  string `json:"username"`  // Username of the Slack bot.
	IconEmoji string `json:"iconEmoji"` // IconEmoji is an emoji name surrounded in ':' characters; The emoji image will replace the normal user icon for the slack bot.
	Workspace string `json:"workspace"` // Workspace is the slack workspace for the alert handler
}

// Telegram sends alerts to telegram.org
type Telegram struct {
	ChatID                string `json:"chatId"`                // ChatID is the Telegram user/group ID to post messages to.
	ParseMode             string `json:"parseMode"`             // ParseMode tells telegram how to render the message (Markdown or HTML)
	DisableWebPagePreview bool   `json:"disableWebPagePreview"` // IsDisableWebPagePreview will disables link previews in alert messages.
	DisableNotification   bool   `json:"disableNotification"`   // IsDisableNotification will disables notifications on iOS devices and disables sounds on Android devices. Android users continue to receive notifications.
}

// OpsGenie sends alerts to opsgenie.com
type OpsGenie struct {
	Teams      []string `json:"teams"`      // Teams that the alert will be routed to send notifications
	Recipients []string `json:"recipients"` // Recipients can be a single user, group, escalation, or schedule (https://docs.opsgenie.com/docs/alert-recipients-and-teams)
}

// Talk sends alerts to Jane Talk (https://jianliao.com/site)
type Talk struct{}

// Kafka sends alerts to any Kafka brokers specified in the handler config
type Kafka struct {
	Cluster  string `json:"cluster"`
	Topic    string `json:"kafka-topic"`
	Template string `json:"template"`
}

// ServiceNow properties
type ServiceNow struct {
	Source     string `json:"source"`
	Node       string `json:"node"`
	Type       string `json:"type"`
	Resource   string `json:"resource"`
	MetricName string `json:"metric_name"`
	MessageKey string `json:"message_key"`
}

// BigPanda properties
type BigPanda struct {
	AppKey            string `json:"app-key"`
	PrimaryProperty   string `json:"primary-property"`
	SecondaryProperty string `json:"secondary-property"`
}

// Teams properties
type Teams struct {
	ChannelURL string `json:"channel-url"` // override configuration
}

// Teams properties
type Zenoss struct {
	Action string `json:"action"`
	Method string `json:"method"`
	Type   string `json:"type"`
	TID    int64  `json:"tid"`

	Device        string `json:"device"`
	Component     string `json:"component"`
	EventClassKey string `json:"evclasskey"`
	EventClass    string `json:"evclass"`
}

// MarshalJSON converts AlertNodes to JSON
func (n *AlertNodes) MarshalJSON() ([]byte, error) {
	type Alias AlertNodes
	var raw = &struct {
		Type string `json:"typeOf"`
		*Alias
	}{
		Type:  "alert",
		Alias: (*Alias)(n),
	}

	return json.Marshal(raw)
}
