# Copyright (C) <2021>  <Reston Stanton>

# ##### BEGIN GPL LICENSE BLOCK #####
#
# 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
# MERCHANTIBILITY 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 <http://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####
import bpy

from ..Shared import modifiers, particles


"""
 █████  █████               █████            █████                █████               ████
░░███  ░░███               ░░███            ░░███                ░░███               ░░███
 ░███   ░███  ████████   ███████   ██████   ███████    ██████     ░███████    ██████  ░███  ████████   ██████  ████████   █████
 ░███   ░███ ░░███░░███ ███░░███  ░░░░░███ ░░░███░    ███░░███    ░███░░███  ███░░███ ░███ ░░███░░███ ███░░███░░███░░███ ███░░
 ░███   ░███  ░███ ░███░███ ░███   ███████   ░███    ░███████     ░███ ░███ ░███████  ░███  ░███ ░███░███████  ░███ ░░░ ░░█████
 ░███   ░███  ░███ ░███░███ ░███  ███░░███   ░███ ███░███░░░      ░███ ░███ ░███░░░   ░███  ░███ ░███░███░░░   ░███      ░░░░███
 ░░████████   ░███████ ░░████████░░████████  ░░█████ ░░██████     ████ █████░░██████  █████ ░███████ ░░██████  █████     ██████
  ░░░░░░░░    ░███░░░   ░░░░░░░░  ░░░░░░░░    ░░░░░   ░░░░░░     ░░░░ ░░░░░  ░░░░░░  ░░░░░  ░███░░░   ░░░░░░  ░░░░░     ░░░░░░
              ░███                                                                          ░███
              █████                                                                         █████
             ░░░░░                                                                         ░░░░░
"""


def change_particle_size(context, domain, kind, size):
    sys = particles.get_sys(domain)
    sim = None
    if kind in particles.sys_name_list:
        for i in sys:
            if kind in i.name:
                sim = i
                break
    else:
        return

    if sim is None:
        return

    if sim.render_type == "OBJECT":
        object = sim.instance_object
        if not object.MantaPro.original_scale:
            object.MantaPro.original_scale = object.scale
            object.MantaPro.new_scale = object.scale

        if (object.scale[0] != object.MantaPro.new_scale[0]) or (object.scale[1] != object.MantaPro.new_scale[1]) or (object.scale[2] != object.MantaPro.new_scale[2]):
            object.MantaPro.original_scale = object.scale

        original_scale = object.MantaPro.original_scale

        object.scale = [original_scale[0] * size,
                        original_scale[1] * size, original_scale[2] * size]
        object.MantaPro.new_scale = object.scale

    if sim.render_type == "COLLECTION":
        coll = sim.instance_collection
        for i in coll.objects:
            object = i

            if not object.MantaPro.original_scale:
                object.MantaPro.original_scale = object.scale
                object.MantaPro.new_scale = object.scale

            if (object.scale[0] != object.MantaPro.new_scale[0]) or (object.scale[1] != object.MantaPro.new_scale[1]) or (object.scale[2] != object.MantaPro.new_scale[2]):
                object.MantaPro.original_scale = object.scale

            original_scale = object.MantaPro.original_scale

            object.scale = [original_scale[0] * size,
                            original_scale[1] * size, original_scale[2] * size]
            object.MantaPro.new_scale = object.scale


"""
 █████  █████               █████            █████
░░███  ░░███               ░░███            ░░███
 ░███   ░███  ████████   ███████   ██████   ███████    ██████
 ░███   ░███ ░░███░░███ ███░░███  ░░░░░███ ░░░███░    ███░░███
 ░███   ░███  ░███ ░███░███ ░███   ███████   ░███    ░███████
 ░███   ░███  ░███ ░███░███ ░███  ███░░███   ░███ ███░███░░░
 ░░████████   ░███████ ░░████████░░████████  ░░█████ ░░██████
  ░░░░░░░░    ░███░░░   ░░░░░░░░  ░░░░░░░░    ░░░░░   ░░░░░░
              ░███
              █████
             ░░░░░
"""

updating = False


def update_flow_type(self, context):

    modifier = modifiers.find_modifier(context.scene.MantaPro.active_flow)
    if modifier:
        modifier_settings = modifier.flow_settings
        modifier_settings.flow_type = self.flow_type


def update_particle_size(self, context):
    domain = context.scene.MantaPro.active_domain
    settings = domain.MantaPro

    size = settings.particle_size
    link = settings.link_particle_size

    spray_size = settings.spray_size
    foam_size = settings.foam_size
    bubble_size = settings.bubble_size
    sprayfoam_size = settings.sprayfoam_size
    spraybubble_size = settings.spraybubble_size
    foambubble_size = settings.foambubble_size
    sprayfoambubble_size = settings.sprayfoambubble_size

    # "SprayFoam", "SprayBubble", "FoamBubble", "SprayFoamBubble"

    if link:
        change_particle_size(context, domain, "Spray", size)
        change_particle_size(context, domain, "Foam", size)
        change_particle_size(context, domain, "Bubble", size)
        change_particle_size(context, domain, "SprayFoam", size)
        change_particle_size(context, domain, "SprayBubble", size)
        change_particle_size(context, domain, "FoamBubble", size)
        change_particle_size(context, domain, "SprayFoamBubble", size)

    else:
        change_particle_size(context, domain, "Spray", spray_size)
        change_particle_size(context, domain, "Foam", foam_size)
        change_particle_size(context, domain, "Bubble", bubble_size)
        change_particle_size(context, domain, "SprayFoam", sprayfoam_size)
        change_particle_size(context, domain, "SprayBubble", spraybubble_size)
        change_particle_size(context, domain, "FoamBubble", foambubble_size)
        change_particle_size(
            context, domain, "SprayFoamBubble", sprayfoambubble_size)


def update_animate_texture(self, context):
    flow = context.scene.MantaPro.active_flow
    speed = self.animate_speed
    frame_start = context.scene.frame_start
    frame_end = context.scene.frame_end

    modifier = modifiers.find_modifier(flow)
    if modifier:
        modifier_settings = modifier.flow_settings

        if self.animate_texture:
            modifier_settings.texture_offset = 0
            modifier_settings.keyframe_insert(
                "texture_offset", frame=frame_start)

            modifier_settings.texture_offset = frame_end * (speed / 100)
            modifier_settings.keyframe_insert(
                "texture_offset", frame=frame_end)

            f_curve = flow.animation_data.action.fcurves.find(
                modifier_settings.path_from_id("texture_offset"))

            for i in f_curve.keyframe_points:
                i.interpolation = "LINEAR"

        else:
            f_curve = flow.animation_data.action.fcurves.find(
                modifier_settings.path_from_id("texture_offset"))
            flow.animation_data.action.fcurves.remove(f_curve)


def update_ember_domain(self, context):
    obj = self.id_data
    force = obj.MantaPro.ember_force_object
    if force:
        force.field.source_object = self.ember_domain


def poll_ember_domain(self, object):
    modifier = modifiers.find_modifier(object)
    if modifier:
        if modifier.fluid_type == "DOMAIN":
            return True
    return False


def ember_use_sub_force(self, context):
    global updating
    if not updating:
        updating = True
        system = particles.find_ember_system(self.id_data)
        settings = system.settings
        force_settings = settings.force_field_1

        if self.ember_use_sub_force:
            force_settings.type = "FORCE"
        else:
            force_settings.type = "NONE"

        updating = False


"""
    ███████    █████          ███                     █████
  ███░░░░░███ ░░███          ░░░                     ░░███
 ███     ░░███ ░███████      █████  ██████   ██████  ███████      ████████  ████████   ██████  ████████   █████
░███      ░███ ░███░░███    ░░███  ███░░███ ███░░███░░░███░      ░░███░░███░░███░░███ ███░░███░░███░░███ ███░░
░███      ░███ ░███ ░███     ░███ ░███████ ░███ ░░░   ░███        ░███ ░███ ░███ ░░░ ░███ ░███ ░███ ░███░░█████
░░███     ███  ░███ ░███     ░███ ░███░░░  ░███  ███  ░███ ███    ░███ ░███ ░███     ░███ ░███ ░███ ░███ ░░░░███
 ░░░███████░   ████████      ░███ ░░██████ ░░██████   ░░█████     ░███████  █████    ░░██████  ░███████  ██████
   ░░░░░░░    ░░░░░░░░       ░███  ░░░░░░   ░░░░░░     ░░░░░      ░███░░░  ░░░░░      ░░░░░░   ░███░░░  ░░░░░░
                         ███ ░███                                 ░███                         ░███
                        ░░██████                                  █████                        █████
                         ░░░░░░                                  ░░░░░                        ░░░░░
"""


class ObjectProps(bpy.types.PropertyGroup):

    particle_collection: bpy.props.PointerProperty(type=bpy.types.Collection)

    # particle size values
    size_max = 100
    size_soft_max = 5
    size_default = 1

    # particle size
    link_particle_size: bpy.props.BoolProperty(
        name="Link particle size", default=True, description="link particle size", update=update_particle_size)

    particle_size: bpy.props.FloatProperty(
        name="Particel size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    spray_size: bpy.props.FloatProperty(
        name="spray size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    foam_size: bpy.props.FloatProperty(
        name="foam size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    bubble_size: bpy.props.FloatProperty(
        name="bubble size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    sprayfoam_size: bpy.props.FloatProperty(
        name="spray+foam size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    spraybubble_size: bpy.props.FloatProperty(
        name="spray+bubble size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    foambubble_size: bpy.props.FloatProperty(
        name="foam+bubble size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    sprayfoambubble_size: bpy.props.FloatProperty(
        name="spray+foam+bubble size", default=size_default, min=0, max=size_max, soft_max=size_soft_max, update=update_particle_size)

    # Other

    moved_cache: bpy.props.BoolProperty(name="moved cache", default=False)

    locked_cache: bpy.props.BoolProperty(
        name="Cache Lock", description="lock the cache to prevent accidental deletion", default=False)

    original_scale: bpy.props.FloatVectorProperty(precision=4)
    new_scale: bpy.props.FloatVectorProperty(precision=4)

    # flow settings
    flow_type: bpy.props.EnumProperty(
        items=[("FIRE", "Fire", "Add fire", 0),
               ("BOTH", "Fire + Smoke", "Add fire and smoke", 1),
               ("SMOKE", "Smoke", "Add smoke", 2)],

        name="Flow Type",
        update=update_flow_type,)

    animate_texture: bpy.props.BoolProperty(
        name="Animate Texture", default=False, description="animate texture using drivers", update=update_animate_texture)

    animate_speed: bpy.props.FloatProperty(
        name="speed", default=0.5, soft_max=1, soft_min=0, precision=5, update=update_animate_texture)

    # ember
    ember_particle_object: bpy.props.PointerProperty(type=bpy.types.Object)
    ember_force_object: bpy.props.PointerProperty(type=bpy.types.Object)

    ember_domain: bpy.props.PointerProperty(
        type=bpy.types.Object, update=update_ember_domain, poll=poll_ember_domain)

    ember_use_sub_force: bpy.props.BoolProperty(
        name="Use Sub Force", default=True, update=ember_use_sub_force)

    # force settings

    force_ember: bpy.props.BoolProperty(default=False)


"""
                              ███           █████
                             ░░░           ░░███
 ████████   ██████   ███████ ████   █████  ███████    ██████  ████████
░░███░░███ ███░░███ ███░░███░░███  ███░░  ░░░███░    ███░░███░░███░░███
 ░███ ░░░ ░███████ ░███ ░███ ░███ ░░█████   ░███    ░███████  ░███ ░░░
 ░███     ░███░░░  ░███ ░███ ░███  ░░░░███  ░███ ███░███░░░   ░███
 █████    ░░██████ ░░███████ █████ ██████   ░░█████ ░░██████  █████
░░░░░      ░░░░░░   ░░░░░███░░░░░ ░░░░░░     ░░░░░   ░░░░░░  ░░░░░
                    ███ ░███
                   ░░██████
                    ░░░░░░
"""

classes = (
    ObjectProps,
)


def register():
    for i in classes:
        bpy.utils.register_class(i)
    bpy.types.Object.MantaPro = bpy.props.PointerProperty(type=ObjectProps)


def unregister():
    for i in classes:
        bpy.utils.unregister_class(i)
    del bpy.types.Object.MantaPro
