# 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


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

updating = False


def update_domains_index(self, context):
    # handle no objects
    if len(self.domains.keys()) < 1:
        return

    # make sure index is not to large
    index = self.domains_index
    while len(self.domains) <= index:
        if index == -1:
            break
        index -= 1

    # set active domain
    item = self.domains[index]
    self.active_domain = item.obj


def update_flows_index(self, context):
    # handle no objects
    if len(self.flows.keys()) < 1:
        return

    # make sure index is not to large
    index = self.flows_index
    while len(self.flows) <= index:
        if index == -1:
            break
        index -= 1

    # set active flow
    item = self.flows[index]
    self.active_flow = item.obj


def update_effectors_index(self, context):
    # handle no objects
    if len(self.effectors.keys()) < 1:
        return

    # make sure index is not to large
    index = self.effectors_index
    while len(self.effectors) <= index:
        if index == -1:
            break
        index -= 1

    # set active effector
    item = self.effectors[index]
    self.active_effector = item.obj


def update_forces_index(self, context):
    # handle no objects
    if len(self.forces.keys()) < 1:
        return

    # make sure index is not to large
    index = self.forces_index
    while len(self.forces) <= index:
        if index == -1:
            break
        index -= 1

    # set active force
    item = self.forces[index]
    self.active_force = item.obj


def update_auto_ops(self, context):
    if self.auto_ops:
        bpy.ops.mantapro.auto_ops("INVOKE_DEFAULT")


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


class MantaProDomains(bpy.types.PropertyGroup):
    obj: bpy.props.PointerProperty(
        type=bpy.types.Object,)
    name: bpy.props.StringProperty(
        name="Name", subtype='NONE', default="default name")
    index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0)


class MantaProFlows(bpy.types.PropertyGroup):
    obj: bpy.props.PointerProperty(
        type=bpy.types.Object,)
    name: bpy.props.StringProperty(
        name="Name", subtype='NONE', default="default name")
    index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0)


class MantaProEffectors(bpy.types.PropertyGroup):
    obj: bpy.props.PointerProperty(
        type=bpy.types.Object,)
    name: bpy.props.StringProperty(
        name="Name", subtype='NONE', default="default name")
    index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0)


class MantaProForces(bpy.types.PropertyGroup):
    obj: bpy.props.PointerProperty(
        type=bpy.types.Object,)
    name: bpy.props.StringProperty(
        name="Name", subtype='NONE', default="default name")
    index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0)


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


class SelectionProps(bpy.types.PropertyGroup):
    v_domain: bpy.props.PointerProperty(
        name="v_domain", type=bpy.types.Object)
    v_flow: bpy.props.PointerProperty(
        name="v_flow", type=bpy.types.Object)
    v_effector: bpy.props.PointerProperty(
        name="v_effector", type=bpy.types.Object)
    v_force: bpy.props.PointerProperty(
        name="v_force", type=bpy.types.Object)


class AutoOps(bpy.types.PropertyGroup):
    auto_find: bpy.props.BoolProperty(
        name="Use Auto Find", description="automatically find all fluid sim objects in the scene", default=True)
    auto_remove: bpy.props.BoolProperty(
        name="Use Auto Remove", description="automatically remove any object form the lists if it is not in the scene", default=True)
    auto_v_selection: bpy.props.BoolProperty(name="Sync Viewport Selection to Lists",
                                             description="selected objects from the viewport get selected in the lists ", default=False)

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


class Dev(bpy.types.PropertyGroup):
    show_panel_id: bpy.props.BoolProperty(default=False)

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


class SceneProps(bpy.types.PropertyGroup):
    active_domain: bpy.props.PointerProperty(
        name="domain", type=bpy.types.Object)
    active_flow: bpy.props.PointerProperty(
        name="flow", type=bpy.types.Object)
    active_effector: bpy.props.PointerProperty(
        name="effector", type=bpy.types.Object)
    active_force: bpy.props.PointerProperty(
        name="force", type=bpy.types.Object)

    domains: bpy.props.CollectionProperty(type=MantaProDomains)
    flows: bpy.props.CollectionProperty(type=MantaProFlows)
    effectors: bpy.props.CollectionProperty(type=MantaProEffectors)
    forces: bpy.props.CollectionProperty(type=MantaProForces)

    selection: bpy.props.PointerProperty(type=SelectionProps)

    domains_index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0, update=update_domains_index)
    flows_index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0, update=update_flows_index)
    effectors_index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0, update=update_effectors_index)
    forces_index: bpy.props.IntProperty(
        name="Index", subtype='NONE', default=0, min=0, update=update_forces_index)

    auto_ops: bpy.props.BoolProperty(
        name="Use Auto Operations", description="use auto operations that auto find new objects and remove deleted objects", default=False, update=update_auto_ops)

    auto_ops_settings: bpy.props.PointerProperty(type=AutoOps)

    DEV: bpy.props.PointerProperty(type=Dev)

    # quick setup save
    quick_setup_save_collection: bpy.props.PointerProperty(
        name="Collection", type=bpy.types.Collection,
        description="The collection that contains all the objects and collections to be saved as a preset")

    quick_setup_save_category: bpy.props.EnumProperty(
        items=[("LIQUID", "Liquid", "Liquid Category", 0),
               ("GAS", "Gas", "Gas Category", 1),
               ("OTHER", "Other", "Other Category", 2)],
        default="OTHER",
        name="Category",
        description="The category that the preset will be displayed under \n (if not OTHER it adds an '_CATEGORY' to the end of the collection name)")

    quick_setup_save_index: bpy.props.IntProperty(
        name="Index", default=4, min=0, max=999,
        description="Index for the showing the preset in lists (higher numbers are placed lower) \n (if two presets have the same index, they are sorted alphabetically)")

    quick_setup_save_name: bpy.props.StringProperty(
        name="Name", default="Preset", description="The name for the preset")


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

classes = (
    MantaProDomains,
    MantaProFlows,
    MantaProEffectors,
    MantaProForces,

    SelectionProps,
    AutoOps,
    Dev,

    SceneProps,
)


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


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