'''
Copyright (C) 2019-2023 Dancing Fortune Software All Rights Reserved

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 <http://www.gnu.org/licenses/>.
'''

bl_info = {
    'name': 'Bake Wrangler',
    'description': 'Bake Wrangler aims to improve all baking tasks with a node based interface and provides additional bake passes',
    'author': 'DFS',
    'version': (1, 5, 'b11'),
    'blender': (3, 6, 0),
    'location': 'Editor Type > Bake Node Editor',
    "warning": "Beta Version",
    'doc_url': 'https://bake-wrangler.readthedocs.io',
    "tracker_url": "https://blenderartists.org/t/bake-wrangler-node-based-baking-tool-set/",
    "support": "COMMUNITY",
    'category': 'Baking'}


import bpy
from . import nodes
from . import status_bar


# Preferences
class BakeWrangler_Preferences(bpy.types.AddonPreferences):
    bl_idname = __package__
    
    def update_icon(self, context):
        if not self.show_icon:
            status_bar.status_bar_icon.disable_bw_icon()
        else:
            status_bar.status_bar_icon.ensure_bw_icon()
            
    # Message prefs
    show_icon: bpy.props.BoolProperty(name="Show BW Icon in Status Bar", description="Shows an icon that changes color based on baking state and can be clicked on to bring up the log", default=True, update=update_icon)
    text_msgs: bpy.props.BoolProperty(name="Messages to Text editor", description="Write messages to a text block in addition to the console", default=True)
    clear_msgs: bpy.props.BoolProperty(name="Clear Old Messages", description="Clear the text block before each new bake", default=True)
    wind_msgs: bpy.props.BoolProperty(name="Open Text in new Window", description="A new window will be opened displaying the text block each time a new bake is started", default=False)
    wind_close: bpy.props.BoolProperty(name="Auto Close Text Window", description="Close the text window on successful bake completion", default=False)
    
    # Node prefs
    show_node_prefs: bpy.props.BoolProperty(name="Node Defaults", description="Default general node options", default=False)
    def_filter_mesh: bpy.props.BoolProperty(name="Meshes", description="Show mesh type objects", default=True)
    def_filter_curve: bpy.props.BoolProperty(name="Curves", description="Show curve type objects", default=True)
    def_filter_surface: bpy.props.BoolProperty(name="Surfaces", description="Show surface type objects", default=True)
    def_filter_meta: bpy.props.BoolProperty(name="Metas", description="Show meta type objects", default=True)
    def_filter_font: bpy.props.BoolProperty(name="Fonts", description="Show font type objects", default=True)
    def_filter_light: bpy.props.BoolProperty(name="Lights", description="Show light type objects", default=True)
    def_filter_collection: bpy.props.BoolProperty(name="Collections", description="Toggle only collections", default=False)
    def_show_adv: bpy.props.BoolProperty(name="Expand Advanced Settings", description="Expand advanced settings on node creation instead of starting with them collapsed", default=False)
    invert_bakemod: bpy.props.BoolProperty(name="Invert Selected in Bake Modifiers", description="Inverts the selection method used by the Bake Modifiers option from ignoring viewport hidden modifiers to baking them", default=False)

    # Render prefs
    show_render_prefs: bpy.props.BoolProperty(name="Render Defaults", description="Default settings for rendering options", default=False)
    def_samples: bpy.props.IntProperty(name="Default Bake Samples", description="The number of samples per pixel that new Pass nodes will be set to when created", default=1, min=1)
    def_xres: bpy.props.IntProperty(name="Default Bake X Resolution", description="The X resolution new Pass nodes will be set to when created", default=1024, min=1, subtype='PIXEL')
    def_yres: bpy.props.IntProperty(name="Default Bake Y Resolution", description="The Y resolution new Pass nodes will be set to when created", default=1024, min=1, subtype='PIXEL')
    def_device: bpy.props.EnumProperty(name="Default Device", description="The render device new Pass nodes will be set to when created", items=nodes.node_tree.BakeWrangler_PassSettings.cycles_devices, default='CPU')
    def_raydist: bpy.props.FloatProperty(name="Default Ray Distance", description="The ray distance that new Mesh nodes will use when created", default=0.01, step=1, min=0.0, unit='LENGTH')
    def_max_ray_dist: bpy.props.FloatProperty(name="Default Max Ray Dist", description="The max ray distance that new Mesh nodes will use when created", default=0.0, step=1, min=0.0, unit='LENGTH')
    def_margin: bpy.props.IntProperty(name="Default Margin", description="The margin that new Mesh nodes will use when created", default=0, min=0, subtype='PIXEL')
    def_mask_margin: bpy.props.IntProperty(name="Default Mask Margin", description="The mask margin that new Mesh nodes will use when created", default=0, min=0, subtype='PIXEL')
    ignore_vis: bpy.props.BoolProperty(name="Objects Always Visible", description="Enable to ignore the visibility of selected objects when baking, making them visible regardless of settings in blender", default=False)

    # Ouput prefs
    show_output_prefs: bpy.props.BoolProperty(name="Output Defaults", description="Default settings for output options", default=False)
    def_format: bpy.props.EnumProperty(name="Default Output Format", description="The format new Output nodes will use when created", items=nodes.node_tree.BakeWrangler_OutputSettings.img_format, default='PNG')
    def_xout: bpy.props.IntProperty(name="Default Output X Resolution", description="The X resolution new Output nodes will be set to when created", default=1024, min=1, subtype='PIXEL')
    def_yout: bpy.props.IntProperty(name="Default Output Y Resolution", description="The Y resolution new Output nodes will be set to when created", default=1024, min=1, subtype='PIXEL')
    def_outpath: bpy.props.StringProperty(name="Default Output Path", description="The path new Output nodes will use when created", default="", subtype='DIR_PATH')
    def_outname: bpy.props.StringProperty(name="Default Output Name", description="The name new Output nodes will use when created", default="Image", subtype='FILE_NAME')
    make_dirs: bpy.props.BoolProperty(name="Create Paths", description="If selected path doesn't exist, try to create it", default=False)
    auto_open: bpy.props.BoolProperty(name="Auto open bakes", description="Automatically open the baked image in blender if it isn't already open", default=True)
    save_packed: bpy.props.BoolProperty(name="Save packed images", description="Prior to baking, save any packed images with changes or they will not apply during the bake", default=False)
    save_images: bpy.props.BoolProperty(name="Save unpacked images", description="Prior to baking, save any unpacked images with changes or they will not apply during the bake", default=False)
    img_non_color: bpy.props.EnumProperty(name="Non-Color", description="Color space to use as non-color when alternative color spaces are in use", items=nodes.node_tree.BakeWrangler_OutputSettings.img_color_spaces)
    
    # Performance prefs
    fact_start: bpy.props.BoolProperty(name="Disable Add-ons", description="Disable add-ons in the background baking instance (faster load times and some 3rd party add-ons can crash the process)", default=True)
    retrys: bpy.props.IntProperty(name="Retries", description="On bake failure retry this many times", default=0)
    
    # Dev prefs
    debug: bpy.props.BoolProperty(name="Debug", description="Enable additional debugging output", default=False)

    def draw(self, context):
        layout = self.layout
        colprefs = layout.column(align=False)

        coltext = colprefs.column(align=False)
        coltext.prop(self, "show_icon")
        coltext.prop(self, "text_msgs")
        if self.text_msgs:
            box = coltext.box()
            box.prop(self, "clear_msgs")
            box.prop(self, "wind_msgs")
            row = box.row(align=True)
            row.label(icon='THREE_DOTS')
            row.prop(self, "wind_close")
            if self.wind_msgs:
                row.enabled = True
            else:
                row.enabled = False

        # Node prefs
        box = colprefs.box()
        if not self.show_node_prefs:
            box.prop(self, "show_node_prefs", icon="DISCLOSURE_TRI_RIGHT", emboss=False)
        else:
            box.prop(self, "show_node_prefs", icon="DISCLOSURE_TRI_DOWN", emboss=False)
            col = box.column(align=False)
            row = col.row(align=True)
            row.alignment = 'LEFT'
            row.label(text="Filter:")
            row1 = row.row(align=True)
            row1.alignment = 'LEFT'
            row1.prop(self, "def_filter_mesh", text="", icon='MESH_DATA')
            row1.prop(self, "def_filter_curve", text="", icon='CURVE_DATA')
            row1.prop(self, "def_filter_surface", text="", icon='SURFACE_DATA')
            row1.prop(self, "def_filter_meta", text="", icon='META_DATA')
            row1.prop(self, "def_filter_font", text="", icon='FONT_DATA')
            row1.prop(self, "def_filter_light", text="", icon='LIGHT_DATA')
            if self.def_filter_collection:
                row1.enabled = False
            row2 = row.row(align=False)
            row2.alignment = 'LEFT'
            row2.prop(self, "def_filter_collection", text="", icon='GROUP')
            col.prop(self, "def_show_adv")
            col.prop(self, "invert_bakemod")

        # Render prefs
        box = colprefs.box()
        if not self.show_render_prefs:
            box.prop(self, "show_render_prefs", icon="DISCLOSURE_TRI_RIGHT", emboss=False)
        else:
            box.prop(self, "show_render_prefs", icon="DISCLOSURE_TRI_DOWN", emboss=False)
            col = box.column(align=False)
            col.prop(self, "def_samples", text="Samples")
            col1 = col.column(align=True)
            col1.prop(self, "def_xres", text="X")
            col1.prop(self, "def_yres", text="Y")
            col.prop(self, "def_device", text="Device")
            col.prop(self, "def_margin", text="Margin")
            col.prop(self, "def_mask_margin", text="Mask Margin")
            col.prop(self, "def_raydist", text="Ray Distance")
            col.prop(self, "def_max_ray_dist", text="Max Ray Dist")
            col.prop(self, "ignore_vis")

        # Output prefs
        box = colprefs.box()
        if not self.show_output_prefs:
            box.prop(self, "show_output_prefs", icon="DISCLOSURE_TRI_RIGHT", emboss=False)
        else:
            box.prop(self, "show_output_prefs", icon="DISCLOSURE_TRI_DOWN", emboss=False)
            col = box.column(align=False)
            col.prop(self, "def_format", text="Format")
            col1 = col.column(align=True)
            col1.prop(self, "def_xout", text="X")
            col1.prop(self, "def_yout", text="Y")
            col2 = col.column(align=True)
            col2.prop(self, "def_outpath", text="Image Path")
            col2.prop(self, "def_outname", text="Image Name")
            col.prop(self, "make_dirs")
            col.prop(self, "auto_open")

        # Dev prefs
        col = colprefs.column(align=True)
        col.prop(self, "fact_start")
        col.prop(self, "save_packed")
        col.prop(self, "save_images")
        col.prop(self, "retrys")
        if 'Non-Color' not in bpy.types.ColorManagedInputColorspaceSettings.bl_rna.properties['name'].enum_items.keys():
            col.prop(self, "img_non_color")
        col.prop(self, "debug")



def register():
    from bpy.utils import register_class
    register_class(BakeWrangler_Preferences)
    # Add status property to the window manager
    bpy.types.WindowManager.bw_status = bpy.props.IntProperty(name="Bake Wrangler Status", default=0)
    bpy.types.WindowManager.bw_lastlog = bpy.props.StringProperty(name="Bake Wangler Log", default="")
    bpy.types.WindowManager.bw_lastfile = bpy.props.StringProperty(name="Bake Wangler Temp Blend", default="")
    nodes.register()
    status_bar.register()


def unregister():
    from bpy.utils import unregister_class
    nodes.unregister()
    status_bar.unregister()
    unregister_class(BakeWrangler_Preferences)
    # Remove status property from window manager
    delattr(bpy.types.WindowManager, 'bw_status')
