# -*- coding: utf-8 -*-

import bpy
import bgl
import blf
import sys
import os
import math

from . sun_calc import degToRad, radToDeg, format_hms
from . properties import Display, Sun

# ---------------------------------------------------------------------------


class HdrObject:

    class Origin:
        x = 0
        y = 0

    def __init__(self, t, w, h):
        self.type = t
        self.width = w
        self.height = h
        self.heightFactor = .50
        self.opacity = 1.0
        self.focused = False
        self.view3d_area = None
        self.origin = self.Origin()

    def set_dimensions(self, width):
        self.width = width
        self.height = int(width * self.heightFactor)

    def check_focus(self, context, event):
        self.focused = self.is_focused(context, event)
        return self.focused

    def is_focused(self, context, event):
        if context.area != self.view3d_area:
            return False

        x = event.mouse_region_x
        y = event.mouse_region_y

        for reg in self.view3d_area.regions:
            if reg.type == 'WINDOW':
                if x < 0 or x > reg.width:
                    return False
                else:
                    break

        if x < self.origin.x or x > (self.origin.x + self.width) or \
                y < self.origin.y or y > (self.origin.y + self.height) or \
                y < 0 or y > reg.height:
            return False
        return True

    def near_border(self, context, event):
        if context.area != self.view3d_area:
            return False

        x = event.mouse_region_x
        y = event.mouse_region_y

        for reg in self.view3d_area.regions:
            if reg.type == 'WINDOW':
                if x < 20 or x > (reg.width - 20) or \
                        y < 20 or y > (reg.height - 20):
                    return True
                else:
                    break
        return False


# ---------------------------------------------------------------------------


class HdrClass:

    class mouse:
        pass

    class grab:

        class spot:
            pass

        class offset:
            pass

    class zoom:
        pass

    class image:
        pass

    class last:
        pass

    def __init__(self):
        self.handler1 = None
        self.handler2 = None
        self.view3d_area = None
        self.draw_region = None
        self.glImage = None
        self.init_zoom_preference = True
        self.reset()
        self.last.filename = None
        self.last.image = None
        self.last.pixels = None
        self.last.projection = None

    def init(self):
        self.object = [HdrObject('MAP', 0, 0), HdrObject('TEXT', 100, 160)]
        self.object[0].set_dimensions(200)
        self.object[1].origin.x = 10
        self.object[1].origin.y = 80

    def zoom_preferences(self, invert_zoom_wheel, invert_mouse_zoom):
        self.init_zoom_preference = False
        if invert_zoom_wheel:
            self.zoom.wheel_up = 'OUT'
            self.zoom.wheel_down = 'IN'
        else:
            self.zoom.wheel_up = 'IN'
            self.zoom.wheel_down = 'OUT'
        if invert_mouse_zoom:
            self.zoom.mouse_up = 'IN'
            self.zoom.mouse_down = 'OUT'
        else:
            self.zoom.mouse_up = 'OUT'
            self.zoom.mouse_down = 'IN'

    def reset(self):
        self.init()
        self.action = None
        self.isActive = False
        self.start = False
        self.stop = False
        self.lockCrosshair = True
        self.elevation = 0.0
        self.azimuth = 0.0
        self.ctrlPress = False
        self.altPress = False
        self.mouse.x = 0
        self.mouse.y = 0
        self.grab.spot.x = 0
        self.grab.spot.y = 0
        self.grab.offset.x = 0
        self.grab.offset.y = 0
        self.zoom.width = 0
        self.zoom.x = 0
        self.zoom.y = 0
        self.image.name = None
        self.image.bindcode = 0
        self.image.loaded = False
        self.image.free_it = False

    def clear_callbacks(self):
        if self.handler2 is not None:
            bpy.types.SpaceView3D.draw_handler_remove(self.handler2, 'WINDOW')
            self.handler2 = None
        if self.handler1 is not None:
            bpy.types.SpaceView3D.draw_handler_remove(self.handler1, 'WINDOW')
            self.handler1 = None

    def set_view3d_area(self, area):
        for obj in self.object:
            obj.view3d_area = area

    def activate(self, context):
        if context.area.type == 'PROPERTIES':
            self.reset()

            def fw(self, context):
                self.draw_region = context.region
                areas = bpy.context.screen.areas
                for area in areas:
                    if area.type == 'VIEW_3D':
                        self.view3d_area = context.area
                        for reg in area.regions:
                            if reg.type == 'WINDOW':
                                self.draw_region = reg
                                Display.refresh()
                                return True
                return False
            if not fw(self, context):
                self.draw_region = context.region

            self.set_view3d_area(self.view3d_area)
            self.start = True
            self.handler1 = bpy.types.SpaceView3D.draw_handler_add(
                Hdr_load_callback,
                (self, context), 'WINDOW', 'POST_PIXEL')
            self.isActive = True
            return True
        else:
            return False

    def activateBGLcallback(self, context):
        self.handler2 = bpy.types.SpaceView3D.draw_handler_add(
            Draw_hdr_callback, (self, context), 'WINDOW', 'POST_PIXEL')
        self.view3d_area = context.area
        self.set_view3d_area(self.view3d_area)
        bpy.ops.sunpos.hdr('INVOKE_DEFAULT')

    def deactivate(self):
        self.clear_callbacks()
        self.stop = False
        self.action = None
        self.image.loaded = False
        if self.glImage is not None:
            try:
                if self.glImage.bindcode == self.image.bindcode:
                    self.glImage.gl_free()
                    bpy.data.images.remove(self.glImage)
            except:
                pass
        self.image.free_it = False
        self.glImage = None
        self.image.bindcode = 0
        self.isActive = False
        if Sun.SP:
            Sun.SP.ShowHdr = False
            Sun.SP.BindToSun = True
        Sun.BindToSun = False
        Display.refresh()

    def make_dummy_file(self, file_name):
        fname = file_name.replace("\\", "/")
        if os.path.exists(fname):
            return False
        else:
            return True

    def load_blender_image(self, file_name):
        fn = file_name
        self.image.name = fn.replace("\\", "/")
        if os.path.exists(self.image.name):
            try:
                self.glImage = bpy.data.images.load(self.image.name)
                self.glImage.pixels = self.last.pixels
                if self.glImage is not None:
                    self.image.loaded = True
                    self.glImage.user_clear()
                    self.object[0].heightFactor = \
                        self.glImage.size[1] / self.glImage.size[0]
                    return True
                else:
                    return False
            except:
                pass
        return False

    def load_gl_image(self):
        for i in range(1, 6):  # Make up to 6 tries to load image
            self.glImage.gl_load(bgl.GL_NEAREST, bgl.GL_NEAREST)
            if self.glImage.bindcode != 0:
                self.image.bindcode = self.glImage.bindcode
                return True
        return False

    def locked_crosshair_event(self, action, event):
        self.mouse.x = event.mouse_region_x
        self.mouse.y = event.mouse_region_y
        self.grab.offset.x = event.mouse_region_x
        self.grab.offset.y = event.mouse_region_y
        self.lockCrosshair = True
        Display.refresh()
        return Hdr_function[action](event)

    # -----------------------------------------------------------------------

    def event_controller(self, context, event):

        if not Sun.SP.ShowHdr or event.type == 'TIMER':
            return {'PASS_THROUGH'}

        hdrInFocus = self.object[0].check_focus(context, event)

        if event.type == 'MOUSEMOVE':
            if self.action == None:
                if hdrInFocus:
                    if self.object[0].near_border(context, event):
                        return {'PASS_THROUGH'}
                    else:
                        return {'RUNNING_MODAL'}
                else:
                    return {'PASS_THROUGH'}
            if self.action in ('PAN', 'ZOOM', 'G'):
                return self.locked_crosshair_event(self.action, event)

        if event.type in ('LEFT_CTRL', 'LEFT_ALT', 'RIGHT_CTRL', 'RIGHT_ALT'):
            Key_function[event.type](event)
            return {'RUNNING_MODAL'}

        self.object[1].check_focus(context, event)

        if event.type in ('MIDDLEMOUSE', 'LEFTMOUSE', 'G'):
            val = Key_function[event.type](context, event)
            if val:
                return val
        elif event.type in ('RIGHTMOUSE', 'ESC', 'H', 'F1'):
            Display.refresh()
            return Key_function[event.type](event)

        if self.action in ('PAN', 'ZOOM', 'G'):
            return self.locked_crosshair_event(self.action, event)

        if not hdrInFocus:
            return {'PASS_THROUGH'}

        self.mouse.x = event.mouse_region_x
        self.mouse.y = event.mouse_region_y

        if event.type == 'WHEELUPMOUSE':
            wheel_zoom(self.zoom.wheel_up)
        elif event.type == 'WHEELDOWNMOUSE':
            wheel_zoom(self.zoom.wheel_down)
        elif self.action == 'CROSS':
            self.lockCrosshair = False
            Display.refresh()

        return {'RUNNING_MODAL'}

# ---------------------------------------------------------------------------


Hdr = HdrClass()


# ---------------------------------------------------------------------------


def key_Ctrl(event):
    if event.value == 'PRESS':
        Hdr.ctrlPress = True
    elif event.value == 'RELEASE':
        Hdr.ctrlPress = False


def key_Alt(event):
    if event.value == 'PRESS':
        Hdr.altPress = True
    elif event.value == 'RELEASE':
        Hdr.altPress = False


def key_Esc(event):
    if Hdr.object[0].focused:
        if Hdr.action is None:
            Hdr.stop = True
            return {'FINISHED'}
    if Hdr.action is not None:
        if event.value == 'RELEASE':
            Hdr.action = None
        return {'RUNNING_MODAL'}
    return {'PASS_THROUGH'}


def key_LeftMouse(context, event):
    if event.value == 'PRESS':
        if Hdr.action is not None:
            Hdr.action = None
            Display.refresh()
            return {'RUNNING_MODAL'}
        elif Hdr.object[0].focused:
            if Hdr.object[0].near_border(context, event):
                Hdr.action = 'BORDER'
                Hdr.lockCrosshair = True
                return {'PASS_THROUGH'}
            Hdr.action = 'CROSS'
            Hdr.lockCrosshair = False
            Display.refresh()
        else:
            return {'PASS_THROUGH'}
    elif event.value == 'RELEASE':
        Hdr.lockCrosshair = True
        Hdr.action = None
        Display.refresh()
        return {'PASS_THROUGH'}

    return False


def key_MiddleMouse(context, event):
    if event.value == 'PRESS':
        if Hdr.object[0].focused:
            if Hdr.ctrlPress:
                hdr = Hdr.object[0]
                Hdr.action = 'ZOOM'
                Hdr.zoom.width = hdr.width
                Hdr.zoom.x = hdr.origin.x
                Hdr.zoom.y = hdr.origin.y
            else:
                Hdr.action = 'PAN' if Hdr.action != 'PAN' else None
            Hdr.grab.spot.x = event.mouse_region_x
            Hdr.grab.spot.y = event.mouse_region_y
            return False
        else:
            return {'PASS_THROUGH'}
    elif event.value == 'RELEASE':
        Hdr.action = None
        Hdr.object[0].focused = False
        Hdr.object[1].focused = False
        Display.refresh()
    return {'RUNNING_MODAL'}

# ---------------------------------------------------------------------------


def key_G(context, event):
    if event.value == 'PRESS':
        if Hdr.object[0].focused:
            Hdr.action = 'PAN' if Hdr.action != 'PAN' else None
            Hdr.grab.spot.x = event.mouse_region_x
            Hdr.grab.spot.y = event.mouse_region_y
            return False
        else:
            return {'PASS_THROUGH'}
    return {'RUNNING_MODAL'}


def key_H(event):
    if event.value == 'PRESS':
        if Hdr.object[0].focused:
            Hdr.action = None
            bpy.ops.object.hdrhelp_operator('INVOKE_DEFAULT')
    return {'RUNNING_MODAL'}


# ---------------------------------------------------------------------------

def hdr_Pan(event):
    return {'RUNNING_MODAL'}


def hdr_Zoom(event):
    mouse_zoom()
    return {'RUNNING_MODAL'}


def hdr_G(event):
    if Hdr.grab.offset.x < Hdr.grab.spot.x:
        off = Hdr.grab.spot.x - Hdr.grab.offset.x
        Hdr.object[1].origin.x -= off
    else:
        off = Hdr.grab.offset.x - Hdr.grab.spot.x
        Hdr.object[1].origin.x += off
    if Hdr.grab.offset.y < Hdr.grab.spot.y:
        off = Hdr.grab.spot.y - Hdr.grab.offset.y
        Hdr.object[1].origin.y -= off
    else:
        off = Hdr.grab.offset.y - Hdr.grab.spot.y
        Hdr.object[1].origin.y += off

    Hdr.grab.spot.x = Hdr.mouse.x
    Hdr.grab.spot.y = Hdr.mouse.y

    return {'RUNNING_MODAL'}


############################################################################

Key_function = dict([('LEFT_CTRL', key_Ctrl), ('LEFT_ALT', key_Alt),
                     ('RIGHT_CTRL', key_Ctrl), ('RIGHT_ALT', key_Alt),
                     ('MIDDLEMOUSE', key_MiddleMouse),
                     ('LEFTMOUSE', key_LeftMouse),
                     ('RIGHTMOUSE', key_Esc), ('ESC', key_Esc),
                     ('G', key_G), ('H', key_H), ('F1', key_H)])

# ---------------------------------------------------------------------------

Hdr_function = dict([('PAN', hdr_Pan), ('ZOOM', hdr_Zoom),
                     ('G', hdr_G)])

############################################################################


def wheel_zoom(action):
    mf = 0.2 if Hdr.ctrlPress else 0.0
    af = 0.07 if Hdr.altPress else 0.0
    if action == 'IN':
        scale = 1.10 + mf - af
    else:
        scale = .90 - mf + af
    if Hdr.object[0].width * scale < 50:
        return
    else:
        Hdr.object[0].set_dimensions(int(int(Hdr.object[0].width * scale)))
    x = Hdr.mouse.x - Hdr.object[0].origin.x
    y = Hdr.mouse.y - Hdr.object[0].origin.y
    Hdr.object[0].origin.x += x - int(x * scale)
    Hdr.object[0].origin.y += y - int(y * scale)
    Hdr.lockCrosshair = True
    Display.refresh()


def mouse_zoom():
    if Hdr.mouse.y > Hdr.grab.spot.y:
        s = Hdr.mouse.y - Hdr.grab.spot.y
        action = Hdr.zoom.mouse_up
    elif Hdr.mouse.y < Hdr.grab.spot.y:
        s = Hdr.grab.spot.y - Hdr.mouse.y
        action = Hdr.zoom.mouse_down
    else:
        s = 0
        action = Hdr.zoom.mouse_down

    if action == 'IN':
        scale = 1 + s * .01
    else:
        scale = 1 - s * .006

    w = int(Hdr.zoom.width * scale)
    if w < 50:
        return
    Hdr.object[0].set_dimensions(w)
    x = Hdr.grab.spot.x - Hdr.zoom.x
    y = Hdr.grab.spot.y - Hdr.zoom.y
    Hdr.object[0].origin.x = x - int(x * scale) + Hdr.zoom.x
    Hdr.object[0].origin.y = y - int(y * scale) + Hdr.zoom.y


# --------------------------------------------------------------------------


############################################################################


def Hdr_load_callback(self, context):

    def remove_imagedata(name):
        bd = bpy.data
        for i in bd.images:
            if i.name == name:
                bd.images.remove(i)

    if Sun.SP.ShowHdr and not Hdr.image.loaded:
        Hdr.glImage = None
        fileName = None
        projection = "EQUIRECTANGULAR"
        try:
            nt = bpy.context.scene.world.node_tree.nodes
            envTex = nt.get(Sun.HDR_texture)
            if envTex.type != "TEX_ENVIRONMENT":
                Sun.SP.ShowHdr = False
            elif envTex.image == None:
                Sun.SP.ShowHdr = False
            else:
                envTex.texture_mapping.rotation.z = 0.0
                projection = envTex.projection
                prefs = bpy.context.preferences
                fileName = prefs.filepaths.temporary_directory + "tmpSun.png"

                st = envTex.image.copy()
                if projection == "MIRROR_BALL":
                    st.scale(256, 256)
                    Hdr.last.image = st.copy()
                    Hdr.last.image.scale(512, 256)
                    ConvertToLatLong(st, Hdr.last.image)
                else:
                    st.scale(512, 256)
                    Hdr.last.image = st.copy()
                    Hdr.last.image.scale(512, 256)

                if Hdr.make_dummy_file(fileName) == True:
                    Hdr.last.image.save_render(fileName)
                Hdr.last.pixels = list(Hdr.last.image.pixels)
        except:
            pass

        if Sun.SP.ShowHdr:
            if not Hdr.load_blender_image(fileName):
                print("Could not load image file: ", Hdr.image.name)
                Sun.SP.ShowHdr = False
            else:
                try:
                    nt = bpy.context.scene.world.node_tree.nodes
                    envTex = nt.get(Sun.HDR_texture)
                    if projection == "MIRROR_BALL":
                        envTex.texture_mapping.rotation.z = degToRad(270.0)
                    else:
                        envTex.texture_mapping.rotation.z = degToRad(90.0)
                except:
                    pass

    if Hdr.start:
        def set_region_data():
            Hdr.activateBGLcallback(context)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            Hdr.object[0].set_dimensions(0)
            Hdr.toolProps = None
            Hdr.toolPropsWidth = 0
            for reg in Hdr.view3d_area.regions:
                if reg.type == 'TOOL_PROPS':
                    Hdr.toolProps = reg
                    Hdr.toolProps_width = reg.width
                elif reg.type == 'WINDOW':
                    Hdr.region = reg
                    Hdr.saved_region_width = reg.width
                    Hdr.object[0].set_dimensions(int(reg.width * .5))
                    Hdr.object[0].origin.x = \
                        int((Hdr.region.width - Hdr.object[0].width) / 2)
                    Hdr.object[0].origin.y = 2
            return

        Hdr.start = False
        if Hdr.image.loaded:
            if not Hdr.load_gl_image():
                print("Could not load image file: ", Hdr.image.name)
            elif Hdr.glImage.bindcode != 0:
                Hdr.image.free_it = True
                set_region_data()
                return
            print("Could not get texture in gl_load()")
            Hdr.glImage = None
            Hdr.image.bindcode = 0
            Sun.SP.ShowHdr = False
        else:
            Sun.SP.ShowHdr = False
        return

    if Hdr.stop:
        Hdr.deactivate()
        return

    return


############################################################################
# Thanks to Domino for the Pixel and ImageBuffer classes
############################################################################


class Pixel:

    def __init__(self, r=0.0, g=0.0, b=0.0, a=None, colour=None):
        self.r = r
        self.g = g
        self.b = b
        self.a = a
        if colour:
            self.r = colour[0]
            self.g = colour[1]
            self.b = colour[2]
            if len(colour) > 3:
                self.a = colour[3]
        if self.a is None:
            self.a = 1.0

    def as_tuple(self):
        return (self.r, self.g, self.b, self.a)


class ImageBuffer:

    def __init__(self, image, clear=False):
        self.image = image
        self.x, self.y = self.image.size
        if clear:
            self.clear()
        else:
            self.buffer = list(self.image.pixels)

    def update(self):
        self.image.pixels = self.buffer

    def _index(self, x, y):
        if x < 0 or y < 0 or x >= self.x or y >= self.y:
            return None
        return (x + y * self.x) * 4

    def clear(self):
        self.buffer = [0.0 for i in range(self.x * self.y * 4)]

    def set_pixel(self, x, y, colour):
        index = self._index(x, y)
        if index is not None:
            self.buffer[index:index + 4] = colour.as_tuple()

    def get_pixel(self, x, y):
        index = self._index(x, y)
        if index is not None:
            return Pixel(colour=self.buffer[index:index + 4])
        else:
            return None


def ConvertToLatLong(inpic, outpic):

    width = inpic.size[0]
    height = inpic.size[1]

    uv_width = width * 2 - 1
    uv_height = height - 1

    pc_width = 0.5 * width
    pc_height = 0.5 * height

    p_in = ImageBuffer(inpic)
    p_out = ImageBuffer(outpic)
    p_out.clear()

    flip = width * 2 - 1

    for col in range(0, width * 2):
        phi = (col / uv_width) * 2 * math.pi
        for row in range(0, height):
            theta = (1 - row / uv_height) * math.pi
            m = math.sqrt(2 * (1 + math.sin(-theta) * math.sin(phi)))
            x = int((math.sin(theta) * math.cos(phi) / m + 1) * pc_width)
            y = int((math.cos(theta) / m + 1) * pc_height)
            pixel = p_in.get_pixel(x, y)
            p_out.set_pixel(flip - col, row, pixel)
    p_out.update()


############################################################################


def Draw_hdr_callback(self, context):

    if context.area != Hdr.view3d_area:
        return
    elif context.area.type == 'PROPERTIES' and \
            context.space_data.context != 'WORLD':
        return

    # Check if window area has changed for sticky zoom
    theHdr = Hdr.object[0]
    if Hdr.region.width < Hdr.saved_region_width:
        diff = Hdr.saved_region_width - Hdr.region.width
        if theHdr.origin.x + theHdr.width > Hdr.saved_region_width:
            if theHdr.origin.x > 0:
                theHdr.origin.x -= diff
            else:
                theHdr.width -= diff
        else:
            if Hdr.toolProps is not None:
                if Hdr.toolProps.width > Hdr.toolProps_width:
                    theHdr.origin.x -= diff
                Hdr.toolProps_width = Hdr.toolProps.width
            if theHdr.origin.x < 0:
                theHdr.origin.x += diff
    else:
        diff = Hdr.region.width - Hdr.saved_region_width
        if theHdr.width > Hdr.saved_region_width:
            theHdr.width += diff
        else:
            if Hdr.toolProps is not None:
                if Hdr.toolProps.width < Hdr.toolProps_width:
                    theHdr.origin.x += diff
                Hdr.toolProps_width = Hdr.toolProps.width
    theHdr.set_dimensions(theHdr.width)
    Hdr.saved_region_width = Hdr.region.width

    zAzim = theHdr.width / 2
    azimFac = zAzim / 180
    zElev = theHdr.height / 2
    elevFac = zElev / 90
    crossChange = True

    if not Hdr.action == 'PAN':
        x = Hdr.mouse.x
        y = Hdr.mouse.y
        if x < theHdr.origin.x or x > theHdr.origin.x + theHdr.width:
            crossChange = False
            x = 0
        else:
            testBoundary = theHdr.origin.x + theHdr.width
            if testBoundary < Hdr.region.width:
                rightBoundary = testBoundary
            else:
                rightBoundary = Hdr.region.width
            if x > rightBoundary:
                crossChange = False
                x = rightBoundary
        cX = x - zAzim - theHdr.origin.x

        if azimFac:
            newAzimuth = cX / azimFac
        else:
            newAzimuth = 0.0

        if y < theHdr.origin.y or y < 0:
            crossChange = False
            y = 0
        elif y > theHdr.origin.y + theHdr.height:
            crossChange = False
            y = theHdr.origin.y + theHdr.height
        cY = y - zElev - theHdr.origin.y

        if elevFac:
            newElevation = cY / elevFac
        else:
            newElevation = 0.0

        if newElevation == Hdr.elevation and newAzimuth == Hdr.azimuth:
            crossChange = False
        else:
            Hdr.elevation = newElevation
            Hdr.azimuth = newAzimuth
    else:
        if Hdr.grab.offset.x < Hdr.grab.spot.x:
            off = Hdr.grab.spot.x - Hdr.grab.offset.x
            theHdr.origin.x -= off
        else:
            off = Hdr.grab.offset.x - Hdr.grab.spot.x
            theHdr.origin.x += off
        if Hdr.grab.offset.y < Hdr.grab.spot.y:
            off = Hdr.grab.spot.y - Hdr.grab.offset.y
            theHdr.origin.y -= off
        else:
            off = Hdr.grab.offset.y - Hdr.grab.spot.y
            theHdr.origin.y += off
        Hdr.grab.spot.x = Hdr.mouse.x
        Hdr.grab.spot.y = Hdr.mouse.y

    Lx = theHdr.origin.x
    Ly = theHdr.origin.y

    # ---------------------
    # Draw a textured quad
    # ---------------------

    bgl.glEnable(bgl.GL_BLEND)
    if Hdr.glImage.bindcode == 0:
        Hdr.load_gl_image()
    bgl.glBindTexture(bgl.GL_TEXTURE_2D, Hdr.glImage.bindcode)
    bgl.glEnable(bgl.GL_TEXTURE_2D)
    bgl.glColor4f(1.0, 1.0, 1.0, Hdr.object[0].opacity)
    bgl.glBegin(bgl.GL_QUADS)
    bgl.glTexCoord2f(0.0, 0.0)
    bgl.glVertex2f(Lx, Ly)
    bgl.glTexCoord2f(1.0, 0.0)
    bgl.glVertex2f(Lx + theHdr.width, Ly)
    bgl.glTexCoord2f(1.0, 1.0)
    bgl.glVertex2f(Lx + theHdr.width, Ly + theHdr.height)
    bgl.glTexCoord2f(0.0, 1.0)
    bgl.glVertex2f(Lx, theHdr.height + Ly)
    bgl.glEnd()
    bgl.glDisable(bgl.GL_TEXTURE_2D)

    # ---------------------
    # draw the crosshair
    # ---------------------
    x = theHdr.width / 2.0
    if crossChange and not Hdr.lockCrosshair:
        Sun.SP.HDR_azimuth = degToRad(newAzimuth + 180)
    azimuth = ((radToDeg(Sun.SP.HDR_azimuth) - 180) * x / 180.0) + x

    bgl.glEnable(bgl.GL_BLEND)
    bgl.glEnable(bgl.GL_LINES)
    bgl.glLineWidth(1.0)
    alpha = 0.8
    color = (0.4, 0.4, 0.4, alpha)
    bgl.glColor4f(color[0], color[1], color[2], color[3])
    bgl.glBegin(bgl.GL_LINES)
    bgl.glVertex2f(Lx + azimuth, Ly)
    bgl.glVertex2f(Lx + azimuth, Ly + theHdr.height)
    bgl.glEnd()

    y = theHdr.height / 2.0
    if crossChange and not Hdr.lockCrosshair:
        Sun.SP.HDR_elevation = newElevation
    elevation = (Sun.SP.HDR_elevation * y / 90.0) + y

    bgl.glColor4f(color[0], color[1], color[2], color[3])
    bgl.glBegin(bgl.GL_LINES)
    bgl.glVertex2f(Lx, Ly + elevation)
    bgl.glVertex2f(Lx + theHdr.width, Ly + elevation)
    bgl.glEnd()

    # ---------------------
    # draw the border
    # ---------------------
    bgl.glDisable(bgl.GL_BLEND)
    color = (0.6, 0.6, .6, 1.0)
    bgl.glColor4f(color[0], color[1], color[2], color[3])
    bgl.glBegin(bgl.GL_LINE_LOOP)
    bgl.glVertex2f(Lx, Ly)
    bgl.glVertex2f(Lx + theHdr.width, Ly)
    bgl.glVertex2f(Lx + theHdr.width, Ly + theHdr.height)
    bgl.glVertex2f(Lx, theHdr.height + Ly)
    bgl.glVertex2f(Lx, Ly)
    bgl.glEnd()

    bgl.glLineWidth(1.0)
    bgl.glDisable(bgl.GL_LINES)
    bgl.glFlush()

# ---------------------------------------------------------------------------


class SunPos_HdrHelp(bpy.types.Operator):
    bl_idname = "object.hdrhelp_operator"
    bl_label = "Hdr help"

    def execute(self, context):
        self.report({'INFO'}, self.message)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_popup(self, width=400, height=200)

    def draw(self, context):
        self.layout.label(text="Available commands:")

        row = self.layout.row()
        split = row.split(percentage=.26)
        colL = split.column()
        colR = split.column()
        colL.label(text="Esc or Right Mouse ")
        colR.label("Close map or text.")
        colL.label(text="Left Mouse")
        colR.label(text="Move crosshair.")
        colL.label(text="G or MiddleMouse")
        colR.label("Pan mode. Grab and move map or text.")
        colL.label(text="Ctrl Middlemouse")
        colR.label(text="Mouse zoom to point.")
        self.layout.label("--- The following are changed by moving " +
                          "the mouse or using the scroll wheel.")
        self.layout.label(text="--- Use Ctrl for coarse increments or Alt for fine.")
        row = self.layout.row()
        split = row.split(percentage=.25)
        colL = split.column()
        colR = split.column()
        colL.label(text="Scroll wheel")
        colR.label(text="Zoom to point.")