/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2024-2026 Matthias Klumpp <matthias@tenstral.net>
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the license, or
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#if !defined(__APPSTREAM_COMPOSE_H) && !defined(ASC_COMPILATION)
#error "Only <appstream-compose.h> can be included directly."
#endif
#pragma once

#include <glib-object.h>
#include <gio/gio.h>

G_BEGIN_DECLS

/**
 * AscMediaError:
 * @ASC_MEDIA_ERROR_FAILED:		Generic failure.
 * @ASC_MEDIA_ERROR_DEAD_WORKER:	The media worker process crashed or could not be spawned.
 * @ASC_MEDIA_ERROR_TIMEOUT:		A media operation took too long and was aborted.
 * @ASC_MEDIA_ERROR_PROTOCOL:		Communication with the media worker was corrupted.
 * @ASC_MEDIA_ERROR_UNSUPPORTED:	The requested operation or image type was not supported.
 *
 * A media processing error.
 *
 * Since: 1.2.0
 **/
typedef enum {
	ASC_MEDIA_ERROR_FAILED,
	ASC_MEDIA_ERROR_DEAD_WORKER,
	ASC_MEDIA_ERROR_TIMEOUT,
	ASC_MEDIA_ERROR_PROTOCOL,
	ASC_MEDIA_ERROR_UNSUPPORTED,
	/*< private >*/
	ASC_MEDIA_ERROR_LAST
} AscMediaError;

#define ASC_MEDIA_ERROR asc_media_error_quark ()
GQuark asc_media_error_quark (void);

/**
 * AscImageScaleMode:
 * @ASC_IMAGE_SCALE_MODE_NONE:		Keep the original (loaded) image size.
 * @ASC_IMAGE_SCALE_MODE_PAD:		Scale to fit the target dimensions and center the
 *					result on a transparent canvas of exactly that size.
 * @ASC_IMAGE_SCALE_MODE_FIT_WIDTH:	Scale proportionally to match the target width.
 * @ASC_IMAGE_SCALE_MODE_FIT_HEIGHT:	Scale proportionally to match the target height.
 *
 * How an image rendition should be scaled. Every mode preserves the aspect ratio of
 * the source image - an image is never stretched or cropped to fill a target size.
 *
 * Since: 1.2.0
 **/
typedef enum {
	ASC_IMAGE_SCALE_MODE_NONE,
	ASC_IMAGE_SCALE_MODE_PAD,
	ASC_IMAGE_SCALE_MODE_FIT_WIDTH,
	ASC_IMAGE_SCALE_MODE_FIT_HEIGHT,
	/*< private >*/
	ASC_IMAGE_SCALE_MODE_LAST
} AscImageScaleMode;

/**
 * AscImageSaveFlags:
 * @ASC_IMAGE_SAVE_FLAG_NONE:		No special flags set
 * @ASC_IMAGE_SAVE_FLAG_LOSSLESS:	Encode the image losslessly
 * @ASC_IMAGE_SAVE_FLAG_OPTIMIZE:	Optimize generated PNG for size
 * @ASC_IMAGE_SAVE_FLAG_SHARPEN:	Sharpen the image to clarify detail
 *
 * The flags used for saving images.
 *
 * Since: 0.14.0
 **/
typedef enum {
	ASC_IMAGE_SAVE_FLAG_NONE     = 0,
	ASC_IMAGE_SAVE_FLAG_LOSSLESS = 1 << 0,
	ASC_IMAGE_SAVE_FLAG_OPTIMIZE = 1 << 1,
	ASC_IMAGE_SAVE_FLAG_SHARPEN  = 1 << 2,
} AscImageSaveFlags;

/**
 * AscImageFormat:
 * @ASC_IMAGE_FORMAT_UNKNOWN:	Unknown image format.
 * @ASC_IMAGE_FORMAT_PNG:	PNG format
 * @ASC_IMAGE_FORMAT_JXL:	JPEG-XL format
 * @ASC_IMAGE_FORMAT_SVG:	SVG format
 * @ASC_IMAGE_FORMAT_SVGZ:	Compressed SVG format
 * @ASC_IMAGE_FORMAT_AVIF:	AVIF format
 * @ASC_IMAGE_FORMAT_WEBP:	WebP format
 * @ASC_IMAGE_FORMAT_JPEG:	JPEG format
 * @ASC_IMAGE_FORMAT_GIF:	GIF format
 *
 * File format of an image.
 *
 * All of these formats can be read, but renditions are only ever written as
 * %ASC_IMAGE_FORMAT_PNG or %ASC_IMAGE_FORMAT_JXL - the other values are for
 * classifying input data.
 *
 * Since: 0.14.0
 **/
typedef enum {
	ASC_IMAGE_FORMAT_UNKNOWN,
	ASC_IMAGE_FORMAT_PNG,
	ASC_IMAGE_FORMAT_JXL,
	ASC_IMAGE_FORMAT_SVG,
	ASC_IMAGE_FORMAT_SVGZ,
	ASC_IMAGE_FORMAT_AVIF,
	ASC_IMAGE_FORMAT_WEBP,
	ASC_IMAGE_FORMAT_JPEG,
	ASC_IMAGE_FORMAT_GIF,
	/*< private >*/
	ASC_IMAGE_FORMAT_LAST
} AscImageFormat;

const gchar		      *asc_image_format_to_string (AscImageFormat format);
AscImageFormat		       asc_image_format_from_string (const gchar *str);
AscImageFormat		       asc_image_format_from_filename (const gchar *fname);

typedef struct _AscImageSource AscImageSource;

#define ASC_TYPE_IMAGE_SOURCE (asc_image_source_get_type ())
GType		asc_image_source_get_type (void);

AscImageSource *asc_image_source_new (GBytes *data);
AscImageSource *asc_image_source_copy (AscImageSource *source);
void		asc_image_source_free (AscImageSource *source);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AscImageSource, asc_image_source_free)

GBytes			      *asc_image_source_get_data (AscImageSource *source);

void			       asc_image_source_get_render_size (AscImageSource *source,
								 gint		*width,
								 gint		*height);
void			       asc_image_source_set_render_size (AscImageSource *source,
								 gint		 width,
								 gint		 height);

gint			       asc_image_source_get_width (AscImageSource *source);
gint			       asc_image_source_get_height (AscImageSource *source);

typedef struct _AscImageTarget AscImageTarget;

#define ASC_TYPE_IMAGE_TARGET (asc_image_target_get_type ())
GType		asc_image_target_get_type (void);

AscImageTarget *asc_image_target_new (const gchar      *name,
				      AscImageScaleMode scale_mode,
				      gint		width,
				      gint		height);
AscImageTarget *asc_image_target_copy (AscImageTarget *target);
void		asc_image_target_free (AscImageTarget *target);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AscImageTarget, asc_image_target_free)

const gchar	 *asc_image_target_get_name (AscImageTarget *target);
AscImageScaleMode asc_image_target_get_scale_mode (AscImageTarget *target);
gint		  asc_image_target_get_width (AscImageTarget *target);
gint		  asc_image_target_get_height (AscImageTarget *target);

AscImageSaveFlags asc_image_target_get_save_flags (AscImageTarget *target);
void		  asc_image_target_set_save_flags (AscImageTarget   *target,
						   AscImageSaveFlags flags);

gboolean	  asc_image_target_get_only_downscale (AscImageTarget *target);
void		  asc_image_target_set_only_downscale (AscImageTarget *target,
						       gboolean	       only_downscale);

void		  asc_image_target_get_source_size_range (AscImageTarget *target,
							  gint		 *min_width,
							  gint		 *min_height,
							  gint		 *max_width,
							  gint		 *max_height);
void		  asc_image_target_set_source_size_range (AscImageTarget *target,
							  gint		  min_width,
							  gint		  min_height,
							  gint		  max_width,
							  gint		  max_height);

gboolean	  asc_image_target_get_skipped (AscImageTarget *target);
gint		  asc_image_target_get_result_width (AscImageTarget *target);
gint		  asc_image_target_get_result_height (AscImageTarget *target);
const gchar	 *asc_image_target_get_error_message (AscImageTarget *target);

#define ASC_TYPE_MEDIA (asc_media_get_type ())
G_DECLARE_FINAL_TYPE (AscMedia, asc_media, ASC, MEDIA, GObject)

AscMedia *asc_media_new (void);

guint	  asc_media_get_request_timeout (AscMedia *media);
void	  asc_media_set_request_timeout (AscMedia *media,
					 guint	   seconds);

guint32	  asc_media_get_memory_limit (AscMedia *media);
void	  asc_media_set_memory_limit (AscMedia *media,
				      guint32	limit_mib);

gboolean  asc_media_ensure_worker (AscMedia	*media,
				   GCancellable *cancellable,
				   GError      **error);
void	  asc_media_stop (AscMedia *media);

gboolean  asc_media_error_is_worker_failure (const GError *error);

gboolean  asc_media_process_image (AscMedia	  *media,
				   AscImageSource *source,
				   GPtrArray	  *targets,
				   const gchar	  *out_dir,
				   GCancellable	  *cancellable,
				   GError	 **error);

G_END_DECLS
