/*
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

#include "history/view/media/history_view_file.h"
#include "history/view/media/history_view_service_box.h"
#include "history/view/media/history_view_sticker.h"

class Image;
struct HistoryMessageSuggestion;

namespace Data {
class DocumentMedia;
class WallPaper;
class MediaGiftBox;
struct GiftCode;
} // namespace Data

namespace HistoryView {

class ThemeDocument final : public File {
public:
	ThemeDocument(not_null<Element*> parent, DocumentData *document);
	ThemeDocument(
		not_null<Element*> parent,
		DocumentData *document,
		const std::optional<Data::WallPaper> &params,
		int serviceWidth = 0);
	~ThemeDocument();

	void draw(Painter &p, const PaintContext &context) const override;
	TextState textState(QPoint point, StateRequest request) const override;

	DocumentData *getDocument() const override {
		return _data;
	}

	bool needsBubble() const override {
		return false;
	}
	bool customInfoLayout() const override {
		return false;
	}
	bool skipBubbleTail() const override {
		return true;
	}
	bool isReadyForOpen() const override;

	bool hasHeavyPart() const override;
	void unloadHeavyPart() override;

	[[nodiscard]] static std::optional<Data::WallPaper> ParamsFromUrl(
		const QString &url);

protected:
	float64 dataProgress() const override;
	bool dataFinished() const override;
	bool dataLoaded() const override;

private:
	QSize countOptimalSize() override;
	QSize countCurrentSize(int newWidth) override;

	[[nodiscard]] bool checkGoodThumbnail() const;
	void validateThumbnail() const;
	void prepareThumbnailFrom(not_null<Image*> image, int good) const;
	void generateThumbnail() const;
	void ensureDataMediaCreated() const;
	[[nodiscard]] QImage finishServiceThumbnail(QImage image) const;

	DocumentData *_data = nullptr;
	int _pixw = 1;
	int _pixh = 1;
	const int _serviceWidth = 0;
	mutable QPixmap _thumbnail;
	mutable int _thumbnailGood = -1; // -1 inline, 0 thumbnail, 1 good
	mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;

	// For wallpaper documents.
	std::vector<QColor> _background;
	float64 _patternOpacity = 0.;
	int _gradientRotation = 0;

	mutable bool _isDark = false;
	int _dimmingIntensity = 0;
	bool _blurredWallPaper = false;

};

class ThemeDocumentBox final : public ServiceBoxContent {
public:
	ThemeDocumentBox(
		not_null<Element*> parent,
		const Data::WallPaper &paper);
	~ThemeDocumentBox();

	int top() override;
	QSize size() override;
	TextWithEntities title() override;
	TextWithEntities subtitle() override;
	rpl::producer<QString> button() override;
	void draw(
		Painter &p,
		const PaintContext &context,
		const QRect &geometry) override;
	ClickHandlerPtr createViewLink() override;

	bool hideServiceText() override {
		return true;
	}

	void stickerClearLoopPlayed() override;
	std::unique_ptr<StickerPlayer> stickerTakePlayer(
		not_null<DocumentData*> data,
		const Lottie::ColorReplacements *replacements) override;

	bool hasHeavyPart() override;
	void unloadHeavyPart() override;

private:
	void createPreview(const Data::WallPaper &paper);

	const not_null<Element*> _parent;
	QString _emojiId;
	std::optional<ThemeDocument> _preview;
	rpl::lifetime _lifetime;

};

class GiftServiceBox final
	: public ServiceBoxContent
	, public base::has_weak_ptr {
public:
	GiftServiceBox(
		not_null<Element*> parent,
		not_null<Data::MediaGiftBox*> gift);
	~GiftServiceBox();

	int top() override;
	int width() override;
	QSize size() override;
	TextWithEntities title() override;
	TextWithEntities subtitle() override;
	rpl::producer<QString> button() override;
	int buttonSkip() override;
	void draw(
		Painter &p,
		const PaintContext &context,
		const QRect &geometry) override;
	ClickHandlerPtr createViewLink() override;

	rpl::producer<> changes() override;

	bool hideServiceText() override;
	void stickerClearLoopPlayed() override;
	std::unique_ptr<StickerPlayer> stickerTakePlayer(
		not_null<DocumentData*> data,
		const Lottie::ColorReplacements *replacements) override;

	bool hasHeavyPart() override;
	void unloadHeavyPart() override;

private:
	void ensureStickerCreated() const;
	void cacheUniqueBackground(int width, int height);
	void checkKeyboardRemoval(
		not_null<const HistoryMessageSuggestion*> suggestion,
		bool expired);
	void clearKeyboard();

	const not_null<Element*> _parent;
	const Data::GiftCode &_data;
	std::unique_ptr<Ui::Text::CustomEmoji> _patternEmoji;
	QImage _backgroundCache;
	base::flat_map<float64, QImage> _patternCache;
	bool _backroundPatterned = false;
	mutable std::optional<Sticker> _sticker;
	rpl::event_stream<> _changes;
	base::Timer _changeTimer;

};

} // namespace HistoryView
