#!/usr/pkg/bin/python3.11
#   Copyright (C) 1997  James Henstridge <james@daa.com.au>
#
#   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/>.

import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
gi.require_version('GimpUi', '3.0')
from gi.repository import GimpUi
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
import time
import sys

def N_(message): return message
def _(message): return GLib.dgettext(None, message)

_color = Gimp.RGB()
_color.set_uchar(240, 0, 0)
_color.set_alpha(1.0)

def foggify(procedure, run_mode, image, n_drawables, drawables, config, data):
    # Work around not being able to set default color by only setting it
    # when color in our config is None. This won't help when resetting to
    # factory default. This also fixes a critical when running without
    # changing the color away from None.
    color = config.get_property('color')
    if color is None:
        config.set_property('color', _color)

    if run_mode == Gimp.RunMode.INTERACTIVE:
        GimpUi.init('python-fu-foggify')
        dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config)
        dialog.fill(None)
        if not dialog.run():
            dialog.destroy()
            return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, GLib.Error())
        else:
            dialog.destroy()

    color      = config.get_property('color')
    name       = config.get_property('name')
    turbulence = config.get_property('turbulence')
    opacity    = config.get_property('opacity')

    Gimp.context_push()
    image.undo_group_start()

    if image.get_base_type() is Gimp.ImageBaseType.RGB:
        type = Gimp.ImageType.RGBA_IMAGE
    else:
        type = Gimp.ImageType.GRAYA_IMAGE
    for drawable in drawables:
        fog = Gimp.Layer.new(image, name,
                             drawable.get_width(), drawable.get_height(),
                             type, opacity,
                             Gimp.LayerMode.NORMAL)
        fog.fill(Gimp.FillType.TRANSPARENT)
        image.insert_layer(fog, drawable.get_parent(),
                           image.get_item_position(drawable))

        Gimp.context_set_background(color)
        fog.edit_fill(Gimp.FillType.BACKGROUND)

        # create a layer mask for the new layer
        mask = fog.create_mask(0)
        fog.add_mask(mask)

        # add some clouds to the layer
        pdb_proc   = Gimp.get_pdb().lookup_procedure('plug-in-plasma')
        pdb_config = pdb_proc.create_config()
        pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE)
        pdb_config.set_property('image', image)
        pdb_config.set_property('drawable', mask)
        pdb_config.set_property('seed', int(time.time()))
        pdb_config.set_property('turbulence', turbulence)
        pdb_proc.run(pdb_config)

        # apply the clouds to the layer
        fog.remove_mask(Gimp.MaskApplyMode.APPLY)
        fog.set_visible(True)

    Gimp.displays_flush()

    image.undo_group_end()
    Gimp.context_pop()

    return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())

class Foggify (Gimp.PlugIn):
    ## Parameters ##
    __gproperties__ = {
        "name": (str,
                 _("Layer _name"),
                 _("Layer name"),
                 _("Clouds"),
                 GObject.ParamFlags.READWRITE),
        "turbulence": (float,
                       _("_Turbulence"),
                       _("Turbulence"),
                       0.0, 7.0, 1.0,
                       GObject.ParamFlags.READWRITE),
        "opacity": (float,
                    _("O_pacity"),
                    _("Opacity"),
                    0.0, 100.0, 100.0,
                    GObject.ParamFlags.READWRITE),
    }
    # I use a different syntax for this property because I think it is
    # supposed to allow setting a default, except it doesn't seem to
    # work. I still leave it this way for now until we figure this out
    # as it should be the better syntax.
    color = GObject.Property(type =Gimp.RGB, default=_color,
                             nick =_("_Fog color"),
                             blurb=_("Fog color"))

    ## GimpPlugIn virtual methods ##
    def do_set_i18n(self, procname):
        return True, 'gimp30-python', None

    def do_query_procedures(self):
        return [ 'python-fu-foggify' ]

    def do_create_procedure(self, name):
        procedure = Gimp.ImageProcedure.new(self, name,
                                            Gimp.PDBProcType.PLUGIN,
                                            foggify, None)
        procedure.set_image_types("RGB*, GRAY*");
        procedure.set_sensitivity_mask (Gimp.ProcedureSensitivityMask.DRAWABLE |
                                        Gimp.ProcedureSensitivityMask.DRAWABLES)
        procedure.set_documentation (_("Add a layer of fog"),
                                     _("Adds a layer of fog to the image."),
                                     name)
        procedure.set_menu_label(_("_Fog..."))
        procedure.set_attribution("James Henstridge",
                                  "James Henstridge",
                                  "1999,2007")
        procedure.add_menu_path ("<Image>/Filters/Decor")

        procedure.add_argument_from_property(self, "name")
        procedure.add_argument_from_property(self, "color")
        procedure.add_argument_from_property(self, "turbulence")
        procedure.add_argument_from_property(self, "opacity")
        return procedure

Gimp.main(Foggify.__gtype__, sys.argv)
