package tmi

import (
	"time"

	badgesModels "code.justin.tv/chat/badges/app/models"
	"code.justin.tv/feeds/feeds-common/entity"
)

// ChannelAutoModProperties represents what properties a user has chosen for their AutoMod rules.
// Each rule is an int64, which any topic above that value should trigger a rejection. 0 is considered "off"
type ChannelAutoModProperties struct {
	AggressiveChannelLevel *int64 `json:"aggressive_channel_level,omitempty"`
	SexualChannelLevel     *int64 `json:"sexual_channel_level,omitempty"`
	ProfanityChannelLevel  *int64 `json:"profanity_channel_level,omitempty"`
	IdentityChannelLevel   *int64 `json:"identity_channel_level,omitempty"`
}

// AutoModRejectedMessage is the response for the AutoModRejectedMessage endpoint
type AutoModRejectedMessage struct {
	MsgID           string   `json:"msg_id"`
	SenderUserID    string   `json:"sender_user_id"`
	TargetChannelID string   `json:"target_channel_id"`
	MessageBody     string   `json:"message_body"`
	FailedFragments []string `json:"failed_fragments"`
	HadActionTaken  bool     `json:"had_action_taken"`
}

type SendMessageParams struct {
	UserID string `json:"user_id"`
	RoomID string `json:"room_id"`
	Body   string `json:"body"`
}

type SendMessageResponse struct {
	// Result indicates the result of the message
	//	- command_success
	//	- command_invalid
	//	- msg_rejected
	//		- r9k drop, etc
	//	- msg_delivered
	//	- user_ratelimited
	//		- ip or account rate limits
	//	- room_ratelimited
	//	- no_permission
	Result string `json:"result"`

	// MsgBody is the default (English) user-facing message text
	MsgBody string `json:"msg_body"`

	// MsgKey is the key for creating user-facing message text
	MsgKey string `json:"msg_key"`

	// MsgParams are the params for creating user-facing message text
	MsgParams map[string]interface{} `json:"msg_params"`

	// SentMsgID is the uuid for the sent message, if one was sent
	SentMsgID string `json:"sent_msg_id"`
}

type UserNoticeMsgParam struct {
	Key   string `json:"key" validate:"nonzero,regexp=^[0-9a-zA-Z\\-]+$"`
	Value string `json:"value" validate:"nonzero"`
}

type UserNoticeTrackingParams struct {
	// (Optional) TargetUserID is the user that is the subject of an action.
	// Examples: gifted_sub target user
	TargetUserID *string `json:"target_user_id"` // eg: gifted_sub target user
	// (Optional) TypeUniqueID is an arbitrary unique identifier to associate
	// with a product event.
	TypeUniqueID *string `json:"type_unique_id"` // eg: raid_id, purchase_order_id
}

type SendUserNoticeParams struct {
	// SenderUserID is the user that this system message is sent on behalf of.
	// The message will NOT look like a user chat message sent by this user.
	SenderUserID int `json:"sender_user_id" validate:"min=1"`
	// TargetChannelID is the channel that this system message should be sent to.
	TargetChannelID int `json:"target_channel_id" validate:"min=1"`
	// (Optional) Body is custom text provided by the sender to be shown with
	// the system message.
	Body string `json:"body" validate:"max=500"`
	// MsgID is the enum describing the type of system message. Example: "sub"
	// All MsgID values must be added to the UsernoticeWhitelist.
	MsgID string `json:"msg_id" validate:"nonzero"`
	// (Optional) MsgParams contains arbitrary metadata that may be relevant
	// for clients to provide custom rendering or additional functionality.
	MsgParams []UserNoticeMsgParam `json:"msg_params" validate:"max=20"`
	// DefaultSystemBody is the English string that should be shown by a client
	// if the client does not recognize the usernotice or does not have
	// localization for this usernotice type.
	DefaultSystemBody string `json:"default_system_body" validate:"nonzero"`
	// TrackingParams contain extra parameters to improve tracking.
	TrackingParams UserNoticeTrackingParams `json:"tracking_params"`
}

type ApproveAutoModRejectedParams struct {
	MsgID           string `json:"msg_id"`
	RequesterUserID int    `json:"requester_user_id"`
}

type BitsMessageResponse struct {
	// Sent indicates whether the message was sent (if IsNoop = false) or have
	// been sent (if IsNoop = true).
	Sent bool `json:"sent"`
	// Indicates the error code, where available, for why the message wasn't sent
	ErrorCode *string `json:"error_code,omitempty"`
	// IsNoop indicates whether the request was made as as noop request and the
	// message would not be published even if it passed enforcements.
	IsNoop  bool   `json:"is_noop"`
	MsgBody string `json:"msg_body,omitempty"`
}

// @deprecated Only used for publishing whispers
// EmoticonMatch stores the start and end indices where an emoticon was found in a string.
type EmoticonMatch struct {
	ID    int `json:"id"`
	Start int `json:"start"`
	End   int `json:"end"`
	Set   int `json:"set"`
}

type AddEmotesParams struct {
	RoomID string            `json:"room_id"`
	UserID string            `json:"user_id"`
	Emotes []AddEmoteTallies `json:"emotes"`
}

type AddEmoteTallies struct {
	Set     int    `json:"set"`
	ID      int    `json:"id"`
	Pattern string `json:"pattern"`
	Count   int    `json:"count"`
}

type Emote struct {
	Set     int    `json:"set"`
	ID      int    `json:"id"`
	Pattern string `json:"pattern"`
}

type UserFirstRoomChatResponse struct {
	// nil if the user hasn't chatted, otherwise the time of the user's first chat
	FirstChatTime *time.Time `json:"first_chat_time,omitempty"`
}

type ModifyUserPropertiesParams struct {
	ChatColor *string `json:"chat_color"`
}

type RoomsMessageContentFragment struct {
	Text          string `json:"text"`
	EmoticonID    string `json:"emoticon_id"`
	EmoticonSetID string `json:"emoticon_set_id"`
}

type RoomsMessage struct {
	ID                string                        `json:"id"`
	RoomID            string                        `json:"room_id"`
	RoomOwner         entity.Entity                 `json:"room_owner"`
	SentAt            time.Time                     `json:"send_at"`
	ContentText       string                        `json:"context_text"`
	ContentFragments  []RoomsMessageContentFragment `json:"content_fragments"`
	SenderID          string                        `json:"sender_id"`
	SenderLogin       string                        `json:"sender_login"`
	SenderDisplayName string                        `json:"sender_display_name"`
	SenderChatColor   string                        `json:"sender_chat_color"`
	SenderBadges      []badgesModels.Badge          `json:"sender_badges"`
	BitsAmount        int                           `json:"bits_amount"`
}

type ChatMessage struct {
	ID      string              `json:"id"`
	Sender  *ChatMessageSender  `json:"sender"`
	Content *ChatMessageContent `json:"content"`
}

type ChatMessageSender struct {
	ID          string  `json:"id"`
	DisplayName *string `json:"display_name"`
}

type ChatMessageContent struct {
	Text string `json:"text"`
}

const (
	ResultMsgRejected     = "msg_rejected"
	ResultMsgDelivered    = "msg_delivered"
	ResultCmdSuccess      = "cmd_success"
	ResultCmdFailed       = "cmd_failed"
	ResultCmdInvalid      = "cmd_invalid"
	ResultCmdUsage        = "cmd_usage"
	ResultNoPermission    = "no_permission"
	ResultUserRateLimited = "user_rate_limited"
	ResultRoomRateLimited = "room_rate_limited"

	ErrorBadCharacters    = "msg_bad_characters"
	ErrorUserSuspended    = "msg_suspended"
	ErrorChannelSuspended = "msg_channel_suspended"
	ErrorUserBanned       = "msg_banned"
	ErrorUserTimedOut     = "msg_timedout"
	ErrorChannelSettings  = "msg_rejected_mandatory"
)
