// declare the minimal number of public variables and global event handlers, all these are global
// or refer to only one possible instance

document.onmousemove   = fncFesMouseMove;
document.onmousedown   = fncFesMouseDown;
document.onmouseup     = fncFesMouseUp;
document.onresize      = fncFesResize;

var pub_clicked_image  = null;
var pub_hovered_image  = null;
var pub_mouse_down     = false;

//=================================================================================================
//
// Object fesImageZoomer (+Functions) for Image Viewer
//
//=================================================================================================

function fesImageZoomer(parameters)
{
    this.img_id = parameters.img_id; // DOM id of the image that will present the zoomer, used as reference key

    this.clicked_object       = null;
    this.image_position       = {left:0,top:0};
    this.viewport_position    = {left:0,top:0};
    this.viewport_width       = null;
    this.viewport_height      = null;
    this.zoomed_width         = null;
    this.zoomed_height        = null;
    this.original_width       = null;
    this.original_height      = null;
    this.clicked_position     = null;
    this.mouse_offset         = {left:0,top:0};
    this.latched_zoom         = null; // store the value of zoom (+/-) for reference by the timed repeat

    this.zoom_interval        = 10; // zoom repeat rate
    this.zoom_factor          = 10; // multiplacation factor for zoom instrcutions (wheel/mouse clicks)
    this.timeout_timer; // reference to the timer object
    this.zoom_command = 'window.fes_zoomers["' + this.img_id + '"].fncZoom()'; // command to send to the timer
    this.move_command = 'window.fes_zoomers["' + this.img_id + '"].fncMove()'; // command to send to the timer

    if (typeof window.fes_zoomers === 'undefined')
    {
        window.fes_zoomers = new Object(); // Create global container object anchored to the window object to hold references to zoomer objects so that the Settimer functions (which runs with window context) can locate them, scrappy but effective

    }

    window.fes_zoomers[this.img_id] = this; // Add a reference to this object keyed on the image ID it will reference

    this.fncLoadImage(document.getElementById(this.img_id)); // to obtain and populate the original dimensions

// if (typeof(parameters.img_url_array) === 'object') this.fncLoadzoomerImages(parameters.img_url_array);

//POS    this.image_position    = fncFesGetAbsolutePosition(document.getElementById(this.img_id)); // capture the location and size of the base image to which to anchor the viewport
//POS    this.viewport_position = fncFesGetAbsolutePosition(document.getElementById(this.img_id)); // capture the location and size of the base image to which to anchor the viewport

//    if (fes_environment.ie && !fes_environment.ie8)
//    {
//        this.viewport_position.top  += parseInt(document.getElementById(this.img_id).parentNode.currentStyle.borderTopWidth);
//        this.viewport_position.left += parseInt(document.getElementById(this.img_id).parentNode.currentStyle.borderLeftWidth);
//
//    }

    this.viewport_width    = document.getElementById(this.img_id).offsetWidth;
    this.viewport_height   = document.getElementById(this.img_id).offsetHeight;

    this.zoomed_width  = this.viewport_width;
    this.zoomed_height = this.viewport_height;

    var loc_viewport_offset = {top:0,left:0};

    document.getElementById(this.img_id).style.position = 'absolute';

    document.getElementById(this.img_id).style.top      = (this.viewport_position.top - loc_viewport_offset.top) + 'px';
    document.getElementById(this.img_id).style.left     = (this.viewport_position.left - loc_viewport_offset.left) + 'px';

}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncLoadImage = function(prm_image_object)
{
//  changes the loaded image and obtains the 'full size' image dimensions

    document.getElementById(this.img_id).src = prm_image_object.src;

    var loc_img = new Image();
    loc_img.src = prm_image_object.src;

    this.original_width = loc_img.width;
    this.original_height = loc_img.height;

}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncMouseMove = function(prm_event)
{
    var loc_mouse_position = fncFesGetPointerCoordinates(prm_event);

    this.fncMove(((loc_mouse_position.left - pub_click_offset.left)- this.mouse_offset.left),
                 ((loc_mouse_position.top - pub_click_offset.top) - this.mouse_offset.top));

    this.mouse_offset.left = loc_mouse_position.left - pub_click_offset.left;
    this.mouse_offset.top = loc_mouse_position.top - pub_click_offset.top;
}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncClickMove = function(prm_left,prm_top)
{
    this.fncMove((this.image_position.left + prm_left),
                 (this.image_position.top + prm_top));

}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncMove = function(prm_left,prm_top)
{
    this.image_position.top = Math.max((this.viewport_position.top + this.viewport_height - this.zoomed_height),
                                       Math.min(this.viewport_position.top,this.image_position.top + prm_top));

    document.getElementById(this.img_id).style.top  = this.image_position.top + 'px';

    this.image_position.left = Math.max((this.viewport_position.left + this.viewport_width - this.zoomed_width),
                                        Math.min(this.viewport_position.left,this.image_position.left + prm_left));

    document.getElementById(this.img_id).style.left = this.image_position.left + 'px';

    loc_rect = 'rect(' + (this.viewport_position.top - this.image_position.top) + 'px, '
                       + (this.viewport_position.left - this.image_position.left + this.viewport_width) + 'px, '
                       + (this.viewport_position.top - this.image_position.top + this.viewport_height) + 'px, '
                       + (this.viewport_position.left - this.image_position.left) + 'px)';

    document.getElementById(this.img_id).style.clip = loc_rect;

}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncZoom = function(prm_zoom)
{
    if (!prm_zoom && !pub_mouse_down) return; // repeat timer expired but mouse is no longer pressed so abandon zoom

    this.latched_zoom = loc_zoom = prm_zoom || this.latched_zoom; // either we're passed +/-1 or reuse the latched value on recall

    loc_zoom = Math.min(loc_zoom *= this.zoom_factor,this.original_width - this.zoomed_width);

/*
    Compute a shimmy here to centralise the image within the view as it's resized
*/
    loc_shimmy_width_weighting  = (this.viewport_width / 2 + (this.viewport_position.left - this.image_position.left)) / (this.zoomed_width / 2); // the weighting prevents an averaged shimmy gravitating towards the centre when zooomed at the edges
    loc_shimmy_height_weighting = (this.viewport_height / 2 + (this.viewport_position.top - this.image_position.top))  / (this.zoomed_height / 2);

    this.zoomed_width += loc_zoom; // compute the new width (and height)
    if (this.zoomed_width < this.viewport_width) this.zoomed_width = this.viewport_width; // fix the minimum zoom at the viewport width
    if (this.zoomed_width > this.original_width) this.zoomed_width = this.original_width; // fix the maximum zoom at the full image width
    this.zoomed_height = this.zoomed_width * this.viewport_height / this.viewport_width;

//    if (this.zoomed_width > this.viewport_width && this.zoomed_width < this.original_width) // only apply the shimmy if we're actually changing size
//    {
        loc_shimmy_width  = Math.round(loc_shimmy_width_weighting * loc_zoom / 2);
        loc_shimmy_height = Math.round(loc_shimmy_height_weighting * loc_zoom * this.viewport_height / this.viewport_width / 2);
//    }
//    else
//    {
//        loc_shimmy_width = loc_shimmy_height = 0;
//
//    }

    this.image_position.top = Math.round(Math.max((this.viewport_position.top + this.viewport_height - this.zoomed_height),
                                                   Math.min(this.viewport_position.top, (this.image_position.top - loc_shimmy_height))));

    document.getElementById(this.img_id).style.top  = this.image_position.top + 'px';

    this.image_position.left = Math.round(Math.max((this.viewport_position.left + this.viewport_width - this.zoomed_width),
                                                   Math.min(this.viewport_position.left,(this.image_position.left - loc_shimmy_width))));

    document.getElementById(this.img_id).style.left = this.image_position.left + 'px';

    document.getElementById(this.img_id).style.width    = this.zoomed_width + 'px';
    document.getElementById(this.img_id).style.height   = this.zoomed_height + 'px';

    loc_rect = 'rect(' + Math.round(this.viewport_position.top - this.image_position.top) + 'px, '
                       + Math.round(this.viewport_position.left - this.image_position.left + this.viewport_width) + 'px, '
                       + Math.round(this.viewport_position.top - this.image_position.top + this.viewport_height) + 'px, '
                       + Math.round(this.viewport_position.left - this.image_position.left) + 'px)';

    document.getElementById(this.img_id).style.clip = loc_rect;

    if (pub_mouse_down || prm_zoom) this.timeout_timer = setTimeout(this.zoom_command, this.zoom_interval);

}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncReset = function()
{
    this.zoomed_width = this.viewport_width;
    this.zoomed_height = this.viewport_height;

    loc_shimmy_width =
    loc_shimmy_height = 0;

    this.image_position.top = Math.max((this.viewport_position.top + this.viewport_height - this.zoomed_height),
                                       Math.min(this.viewport_position.top, (this.image_position.top - loc_shimmy_height)));

    document.getElementById(this.img_id).style.top  = this.image_position.top + 'px';

    this.image_position.left = Math.max((this.viewport_position.left + this.viewport_width - this.zoomed_width),
                                        Math.min(this.viewport_position.left,(this.image_position.left - loc_shimmy_width)));

    document.getElementById(this.img_id).style.left = this.image_position.left + 'px';

    document.getElementById(this.img_id).style.width    = this.zoomed_width + 'px';
    document.getElementById(this.img_id).style.height   = this.zoomed_height + 'px';

    loc_rect = 'rect(' + (this.viewport_position.top - this.image_position.top) + 'px, '
                       + (this.viewport_position.left - this.image_position.left + this.viewport_width) + 'px, '
                       + (this.viewport_position.top - this.image_position.top + this.viewport_height) + 'px, '
                       + (this.viewport_position.left - this.image_position.left) + 'px)';

    document.getElementById(this.img_id).style.clip = loc_rect;

}

//
//=================================================================================================
//

fesImageZoomer.prototype.fncResize = function()
{

debugDump(this.img_id,"resizer");
debugDump(document.body.clientWidth,"resizer1");
debugDump(document.documentElement.clientHeight,"resizer2");


}

//
//=================================================================================================
//

function fncFesGetPointerCoordinates(prm_event)
{
    prm_event = prm_event || window.event;

    if (prm_event.pageX || prm_event.pageY) // standards browser
    {
        return {left:prm_event.pageX, top:prm_event.pageY};

    }
    else // IE
    {   return {left:prm_event.clientX + document.body.scrollLeft - document.body.clientLeft,
                top:prm_event.clientY  + document.body.scrollTop  - document.body.clientTop};

    }

}

function fncFesMouseMove(prm_event)
{
    prm_event = prm_event || window.event;

    var loc_mouse_position = fncFesGetPointerCoordinates(prm_event);

    if (pub_clicked_image)
    {
        window.fes_zoomers[pub_clicked_image.id].fncMouseMove(prm_event);

        return false;
    }

}

function fncFesMouseUp(prm_event)
{
    pub_clicked_image = null;
    pub_mouse_down = false;

}

function fncFesMouseDown(prm_event)
{
    pub_mouse_down = true;

}

function fncFesResize(prm_event)
{
    for (var loc_zoomer in  window.fes_zoomers)
    {
        window.fes_zoomers[loc_zoomer].fncResize();

    }

    return false;

}

function fncFesEnableThing(prm_object_id)
{
    if (!pub_fes_mo_preloaded) return false;

    loc_object = document.getElementById(prm_object_id);

    pub_hovered_image = loc_object;
    document.onmousewheel   = fncFesOnMouseWheel;
    if (document.addEventListener) document.addEventListener('DOMMouseScroll', fncFesOnMouseWheel, false);

    loc_object.onmousedown = function(prm_event)
    {
        pub_clicked_image    = this;
        pub_click_offset     = FncGetMouseOffset(this,prm_event);
        pub_clicked_position = fncFesGetPointerCoordinates(prm_event);

        window.fes_zoomers[pub_clicked_image.id].mouse_offset.left = 0;
        window.fes_zoomers[pub_clicked_image.id].mouse_offset.top = 0;

        return false;
    }

    if (!window.fes_zoomers || !window.fes_zoomers[prm_object_id])
    {
        new fesImageZoomer({img_id : prm_object_id});

    }

}

function fncFesDisableThing(prm_object)
{
    pub_hovered_image = null;
    document.onmousewheel = null;
    if (document.addEventListener) document.addEventListener('DOMMouseScroll', null, false);

}

function fncFesZoomThing(prm_object_id,prm_zoom)
{
    if (!window.fes_zoomers || !window.fes_zoomers[prm_object_id])
    {
        new fesImageZoomer({img_id : prm_object_id});

    }

    window.fes_zoomers[prm_object_id].fncZoom(prm_zoom);

}

function fncFesMoveThing(prm_object_id,prm_left,prm_top)
{
    window.fes_zoomers[prm_object_id].fncClickMove(prm_left,prm_top);

}

function fncFesResetThing(prm_object_id)
{
    if (!window.fes_zoomers || !window.fes_zoomers[prm_object_id])
    {
        new fesImageZoomer({img_id : prm_object_id});

    }

    window.fes_zoomers[prm_object_id].fncReset();

}

function fncFesLoadThing(prm_object_id,prm_object)
{
    window.fes_zoomers[prm_object_id].fncLoadImage(prm_object);

}

function fncFesOnMouseWheelAction(prm_delta)
{
    window.fes_zoomers[pub_hovered_image.id].fncZoom(prm_delta);
}


function FncGetMouseOffset(target,prm_event)
{
    prm_event = prm_event || window.event;

    var loc_element_position = fncFesGetAbsolutePosition(target);
    var loc_mouse_position = fncFesGetPointerCoordinates(prm_event);

//    return {left:loc_mouse_position.left - loc_element_position.left, top:loc_mouse_position.top - loc_element_position.top};
    return {left:loc_mouse_position.left, top:loc_mouse_position.top};
}

function fncFesToggleVideo(prm_object_id)
{
    if (!window.fes_zoomers || !window.fes_zoomers[prm_object_id])
    {
        new fesImageZoomer({img_id : prm_object_id});

    }

    window.fes_zoomers[prm_object_id].fncReset();

}



//function makeDraggable(item){
//    if(!item) return;
//    item.onmousedown = function(ev){
//        pub_clicked_image  = this;
//        pub_click_offset = FncGetMouseOffset(this, ev);
//        return false;
//    }
//}

