
var logA = function(x){ console.log(x); return x; }.A();

var loaderImage = 'img/loader.gif';

function logMsgA(msg){
    return function(x){
        console.log(msg + ': ' + x);
        return x;
    }.A();
}

function makeAjaxLink(link){
    var href = link.get('href');
    link.removeProperty('href');
    return { item:link, source: href };
}

function adjustToAspect(coords, img) {
    var img_aspect = img.get('width') / img.get('height');
    var scroll_aspect = coords.width / coords.height;

    var width = coords.width;
    var height = coords.height;

    if(scroll_aspect < img_aspect) height = width / img_aspect;
    else                           width  = height * img_aspect;

    var maxWidth = 1400;
    var factor = maxWidth / width;
    if(factor < 1) {
        width = maxWidth;
        height *= factor;
    }

    var top = coords.top + (coords.height - height)/2;
    var left = coords.left + (coords.width - width)/2;
    return { top: top, left: left, width: width, height: height };
}

function computeFinalImageCoords(x) {
    var delta = 20;
    var size = window.getCoordinates();
    var end = { top: delta, left: delta,
                width: size.width - 2*delta, 
                height: size.height - 2*delta};

    return adjustToAspect(end, x.img);
}

var showImage = createAndRunSub(function(x) {
    var container = document.getElement('body');
    var thumb = x.item.getElement('img');
    var start = thumb.getCoordinates();
    var scroll = window.getScroll();

    var overlay = new Element('div', { styles: { position: 'fixed',
                                                 'background-color': 'black',
                                                 top: 0, left: 0, width: '100%', height: '100%',
                                                 'z-index': 5000, opacity: 0 }});
    overlay.inject(container);

    x.img.setStyles({ visibility: 'visible',
                      opacity: 1, 'z-index': 9999,
                      position: 'fixed',
                      left: start.left - scroll.x, 
                      top: start.top - scroll.y,
                      width: start.width, 
                      height: start.height });
    if(x.img.getParent() != container) x.img.inject(container);

    var showOverlay = ignoreResultA( $constA( overlay ), morphA({ opacity: 0.6 }) );
    var hideOverlay = ignoreResultA( $constA( overlay ), morphA({ opacity: 0.0 }),
                                     overlay.destroy.bind(overlay) );

    var imageIn = $sequenceA(
            trueA,
            $whileA( $id,
                $orA( 
                    $sequenceA(
                        $constA(x.img),
                        createAndRunSub(function(){
                            return morphA( computeFinalImageCoords(x) ).next( falseA );
                        })),
                    $sequenceA( $constA(window), $onEvent('resize'), trueA ))));

    var imageOut = $sequenceA(
            ignoreResultA( function(img){
                    var scroll = window.getScroll();
                    var end = computeFinalImageCoords(x);
                    img.setStyles( { position: 'absolute',
                                     left: scroll.x + end.left,
                                     top: scroll.y + end.top });
            }),
            createAndRunSub(function() {
                return ignoreResultA( morphA( thumb.getCoordinates()));
            }));
    var handleResize = $sequenceA( 
                        $constA(window), 
                        $onEvent('resize'),
                        function(){
                            x.img.setStyles( computeFinalImageCoords(x) );
                            return true;
                        });
    var blendIn = ignoreResultA( $fanout( showOverlay, imageIn ));
    var blendOut = $fanout( imageOut, hideOverlay );
    var cleanUp = function(){ x.img.setStyle('visibility', 'hidden'); x.img.dispose(); };

    return $sequenceA(
        $constA(x.img),
        blendIn,
        ignoreResultA( // handle resize of browser until click on image
            trueA,
            $whileA( $id,
                $orA(
                    $sequenceA( $constA(x.img), $onEvent('click'), falseA),
                    handleResize))),
        blendOut, cleanUp);
});

var PROTO_LOAD = 1;
var PROTO_SHOW = 2;

function proto(t){ return function(x){
        return {type: t, data: x};
    };
}

function isProtoA(t) { 
    return function(x){
        return x !== null && $defined(x['type']) && x.type === t;
    };
}

var isLoadMsg = isProtoA(PROTO_LOAD);
var isShowMsg = isProtoA(PROTO_SHOW);

function showLoad(x){
    var coords = x.item.getElement('img').getCoordinates();
    var loaderDim = 15;

    var overlayContainer = new Element('div',
            { styles: { position: 'absolute',
                        top: coords.top, left: coords.left,
                        width: coords.width, height: coords.height,
                        'z-index': 5000 }});

    var overlay = new Element('div',
            { styles: { position: 'absolute',
                        'background-color': 'black',
                        top: 0, left: 0, 
                        width: coords.width, height: coords.height,
                        'z-index': 6000, opacity: 0.4
                        }});

    var loader = Asset.image(loaderImage);
    loader.setStyles( { position: 'absolute',
                        width: loaderDim,
                        height: loaderDim,
                        top: (coords.height - loaderDim)/2,
                        left: (coords.width - loaderDim)/2,
                        'z-index': 7000, opacity: 1
                        });



    var container = document.getElement('body');
    overlayContainer.inject(container);
    overlay.inject(overlayContainer);
    loader.inject(overlayContainer);

    return [overlay, loader, overlayContainer, x.item];
}

function endLoad(overlay){
    overlay[1].destroy();
    overlay[0].destroy();
    overlay[2].destroy();
}

function init_gallery() {
    var stopLoadOnMouseLeave = true;

    var g_entries = $orA(
            $('gallery').getElements('.g_entry').map( function(e){
                var link = e.getElement('a');
                if(!link) return null;
                link =  makeAjaxLink( link );
                link.item = e;
                return link;
                }).filter( function(e) { return e !== null; }).map( 
                    function(e) { 
                        return e.item.onEvent('click').next( $constA( e ));
                }));

    $foreverA(
        $orA(
            $sequenceA( g_entries, proto(PROTO_LOAD)),
            $sequenceA(
                guardA( $not( isNull )), guardA( isLoadMsg ),
                fieldA('data'),
                $orA(
                    $sequenceA(
                        showLoad,
                        $orA( 
                            waitForKill(endLoad),
                            $sequenceA(
                                ignoreResultA(
                                    guardA(
                                        $constA(stopLoadOnMouseLeave))),
                                arefA(2),
                                $onEvent('mouseleave'),
                                $constA(null)))),
                    $sequenceA(
                        $fanout(
                            setFieldIfUndefinedA('img', $sequenceA( fieldA('source'), loadImage)),
                            $delayA(5)),
                        arefA(0),
                        proto(PROTO_SHOW))))),
        $whenA( isShowMsg,
            $sequenceA( fieldA( 'data' ), showImage, $constA( null )))).run(null);
}

window.addEvent('domready', function(){
          init_gallery();
        });


