/*
   GoToSocial
   Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package model

// Status represents a mastodon-api Status type, as defined here: https://docs.joinmastodon.org/entities/status/
type Status struct {
	// ID of the status in the database.
	ID string `json:"id"`
	// The date when this status was created (ISO 8601 Datetime)
	CreatedAt string `json:"created_at"`
	// ID of the status being replied.
	InReplyToID string `json:"in_reply_to_id,omitempty"`
	// ID of the account being replied to.
	InReplyToAccountID string `json:"in_reply_to_account_id,omitempty"`
	// Is this status marked as sensitive content?
	Sensitive bool `json:"sensitive"`
	// Subject or summary line, below which status content is collapsed until expanded.
	SpoilerText string `json:"spoiler_text"`
	// Visibility of this status.
	Visibility Visibility `json:"visibility"`
	// Primary language of this status. (ISO 639 Part 1 two-letter language code)
	Language string `json:"language"`
	// URI of the status used for federation.
	URI string `json:"uri"`
	// A link to the status's HTML representation.
	URL string `json:"url"`
	// How many replies this status has received.
	RepliesCount int `json:"replies_count"`
	// How many boosts this status has received.
	ReblogsCount int `json:"reblogs_count"`
	// How many favourites this status has received.
	FavouritesCount int `json:"favourites_count"`
	// Have you favourited this status?
	Favourited bool `json:"favourited"`
	// Have you boosted this status?
	Reblogged bool `json:"reblogged"`
	// Have you muted notifications for this status's conversation?
	Muted bool `json:"muted"`
	// Have you bookmarked this status?
	Bookmarked bool `json:"bookmarked"`
	// Have you pinned this status? Only appears if the status is pinnable.
	Pinned bool `json:"pinned,omitempty"`
	// HTML-encoded status content.
	Content string `json:"content"`
	// The status being reblogged.
	Reblog *Status `json:"reblog,omitempty"`
	// The application used to post this status.
	Application *Application `json:"application"`
	// The account that authored this status.
	Account *Account `json:"account"`
	// Media that is attached to this status.
	MediaAttachments []Attachment `json:"media_attachments"`
	// Mentions of users within the status content.
	Mentions []Mention `json:"mentions"`
	// Hashtags used within the status content.
	Tags []Tag `json:"tags"`
	// Custom emoji to be used when rendering status content.
	Emojis []Emoji `json:"emojis"`
	// Preview card for links included within status content.
	Card *Card `json:"card"`
	// The poll attached to the status.
	Poll *Poll `json:"poll"`
	// Plain-text source of a status. Returned instead of content when status is deleted,
	// so the user may redraft from the source text without the client having to reverse-engineer
	// the original text from the HTML content.
	Text string `json:"text"`
}

// StatusCreateRequest represents a mastodon-api status POST request, as defined here: https://docs.joinmastodon.org/methods/statuses/
// It should be used at the path https://mastodon.example/api/v1/statuses
type StatusCreateRequest struct {
	// Text content of the status. If media_ids is provided, this becomes optional. Attaching a poll is optional while status is provided.
	Status string `form:"status" json:"status" xml:"status"`
	// Array of Attachment ids to be attached as media. If provided, status becomes optional, and poll cannot be used.
	MediaIDs []string `form:"media_ids" json:"media_ids" xml:"media_ids"`
	// Poll to include with this status.
	Poll *PollRequest `form:"poll" json:"poll" xml:"poll"`
	// ID of the status being replied to, if status is a reply
	InReplyToID string `form:"in_reply_to_id" json:"in_reply_to_id" xml:"in_reply_to_id"`
	// Mark status and attached media as sensitive?
	Sensitive bool `form:"sensitive" json:"sensitive" xml:"sensitive"`
	// Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field.
	SpoilerText string `form:"spoiler_text" json:"spoiler_text" xml:"spoiler_text"`
	// Visibility of the posted status. Enumerable oneOf public, unlisted, private, direct.
	Visibility Visibility `form:"visibility" json:"visibility" xml:"visibility"`
	// ISO 8601 Datetime at which to schedule a status. Providing this paramter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future.
	ScheduledAt string `form:"scheduled_at" json:"scheduled_at" xml:"scheduled_at"`
	// ISO 639 language code for this status.
	Language string `form:"language" json:"language" xml:"language"`
}

// Visibility denotes the visibility of this status to other users
type Visibility string

const (
	// VisibilityPublic means visible to everyone
	VisibilityPublic Visibility = "public"
	// VisibilityUnlisted means visible to everyone but only on home timelines or in lists
	VisibilityUnlisted Visibility = "unlisted"
	// VisibilityPrivate means visible to followers only
	VisibilityPrivate Visibility = "private"
	// VisibilityDirect means visible only to tagged recipients
	VisibilityDirect Visibility = "direct"
)

// AdvancedStatusCreateForm wraps the mastodon status create form along with the GTS advanced
// visibility settings.
type AdvancedStatusCreateForm struct {
	StatusCreateRequest
	AdvancedVisibilityFlagsForm
}

// AdvancedVisibilityFlagsForm allows a few more advanced flags to be set on new statuses, in addition
// to the standard mastodon-compatible ones.
type AdvancedVisibilityFlagsForm struct {
	// The gotosocial visibility model
	VisibilityAdvanced *string `form:"visibility_advanced" json:"visibility_advanced" xml:"visibility_advanced"`
	// This status will be federated beyond the local timeline(s)
	Federated *bool `form:"federated" json:"federated" xml:"federated"`
	// This status can be boosted/reblogged
	Boostable *bool `form:"boostable" json:"boostable" xml:"boostable"`
	// This status can be replied to
	Replyable *bool `form:"replyable" json:"replyable" xml:"replyable"`
	// This status can be liked/faved
	Likeable *bool `form:"likeable" json:"likeable" xml:"likeable"`
}