# -*- 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.user_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("Available commands:")

        row = self.layout.row()
        split = row.split(percentage=.26)
        colL = split.column()
        colR = split.column()
        colL.label("Esc or Right Mouse ")
        colR.label("Close map or text.")
        colL.label("Left Mouse")
        colR.label("Move crosshair.")
        colL.label("G or MiddleMouse")
        colR.label("Pan mode. Grab and move map or text.")
        colL.label("Ctrl Middlemouse")
        colR.label("Mouse zoom to point.")
        self.layout.label("--- The following are changed by moving " +
                          "the mouse or using the scroll wheel.")
        self.layout.label("--- 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("Scroll wheel")
        colR.label("Zoom to point.")
