/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattisbvf
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef __PIKA_IMAGE_H__
#define __PIKA_IMAGE_H__


#include "pikaviewable.h"


#define PIKA_IMAGE_ACTIVE_PARENT ((gpointer) 1)


#define PIKA_TYPE_IMAGE            (pika_image_get_type ())
#define PIKA_IMAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_IMAGE, PikaImage))
#define PIKA_IMAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_IMAGE, PikaImageClass))
#define PIKA_IS_IMAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_IMAGE))
#define PIKA_IS_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_IMAGE))
#define PIKA_IMAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_IMAGE, PikaImageClass))


typedef struct _PikaImageClass   PikaImageClass;
typedef struct _PikaImagePrivate PikaImagePrivate;

struct _PikaImage
{
  PikaViewable      parent_instance;

  Pika             *pika;  /*  the PIKA the image belongs to  */

  PikaImagePrivate *priv;
};

struct _PikaImageClass
{
  PikaViewableClass  parent_class;

  /*  signals  */
  void (* mode_changed)                 (PikaImage            *image);
  void (* precision_changed)            (PikaImage            *image);
  void (* alpha_changed)                (PikaImage            *image);
  void (* floating_selection_changed)   (PikaImage            *image);
  void (* selected_channels_changed)    (PikaImage            *image);
  void (* selected_vectors_changed)     (PikaImage            *image);
  void (* selected_layers_changed)      (PikaImage            *image);
  void (* component_visibility_changed) (PikaImage            *image,
                                         PikaChannelType       channel);
  void (* component_active_changed)     (PikaImage            *image,
                                         PikaChannelType       channel);
  void (* mask_changed)                 (PikaImage            *image);
  void (* resolution_changed)           (PikaImage            *image);
  void (* size_changed_detailed)        (PikaImage            *image,
                                         gint                  previous_origin_x,
                                         gint                  previous_origin_y,
                                         gint                  previous_width,
                                         gint                  previous_height);
  void (* unit_changed)                 (PikaImage            *image);
  void (* quick_mask_changed)           (PikaImage            *image);
  void (* selection_invalidate)         (PikaImage            *image);

  void (* clean)                        (PikaImage            *image,
                                         PikaDirtyMask         dirty_mask);
  void (* dirty)                        (PikaImage            *image,
                                         PikaDirtyMask         dirty_mask);
  void (* saving)                       (PikaImage            *image);
  void (* saved)                        (PikaImage            *image,
                                         GFile                *file);
  void (* exported)                     (PikaImage            *image,
                                         GFile                *file);

  void (* guide_added)                  (PikaImage            *image,
                                         PikaGuide            *guide);
  void (* guide_removed)                (PikaImage            *image,
                                         PikaGuide            *guide);
  void (* guide_moved)                  (PikaImage            *image,
                                         PikaGuide            *guide);
  void (* sample_point_added)           (PikaImage            *image,
                                         PikaSamplePoint      *sample_point);
  void (* sample_point_removed)         (PikaImage            *image,
                                         PikaSamplePoint      *sample_point);
  void (* sample_point_moved)           (PikaImage            *image,
                                         PikaSamplePoint      *sample_point);
  void (* parasite_attached)            (PikaImage            *image,
                                         const gchar          *name);
  void (* parasite_detached)            (PikaImage            *image,
                                         const gchar          *name);
  void (* colormap_changed)             (PikaImage            *image,
                                         gint                  color_index);
  void (* undo_event)                   (PikaImage            *image,
                                         PikaUndoEvent         event,
                                         PikaUndo             *undo);
  void (* layer_sets_changed)           (PikaImage            *image);
  void (* channel_sets_changed)         (PikaImage            *image);
  void (* vectors_sets_changed)         (PikaImage            *image);
};


GType           pika_image_get_type              (void) G_GNUC_CONST;

PikaImage     * pika_image_new                   (Pika               *pika,
                                                  gint                width,
                                                  gint                height,
                                                  PikaImageBaseType   base_type,
                                                  PikaPrecision       precision);

gint64          pika_image_estimate_memsize      (PikaImage          *image,
                                                  PikaComponentType   component_type,
                                                  gint                width,
                                                  gint                height);

PikaImageBaseType  pika_image_get_base_type      (PikaImage          *image);
PikaComponentType  pika_image_get_component_type (PikaImage          *image);
PikaPrecision      pika_image_get_precision      (PikaImage          *image);

const Babl    * pika_image_get_format            (PikaImage          *image,
                                                  PikaImageBaseType   base_type,
                                                  PikaPrecision       precision,
                                                  gboolean            with_alpha,
                                                  const Babl         *space);

const Babl    * pika_image_get_layer_space       (PikaImage          *image);
const Babl    * pika_image_get_layer_format      (PikaImage          *image,
                                                  gboolean            with_alpha);
const Babl    * pika_image_get_channel_format    (PikaImage          *image);
const Babl    * pika_image_get_mask_format       (PikaImage          *image);

PikaLayerMode   pika_image_get_default_new_layer_mode
                                                 (PikaImage          *image);
void            pika_image_unset_default_new_layer_mode
                                                 (PikaImage          *image);

gint            pika_image_get_id                (PikaImage          *image);
PikaImage     * pika_image_get_by_id             (Pika               *pika,
                                                  gint                id);

GFile         * pika_image_get_file              (PikaImage          *image);
GFile         * pika_image_get_untitled_file     (PikaImage          *image);
GFile         * pika_image_get_file_or_untitled  (PikaImage          *image);
GFile         * pika_image_get_imported_file     (PikaImage          *image);
GFile         * pika_image_get_exported_file     (PikaImage          *image);
GFile         * pika_image_get_save_a_copy_file  (PikaImage          *image);
GFile         * pika_image_get_any_file          (PikaImage          *image);

void            pika_image_set_file              (PikaImage          *image,
                                                  GFile              *file);
void            pika_image_set_imported_file     (PikaImage          *image,
                                                  GFile              *file);
void            pika_image_set_exported_file     (PikaImage          *image,
                                                  GFile              *file);
void            pika_image_set_save_a_copy_file  (PikaImage          *image,
                                                  GFile              *file);

const gchar   * pika_image_get_display_name      (PikaImage          *image);
const gchar   * pika_image_get_display_path      (PikaImage          *image);

void            pika_image_set_load_proc         (PikaImage          *image,
                                                  PikaPlugInProcedure *proc);
PikaPlugInProcedure * pika_image_get_load_proc   (PikaImage          *image);
void            pika_image_set_save_proc         (PikaImage          *image,
                                                  PikaPlugInProcedure *proc);
PikaPlugInProcedure * pika_image_get_save_proc   (PikaImage          *image);
void            pika_image_saving                (PikaImage          *image);
void            pika_image_saved                 (PikaImage          *image,
                                                  GFile              *file);
void            pika_image_set_export_proc       (PikaImage          *image,
                                                  PikaPlugInProcedure *proc);
PikaPlugInProcedure * pika_image_get_export_proc (PikaImage          *image);
void            pika_image_exported              (PikaImage          *image,
                                                  GFile              *file);

gint            pika_image_get_xcf_version       (PikaImage          *image,
                                                  gboolean            zlib_compression,
                                                  gint               *pika_version,
                                                  const gchar       **version_string,
                                                  gchar             **version_reason);

void            pika_image_set_xcf_compression   (PikaImage          *image,
                                                  gboolean            compression);
gboolean        pika_image_get_xcf_compression   (PikaImage          *image);

void            pika_image_set_resolution        (PikaImage          *image,
                                                  gdouble             xres,
                                                  gdouble             yres);
void            pika_image_get_resolution        (PikaImage          *image,
                                                  gdouble            *xres,
                                                  gdouble            *yres);
void            pika_image_resolution_changed    (PikaImage          *image);

void            pika_image_set_unit              (PikaImage          *image,
                                                  PikaUnit            unit);
PikaUnit        pika_image_get_unit              (PikaImage          *image);
void            pika_image_unit_changed          (PikaImage          *image);

gint            pika_image_get_width             (PikaImage          *image);
gint            pika_image_get_height            (PikaImage          *image);

gboolean        pika_image_has_alpha             (PikaImage          *image);
gboolean        pika_image_is_empty              (PikaImage          *image);

void           pika_image_set_floating_selection (PikaImage          *image,
                                                  PikaLayer          *floating_sel);
PikaLayer    * pika_image_get_floating_selection (PikaImage          *image);
void       pika_image_floating_selection_changed (PikaImage          *image);

PikaChannel   * pika_image_get_mask              (PikaImage          *image);
void            pika_image_mask_changed          (PikaImage          *image);
gboolean        pika_image_mask_intersect        (PikaImage          *image,
                                                  GList              *items,
                                                  gint               *x,
                                                  gint               *y,
                                                  gint               *width,
                                                  gint               *height);


/*  image components  */

const Babl    * pika_image_get_component_format  (PikaImage          *image,
                                                  PikaChannelType     channel);
gint            pika_image_get_component_index   (PikaImage          *image,
                                                  PikaChannelType     channel);

void            pika_image_set_component_active  (PikaImage          *image,
                                                  PikaChannelType     type,
                                                  gboolean            active);
gboolean        pika_image_get_component_active  (PikaImage          *image,
                                                  PikaChannelType     type);
void            pika_image_get_active_array      (PikaImage          *image,
                                                  gboolean           *components);
PikaComponentMask pika_image_get_active_mask     (PikaImage          *image);

void            pika_image_set_component_visible (PikaImage          *image,
                                                  PikaChannelType     type,
                                                  gboolean            visible);
gboolean        pika_image_get_component_visible (PikaImage          *image,
                                                  PikaChannelType     type);
void            pika_image_get_visible_array     (PikaImage          *image,
                                                  gboolean           *components);
PikaComponentMask pika_image_get_visible_mask    (PikaImage          *image);


/*  emitting image signals  */

void            pika_image_mode_changed          (PikaImage          *image);
void            pika_image_precision_changed     (PikaImage          *image);
void            pika_image_alpha_changed         (PikaImage          *image);
void            pika_image_invalidate            (PikaImage          *image,
                                                  gint                x,
                                                  gint                y,
                                                  gint                width,
                                                  gint                height);
void            pika_image_invalidate_all        (PikaImage          *image);
void            pika_image_guide_added           (PikaImage          *image,
                                                  PikaGuide          *guide);
void            pika_image_guide_removed         (PikaImage          *image,
                                                  PikaGuide          *guide);
void            pika_image_guide_moved           (PikaImage          *image,
                                                  PikaGuide          *guide);

void            pika_image_sample_point_added    (PikaImage          *image,
                                                  PikaSamplePoint    *sample_point);
void            pika_image_sample_point_removed  (PikaImage          *image,
                                                  PikaSamplePoint    *sample_point);
void            pika_image_sample_point_moved    (PikaImage          *image,
                                                  PikaSamplePoint    *sample_point);
void            pika_image_colormap_changed      (PikaImage          *image,
                                                  gint                col);
void            pika_image_selection_invalidate  (PikaImage          *image);
void            pika_image_quick_mask_changed    (PikaImage          *image);
void            pika_image_size_changed_detailed (PikaImage          *image,
                                                  gint                previous_origin_x,
                                                  gint                previous_origin_y,
                                                  gint                previous_width,
                                                  gint                previous_height);
void            pika_image_undo_event            (PikaImage          *image,
                                                  PikaUndoEvent       event,
                                                  PikaUndo           *undo);


/*  dirty counters  */

gint            pika_image_dirty                 (PikaImage          *image,
                                                  PikaDirtyMask       dirty_mask);
gint            pika_image_clean                 (PikaImage          *image,
                                                  PikaDirtyMask       dirty_mask);
void            pika_image_clean_all             (PikaImage          *image);
void            pika_image_export_clean_all      (PikaImage          *image);
gint            pika_image_is_dirty              (PikaImage          *image);
gboolean        pika_image_is_export_dirty       (PikaImage          *image);
gint64          pika_image_get_dirty_time        (PikaImage          *image);


/*  flush this image's displays  */

void            pika_image_flush                 (PikaImage          *image);


/*  display / instance counters  */

gint            pika_image_get_display_count     (PikaImage          *image);
void            pika_image_inc_display_count     (PikaImage          *image);
void            pika_image_dec_display_count     (PikaImage          *image);

gint            pika_image_get_instance_count    (PikaImage          *image);
void            pika_image_inc_instance_count    (PikaImage          *image);

void            pika_image_inc_show_all_count    (PikaImage          *image);
void            pika_image_dec_show_all_count    (PikaImage          *image);


/*  parasites  */

const PikaParasite * pika_image_parasite_find    (PikaImage          *image,
                                                  const gchar        *name);
gchar        ** pika_image_parasite_list         (PikaImage          *image);
gboolean        pika_image_parasite_validate     (PikaImage          *image,
                                                  const PikaParasite *parasite,
                                                  GError            **error);
void            pika_image_parasite_attach       (PikaImage          *image,
                                                  const PikaParasite *parasite,
                                                  gboolean            push_undo);
void            pika_image_parasite_detach       (PikaImage          *image,
                                                  const gchar        *name,
                                                  gboolean            push_undo);


/*  tattoos  */

PikaTattoo      pika_image_get_new_tattoo        (PikaImage          *image);
gboolean        pika_image_set_tattoo_state      (PikaImage          *image,
                                                  PikaTattoo          val);
PikaTattoo      pika_image_get_tattoo_state      (PikaImage          *image);


/*  projection  */

PikaProjection * pika_image_get_projection       (PikaImage          *image);


/*  layers / channels / vectors  */

PikaItemTree  * pika_image_get_layer_tree        (PikaImage          *image);
PikaItemTree  * pika_image_get_channel_tree      (PikaImage          *image);
PikaItemTree  * pika_image_get_vectors_tree      (PikaImage          *image);

PikaContainer * pika_image_get_layers            (PikaImage          *image);
PikaContainer * pika_image_get_channels          (PikaImage          *image);
PikaContainer * pika_image_get_vectors           (PikaImage          *image);

gint            pika_image_get_n_layers          (PikaImage          *image);
gint            pika_image_get_n_channels        (PikaImage          *image);
gint            pika_image_get_n_vectors         (PikaImage          *image);

GList         * pika_image_get_layer_iter        (PikaImage          *image);
GList         * pika_image_get_channel_iter      (PikaImage          *image);
GList         * pika_image_get_vectors_iter      (PikaImage          *image);

GList         * pika_image_get_layer_list        (PikaImage          *image);
GList         * pika_image_get_channel_list      (PikaImage          *image);
GList         * pika_image_get_vectors_list      (PikaImage          *image);

void          pika_image_unset_selected_channels (PikaImage          *image);

gboolean        pika_image_is_selected_drawable  (PikaImage          *image,
                                                  PikaDrawable       *drawable);
gboolean     pika_image_equal_selected_drawables (PikaImage          *image,
                                                  GList              *drawables);

GList        * pika_image_get_selected_drawables (PikaImage          *image);
GList         * pika_image_get_selected_layers   (PikaImage          *image);
GList         * pika_image_get_selected_channels (PikaImage          *image);
GList         * pika_image_get_selected_vectors  (PikaImage          *image);

void            pika_image_set_selected_layers   (PikaImage          *image,
                                                  GList              *layers);
void            pika_image_set_selected_channels (PikaImage          *image,
                                                  GList              *channels);
void            pika_image_set_selected_vectors  (PikaImage          *image,
                                                  GList              *vectors);

PikaLayer     * pika_image_get_layer_by_tattoo   (PikaImage          *image,
                                                  PikaTattoo          tattoo);
PikaChannel   * pika_image_get_channel_by_tattoo (PikaImage          *image,
                                                  PikaTattoo          tattoo);
PikaVectors   * pika_image_get_vectors_by_tattoo (PikaImage          *image,
                                                  PikaTattoo          tattoo);

PikaLayer     * pika_image_get_layer_by_name     (PikaImage          *image,
                                                  const gchar        *name);
PikaChannel   * pika_image_get_channel_by_name   (PikaImage          *image,
                                                  const gchar        *name);
PikaVectors   * pika_image_get_vectors_by_name   (PikaImage          *image,
                                                  const gchar        *name);

gboolean        pika_image_reorder_item          (PikaImage          *image,
                                                  PikaItem           *item,
                                                  PikaItem           *new_parent,
                                                  gint                new_index,
                                                  gboolean            push_undo,
                                                  const gchar        *undo_desc);
gboolean        pika_image_raise_item            (PikaImage          *image,
                                                  PikaItem           *item,
                                                  GError            **error);
gboolean        pika_image_raise_item_to_top     (PikaImage          *image,
                                                  PikaItem           *item);
gboolean        pika_image_lower_item            (PikaImage          *image,
                                                  PikaItem           *item,
                                                  GError            **error);
gboolean        pika_image_lower_item_to_bottom  (PikaImage          *image,
                                                  PikaItem           *item);

gboolean        pika_image_add_layer             (PikaImage          *image,
                                                  PikaLayer          *layer,
                                                  PikaLayer          *parent,
                                                  gint                position,
                                                  gboolean            push_undo);
void            pika_image_remove_layer          (PikaImage          *image,
                                                  PikaLayer          *layer,
                                                  gboolean            push_undo,
                                                  GList              *new_selected);

void            pika_image_add_layers            (PikaImage          *image,
                                                  GList              *layers,
                                                  PikaLayer          *parent,
                                                  gint                position,
                                                  gint                x,
                                                  gint                y,
                                                  gint                width,
                                                  gint                height,
                                                  const gchar        *undo_desc);

void            pika_image_store_item_set        (PikaImage          *image,
                                                  PikaItemList       *set);
gboolean        pika_image_unlink_item_set       (PikaImage          *image,
                                                  PikaItemList       *set);
GList         * pika_image_get_stored_item_sets   (PikaImage         *image,
                                                   GType              item_type);
void            pika_image_select_item_set       (PikaImage          *image,
                                                  PikaItemList       *set);
void            pika_image_add_item_set          (PikaImage          *image,
                                                  PikaItemList       *set);
void            pika_image_remove_item_set       (PikaImage          *image,
                                                  PikaItemList       *set);
void            pika_image_intersect_item_set    (PikaImage        *image,
                                                  PikaItemList       *set);

gboolean        pika_image_add_channel           (PikaImage          *image,
                                                  PikaChannel        *channel,
                                                  PikaChannel        *parent,
                                                  gint                position,
                                                  gboolean            push_undo);
void            pika_image_remove_channel        (PikaImage          *image,
                                                  PikaChannel        *channel,
                                                  gboolean            push_undo,
                                                  GList              *new_selected);

gboolean        pika_image_add_vectors           (PikaImage          *image,
                                                  PikaVectors        *vectors,
                                                  PikaVectors        *parent,
                                                  gint                position,
                                                  gboolean            push_undo);
void            pika_image_remove_vectors        (PikaImage          *image,
                                                  PikaVectors        *vectors,
                                                  gboolean            push_undo,
                                                  GList              *new_selected);

gboolean        pika_image_add_hidden_item       (PikaImage          *image,
                                                  PikaItem           *item);
void            pika_image_remove_hidden_item    (PikaImage          *image,
                                                  PikaItem           *item);
gboolean        pika_image_is_hidden_item        (PikaImage          *image,
                                                  PikaItem           *item);

gboolean    pika_image_coords_in_active_pickable (PikaImage          *image,
                                                  const PikaCoords   *coords,
                                                  gboolean            show_all,
                                                  gboolean            sample_merged,
                                                  gboolean            selected_only);

void            pika_image_invalidate_previews   (PikaImage          *image);

void            pika_image_set_converting        (PikaImage          *image,
                                                  gboolean            converting);
gboolean        pika_image_get_converting        (PikaImage          *image);


#endif /* __PIKA_IMAGE_H__ */
