/*
 *  $Id: cmap_basicops.c 29793 2026-04-13 17:51:11Z yeti-dn $
 *  Copyright (C) 2021 David Necas (Yeti), Petr Klapetek.
 *  E-mail: yeti@gwyddion.net, klapetek@gwyddion.net.
 *
 *  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 2 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, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include <glib/gi18n-lib.h>
#include <gwy.h>

#define RUN_MODES GWY_RUN_IMMEDIATE

static gboolean module_register  (void);
static void     flip_horizontally(GwyFile *data,
                                  GwyRunModeFlags mode);
static void     flip_vertically  (GwyFile *data,
                                  GwyRunModeFlags mode);
#if 0
static void     flip_diagonally           (GwyFile *data,
                                           GwyRunModeFlags mode);
#endif
static void rotate_clockwise_90       (GwyFile *data,
                                       GwyRunModeFlags mode);
static void rotate_counterclockwise_90(GwyFile *data,
                                       GwyRunModeFlags mode);
static void rotate_180                (GwyFile *data,
                                       GwyRunModeFlags mode);
static void null_offsets              (GwyFile *data,
                                       GwyRunModeFlags mode);
static void remove_segments           (GwyFile *data,
                                       GwyRunModeFlags mode);

static GwyModuleInfo module_info = {
    GWY_MODULE_ABI_VERSION,
    &module_register,
    N_("Basic operations like flipping and rotation by multiples of 90 degrees."),
    "Yeti <yeti@gwyddion.net>",
    "1.0",
    "David Nečas (Yeti) & Petr Klapetek",
    "2021",
};

GWY_MODULE_QUERY2(module_info, cmap_basicops)

static gboolean
module_register(void)
{
    gwy_cmap_func_register("cmap_flip_horizontally",
                           &flip_horizontally,
                           N_("/_Basic Operations/Flip _Horizontally"),
                           GWY_ICON_FLIP_HORIZONTALLY,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Flip data horizontally"));
    gwy_cmap_func_register("cmap_flip_vertically",
                           &flip_vertically,
                           N_("/_Basic Operations/Flip _Vertically"),
                           GWY_ICON_FLIP_VERTICALLY,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Flip data vertically"));
    gwy_cmap_func_register("cmap_rotate_180",
                           &rotate_180,
                           N_("/_Basic Operations/Flip _Both"),
                           GWY_ICON_ROTATE_180,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Flip data both horizontally and vertically"));
#if 0
    gwy_cmap_func_register("cmap_flip_diagonally",
                           &flip_diagonally,
                           N_("/_Basic Operations/Flip Dia_gonally"),
                           GWY_ICON_FLIP_DIAGONALLY,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Flip data diagonally"));
#endif
    gwy_cmap_func_register("cmap_rotate_90_cw",
                           &rotate_clockwise_90,
                           N_("/_Basic Operations/Rotate C_lockwise"),
                           GWY_ICON_ROTATE_90_CW,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Rotate data 90 degrees clockwise"));
    gwy_cmap_func_register("cmap_rotate_90_ccw",
                           &rotate_counterclockwise_90,
                           N_("/_Basic Operations/Rotate _Counterclockwise"),
                           GWY_ICON_ROTATE_90_CCW,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Rotate data 90 degrees counterclockwise"));
    gwy_cmap_func_register("cmap_null_offsets",
                           &null_offsets,
                           N_("/_Basic Operations/_Null Offsets"),
                           GWY_ICON_NULL_OFFSETS,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Null horizontal offsets, moving the origin to the upper left corner"));
    gwy_cmap_func_register("cmap_remove_segments",
                           &remove_segments,
                           N_("/_Basic Operations/Remove _Segments"),
                           NULL,
                           RUN_MODES,
                           GWY_MENU_FLAG_CMAP,
                           N_("Remove curve segmentation"));

    return TRUE;
}

static inline void
basicops_common(GwyFile *data, GwyLawn **lawn, GwyField **field, GQuark *quarks, gint *id)
{
    gwy_data_browser_get_current(GWY_APP_LAWN, lawn,
                                 GWY_APP_LAWN_KEY, quarks + 0,
                                 GWY_APP_LAWN_ID, id,
                                 0);
    quarks[1] = gwy_file_key_cmap_picture(*id);
    *field = gwy_dict_get_object(GWY_DICT(data), quarks[1]);
    gwy_app_undo_qcheckpointv(GWY_DICT(data), 2, quarks);
}

static void
flip_horizontally(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    GwyField *preview;
    GQuark quarks[2];
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    basicops_common(data, &lawn, &preview, quarks, &id);
    gwy_lawn_flip(lawn, TRUE, FALSE);
    gwy_field_flip(preview, TRUE, FALSE);
    gwy_field_data_changed(preview);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
}

static void
flip_vertically(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    GwyField *preview;
    GQuark quarks[2];
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    basicops_common(data, &lawn, &preview, quarks, &id);
    gwy_lawn_flip(lawn, FALSE, TRUE);
    gwy_field_flip(preview, FALSE, TRUE);
    gwy_field_data_changed(preview);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
}

static void
rotate_180(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    GwyField *preview;
    GQuark quarks[2];
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    basicops_common(data, &lawn, &preview, quarks, &id);
    gwy_lawn_flip(lawn, TRUE, TRUE);
    gwy_field_flip(preview, TRUE, TRUE);
    gwy_field_data_changed(preview);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
}

#if 0
static void
flip_diagonally(GwyFile *data, GwyRunModeFlags mode)
{
    GwyField *dfields[3], *newfield;
    GQuark quarks[3];
    gint id, n, i;

    g_return_if_fail(mode & RUN_MODES);
    n = get_fields_and_quarks(dfields, quarks, &id);
    gwy_app_undo_qcheckpointv(GWY_DICT(data), n, quarks);
    for (i = 0; i < n; i++) {
        newfield = gwy_field_new_alike(dfields[i], FALSE);
        gwy_field_transpose(dfields[i], newfield, FALSE);
        gwy_dict_set_object(GWY_DICT(data), quarks[i], newfield);
        g_object_unref(newfield);
    }
    gwy_app_data_clear_selections(data, id);
    gwy_log_add(data, GWY_FILE_IMAGE, id, id);
}
#endif

static void
rotate_clockwise_90(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    GwyField *preview;
    GQuark quarks[2];
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    basicops_common(data, &lawn, &preview, quarks, &id);
    lawn = gwy_lawn_new_rotated_90(lawn, TRUE);
    preview = gwy_field_new_rotated_90(preview, TRUE);
    gwy_dict_set_object(GWY_DICT(data), quarks[0], lawn);
    gwy_dict_set_object(GWY_DICT(data), quarks[1], preview);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
    g_object_unref(lawn);
    g_object_unref(preview);
}

static void
rotate_counterclockwise_90(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    GwyField *preview;
    GQuark quarks[2];
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    basicops_common(data, &lawn, &preview, quarks, &id);
    lawn = gwy_lawn_new_rotated_90(lawn, FALSE);
    preview = gwy_field_new_rotated_90(preview, FALSE);
    gwy_dict_set_object(GWY_DICT(data), quarks[0], lawn);
    gwy_dict_set_object(GWY_DICT(data), quarks[1], preview);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
    g_object_unref(lawn);
    g_object_unref(preview);
}

static void
null_offsets(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    GwyField *preview;
    GQuark quarks[2];
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    basicops_common(data, &lawn, &preview, quarks, &id);
    gwy_lawn_set_xoffset(lawn, 0.0);
    gwy_lawn_set_yoffset(lawn, 0.0);
    gwy_field_set_xoffset(preview, 0.0);
    gwy_field_set_yoffset(preview, 0.0);
    gwy_field_data_changed(preview);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
}

static void
remove_segments(GwyFile *data, GwyRunModeFlags mode)
{
    GwyLawn *lawn;
    gint id;

    g_return_if_fail(mode & RUN_MODES);
    gwy_data_browser_get_current(GWY_APP_LAWN, &lawn,
                                 GWY_APP_LAWN_ID, &id,
                                 0);
    g_return_if_fail(lawn);
    // FIXME: This saves the entire data to undo.
    //gwy_app_undo_qcheckpointv(GWY_DICT(data), 2, quarks);
    gwy_lawn_set_segments(lawn, 0, NULL);
    gwy_lawn_data_changed(lawn);
    gwy_log_add(data, GWY_FILE_CMAP, id, id);
}

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
