/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.

For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once

template <typename Object>
class object_ptr;

class PeerData;
struct ShareBoxStyleOverrides;

namespace ChatHelpers {
class Show;
} // namespace ChatHelpers

namespace Data {
struct Boost;
struct CreditsHistoryEntry;
struct SubscriptionEntry;
struct GiftCode;
struct CreditTopupOption;
struct SavedStarGift;
class SavedStarGiftId;
struct StarGift;
struct UniqueGift;
struct GiftUpgradeSpinner;
} // namespace Data

namespace HistoryView {
struct ScheduleBoxStyleArgs;
} // namespace HistoryView

namespace Main {
class Session;
class SessionShow;
} // namespace Main

namespace Window {
class SessionController;
} // namespace Window

namespace style {
struct Box;
struct Table;
struct FlatLabel;
struct PopupMenu;
struct IconButton;
struct PeerListItem;
} // namespace style

namespace Ui {
class GenericBox;
class RpWidget;
class VerticalLayout;
class PopupMenu;
} // namespace Ui

namespace Settings {

struct SubscriptionRightLabel {
	Fn<void(QPainter &, int x, int y, int h)> draw;
	QSize size;
};
SubscriptionRightLabel PaintSubscriptionRightLabelCallback(
	not_null<::Main::Session*> session,
	const style::PeerListItem &st,
	int amount);

void FillCreditOptions(
	std::shared_ptr<::Main::SessionShow> show,
	not_null<Ui::VerticalLayout*> container,
	not_null<PeerData*> peer,
	CreditsAmount minCredits,
	Fn<void()> paid,
	rpl::producer<> showFinishes,
	rpl::producer<QString> subtitle,
	std::vector<Data::CreditTopupOption> preloadedTopupOptions,
	bool dark = false,
	PeerId spendPurposePeerId = PeerId(0));

[[nodiscard]] not_null<Ui::RpWidget*> AddBalanceWidget(
	not_null<Ui::RpWidget*> parent,
	not_null<::Main::Session*> session,
	rpl::producer<CreditsAmount> balanceValue,
	bool rightAlign,
	rpl::producer<float64> opacityValue = nullptr,
	bool dark = false);

void AddWithdrawalWidget(
	not_null<Ui::VerticalLayout*> container,
	not_null<Window::SessionController*> controller,
	not_null<PeerData*> peer,
	rpl::producer<QString> secondButtonUrl,
	rpl::producer<CreditsAmount> availableBalanceValue,
	rpl::producer<QDateTime> dateValue,
	bool withdrawalEnabled,
	rpl::producer<QString> usdValue);

struct GiftWearBoxStyleOverride {
	const style::Box *box = nullptr;
	const style::IconButton *close = nullptr;
	const style::FlatLabel *title = nullptr;
	const style::FlatLabel *subtitle = nullptr;
	const style::icon *radiantIcon = nullptr;
	const style::icon *profileIcon = nullptr;
	const style::icon *proofIcon = nullptr;
	const style::FlatLabel *infoTitle = nullptr;
	const style::FlatLabel *infoAbout = nullptr;
};
[[nodiscard]] GiftWearBoxStyleOverride DarkGiftWearBoxStyle();

struct CreditsEntryBoxStyleOverrides {
	const style::Box *box = nullptr;
	const style::PopupMenu *menu = nullptr;
	const style::Table *table = nullptr;
	const style::FlatLabel *tableValueMultiline = nullptr;
	const style::FlatLabel *tableValueMessage = nullptr;
	const style::icon *link = nullptr;
	const style::icon *share = nullptr;
	const style::icon *theme = nullptr;
	const style::icon *transfer = nullptr;
	const style::icon *craft = nullptr;
	const style::icon *wear = nullptr;
	const style::icon *takeoff = nullptr;
	const style::icon *resell = nullptr;
	const style::icon *unlist = nullptr;
	const style::icon *show = nullptr;
	const style::icon *hide = nullptr;
	const style::icon *pin = nullptr;
	const style::icon *unpin = nullptr;
	const style::icon *offer = nullptr;
	std::shared_ptr<ShareBoxStyleOverrides> shareBox;
	std::shared_ptr<GiftWearBoxStyleOverride> giftWearBox;
};
[[nodiscard]] CreditsEntryBoxStyleOverrides DarkCreditsEntryBoxStyle();

[[nodiscard]] rpl::producer<CreditsAmount> UniqueGiftResalePrice(
	std::shared_ptr<Data::UniqueGift> unique,
	bool forceTon = false);
[[nodiscard]] bool UniqueGiftCanRemoveDetails(
	const Data::CreditsHistoryEntry &entry);
[[nodiscard]] Fn<void(Fn<void()> removed)> UniqueGiftRemoveDetailsHandler(
	std::shared_ptr<ChatHelpers::Show> show,
	const Data::CreditsHistoryEntry &entry);

void GenericCreditsEntryBox(
	not_null<Ui::GenericBox*> box,
	std::shared_ptr<ChatHelpers::Show> show,
	const Data::CreditsHistoryEntry &e,
	const Data::SubscriptionEntry &s,
	CreditsEntryBoxStyleOverrides st = {});
void GenericCreditsEntryBody(
	not_null<Ui::GenericBox*> box,
	std::shared_ptr<ChatHelpers::Show> show,
	const Data::CreditsHistoryEntry &e);
void GenericCreditsEntryBody(
	not_null<Ui::GenericBox*> box,
	std::shared_ptr<ChatHelpers::Show> show,
	const Data::CreditsHistoryEntry &e,
	const Data::SubscriptionEntry &s,
	std::shared_ptr<Data::GiftUpgradeSpinner> upgradeSpinner,
	CreditsEntryBoxStyleOverrides st = {});
void UniqueGiftValueBox(
	not_null<Ui::GenericBox*> box,
	std::shared_ptr<ChatHelpers::Show> show,
	const Data::CreditsHistoryEntry &e,
	CreditsEntryBoxStyleOverrides st = {});
void ReceiptCreditsBox(
	not_null<Ui::GenericBox*> box,
	not_null<Window::SessionController*> controller,
	const Data::CreditsHistoryEntry &e,
	const Data::SubscriptionEntry &s);
void BoostCreditsBox(
	not_null<Ui::GenericBox*> box,
	not_null<Window::SessionController*> controller,
	const Data::Boost &b);
void GiftedCreditsBox(
	not_null<Ui::GenericBox*> box,
	not_null<Window::SessionController*> controller,
	not_null<PeerData*> from,
	not_null<PeerData*> to,
	int count,
	TimeId date);
void CreditsPrizeBox(
	not_null<Ui::GenericBox*> box,
	not_null<Window::SessionController*> controller,
	const Data::GiftCode &data,
	TimeId date);

struct StarGiftResaleInfo {
	PeerId recipientId;
	bool forceTon = false;
};
void GlobalStarGiftBox(
	not_null<Ui::GenericBox*> box,
	std::shared_ptr<ChatHelpers::Show> show,
	const Data::StarGift &data,
	StarGiftResaleInfo resale,
	CreditsEntryBoxStyleOverrides st = {});

[[nodiscard]] Data::CreditsHistoryEntry SavedStarGiftEntry(
	not_null<PeerData*> owner,
	const Data::SavedStarGift &data);
[[nodiscard]] Data::SavedStarGiftId EntryToSavedStarGiftId(
	not_null<::Main::Session*> session,
	const Data::CreditsHistoryEntry &entry);
void ShowSavedStarGiftBox(
	not_null<Window::SessionController*> controller,
	not_null<PeerData*> owner,
	const Data::SavedStarGift &data,
	Fn<std::vector<Data::CreditsHistoryEntry>()> pinned = nullptr);
enum class SavedStarGiftMenuType {
	List,
	View,
};
void FillSavedStarGiftMenu(
	std::shared_ptr<ChatHelpers::Show> show,
	not_null<Ui::PopupMenu*> menu,
	const Data::CreditsHistoryEntry &e,
	SavedStarGiftMenuType type,
	CreditsEntryBoxStyleOverrides st = {});

void ShowStarGiftViewBox(
	not_null<Window::SessionController*> controller,
	const Data::GiftCode &data,
	FullMsgId itemId);
void ShowRefundInfoBox(
	not_null<Window::SessionController*> controller,
	FullMsgId refundItemId);

[[nodiscard]] object_ptr<Ui::RpWidget> GenericEntryPhoto(
	not_null<Ui::RpWidget*> parent,
	Fn<Fn<void(Painter &, int, int, int, int)>(Fn<void()> update)> callback,
	int photoSize);

[[nodiscard]] object_ptr<Ui::RpWidget> HistoryEntryPhoto(
	not_null<Ui::RpWidget*> parent,
	not_null<PhotoData*> photo,
	int photoSize);

[[nodiscard]] object_ptr<Ui::RpWidget> PaidMediaThumbnail(
	not_null<Ui::RpWidget*> parent,
	not_null<PhotoData*> photo,
	PhotoData *second,
	int totalCount,
	int photoSize);

[[nodiscard]] object_ptr<Ui::RpWidget> SubscriptionUserpic(
	not_null<Ui::RpWidget*> parent,
	not_null<PeerData*> peer,
	int photoSize);

struct SmallBalanceBot {
	UserId botId = 0;
};
struct SmallBalanceReaction {
	ChannelId channelId = 0;
};
struct SmallBalanceVideoStream {
	PeerId streamerId = 0;
};
struct SmallBalanceSubscription {
	QString name;
};
struct SmallBalanceDeepLink {
	QString purpose;
};
struct SmallBalanceStarGift {
	PeerId recipientId;
};
struct SmallBalanceForMessage {
	PeerId recipientId;
};
struct SmallBalanceForSuggest {
	PeerId recipientId;
};
struct SmallBalanceForOffer {
};
struct SmallBalanceForSearch {
};
struct SmallBalanceSource : std::variant<
	SmallBalanceBot,
	SmallBalanceReaction,
	SmallBalanceVideoStream,
	SmallBalanceSubscription,
	SmallBalanceDeepLink,
	SmallBalanceStarGift,
	SmallBalanceForMessage,
	SmallBalanceForSuggest,
	SmallBalanceForOffer,
	SmallBalanceForSearch> {
	using variant::variant;
};

void SmallBalanceBox(
	not_null<Ui::GenericBox*> box,
	std::shared_ptr<::Main::SessionShow> show,
	uint64 wholeCredits,
	SmallBalanceSource source,
	Fn<void()> paid);

enum class SmallBalanceResult {
	Already,
	Success,
	Blocked,
	Cancelled,
};

void MaybeRequestBalanceIncrease(
	std::shared_ptr<::Main::SessionShow> show,
	uint64 credits,
	SmallBalanceSource source,
	Fn<void(SmallBalanceResult)> done);

void AddMiniStars(
	not_null<Ui::VerticalLayout*> content,
	not_null<Ui::RpWidget*> widget,
	int photoSize,
	int boxWidth,
	float64 heightRatio);

void AddUniqueCloseMoreButton(
	not_null<Ui::GenericBox*> box,
	Settings::CreditsEntryBoxStyleOverrides st,
	Fn<void(not_null<Ui::PopupMenu*>)> fillMenu = nullptr,
	Fn<void()> launchCraft = nullptr);

} // namespace Settings
