'''
    Copyright (C) 2021 - 2024 Akaneyu

    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/>.
'''

import os
import ctypes
import bpy
import bpy.utils.previews
import blf
import numpy as np
from . ui_renderer import UIRenderer as UIRenderer

class Session:
    def __init__(self):
        self.icons = None
        self.ui_renderer = None
        self.draw_handler = None
        self.previous_object = None
        self.brush_position = None
        self.brush_size = 50.0
        self.selecting_direction = False
        self.brush_active = False
        self.resizing_brush = False

def get_session():
    global session

    return session

def draw_handler():
    global session

    context = bpy.context

    wm = context.window_manager
    props = wm.symmetrizetexture_properties
    mirror_axis = props.image_mirror_axis

    info_text = None

    if not session.ui_renderer:
        session.ui_renderer = UIRenderer()

    # direction setup
    if session.selecting_direction:
        if mirror_axis == 'x_axis':
            border_pos1 = context.region.view2d.view_to_region(0.5, 0, clip=False)
            border_pos2 = context.region.view2d.view_to_region(0.5, 1.0, clip=False)
        else:
            border_pos1 = context.region.view2d.view_to_region(0, 0.5, clip=False)
            border_pos2 = context.region.view2d.view_to_region(1.0, 0.5, clip=False)

        session.ui_renderer.render_border(border_pos1, border_pos2)

        center = context.region.view2d.view_to_region(0.5, 0.5, clip=False)

        if mirror_axis == 'x_axis':
            arrow_angle = 0 if session.direction > 0 else np.pi
        else:
            arrow_angle = np.pi / 2.0 if session.direction > 0 else np.pi * 1.5

        session.ui_renderer.render_arrow(center, arrow_angle)

        info_text = "[LMB] Perform  " \
            + "[RMB] Cancel"

    # brush
    if session.brush_active and session.brush_position:
        session.ui_renderer.render_brush_frame(session.brush_position, session.brush_size)

        info_text = "[LMB] Perform  " \
            + "[RMB] Finish  " \
            + "[F] Change brush size"

    area_width, area_height = context.area.width, context.area.height

    # info text
    if info_text:
        ui_scale = context.preferences.system.ui_scale

        session.ui_renderer.render_info_box((0, 0), (area_width, 20 * ui_scale))

        blf.position(0, 8 * ui_scale, 6 * ui_scale, 0)
        blf.size(0, 11 * ui_scale) if bpy.app.version >= (3, 6) \
                else blf.size(0, 11 * ui_scale, 72)
        blf.color(0, 0.7, 0.7, 0.7, 1.0)
        blf.draw(0, info_text)

def load_icons():
    global session

    script_dir = os.path.dirname(os.path.realpath(__file__))
    icons = bpy.utils.previews.new()

    icons_dir = os.path.join(script_dir, "icons")
    for file_name in os.listdir(icons_dir):
        icon_name = os.path.splitext(file_name)[0]
        icons.load(icon_name, os.path.join(icons_dir, file_name), 'IMAGE')

    session.icons = icons

def dispose_icons():
    global session

    bpy.utils.previews.remove(session.icons)

def load_native_library():
    script_dir = os.path.dirname(os.path.realpath(__file__))

    if os.name == 'nt':
        lib_file_name = 'symmetrize_texture.dll'
    else:
        lib_file_name = 'libsymmetrize_texture.so'

    lib = ctypes.CDLL(os.path.join(script_dir, lib_file_name))

    return lib

def unload_native_library(lib):
    if os.name == 'nt':
        kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
        kernel32.FreeLibrary.argtypes = [ctypes.c_void_p]
        kernel32.FreeLibrary(lib._handle)
    else:
        stdlib = ctypes.CDLL("")
        stdlib.dlclose.argtypes = [ctypes.c_void_p]
        stdlib.dlclose(lib._handle)

def get_image_previews(self, context):
    image_previews = []
    for i, img in enumerate(bpy.data.images):
        image_previews.append((img.name, img.name, img.name, bpy.types.UILayout.icon(img), i))            

    return image_previews

class SYMMETRIZE_TEXTURE_PropertyGroup(bpy.types.PropertyGroup):
    image_preview: bpy.props.EnumProperty(items=get_image_previews, options={'LIBRARY_EDITABLE'})

    # created in the register(): image_mirror_axis

    brush_strength: bpy.props.FloatProperty(name='Strength', default=1.0, min=0, max=1.0, precision=3)
    brush_falloff: bpy.props.EnumProperty(items=(
            ('smooth', 'Smooth', 'Smooth', 'SMOOTHCURVE', 0),
            ('constant', 'Constant', 'Constant', 'NOCURVE', 1)))

session = Session()
