var Fastbox = (function(){

  function Fastbox(links, path_css, path_php){
    // We will need this
    new Asset.css(path_css);

    // Apply lightbox on the links elements
    $$(links).each(function(link){
      link.addEvent('click', function(e){
        e.stop();

        // ===============
        // = GLOBAL VARS =
        // ===============
        var img, loading, closed, timer, block, fix_hud, img_width, img_height;

        // ===================
        // = BUILD INTERFACE =
        // ===================

        // OVERLAY
        if (!overlay) {
          var overlay = new Element('div', {'id': 'overlay'});
          // --- Effects
          var fx_o = new Fx.Morph(overlay, {'duration': 500, 'link': 'cancel'});
          // --- Events
          overlay.addEvent('click', function(){ close(); });
        }
        // --- Inject
        fx_o.set({'opacity': 0});
        overlay.inject(document.body);

        // IMAGE FRAME
        if (!frame) {
          var frame = new Element('div', {'id': 'frame'});
          // --- Events
          frame.addEvent('click', function(){ close(); });
        }
        // --- Inject
        frame.inject(document.body);

        // INDICATOR
        if (!indicator){
          var indicator = new Element('div', {'id': 'indicator'});
          var busy = new Element('div', {'id': 'busy'}).inject(indicator);
          // --- Events
          indicator.addEvent('click', function(){ close(); });
        }

        // HUD CONTROLLER
        if (!hud) {
          var c_prev = new Element('a', {'id': 'c_prev'});
          var c_down = new Element('a', {'id': 'c_down'});
          var c_next = new Element('a', {'id': 'c_next'});
          var controls = new Elements([c_prev, c_down, c_next]);
          var hud = new Element('div', {'id': 'hud'}).adopt(controls);
          // --- Effects
          var fx = new Fx.Morph(hud, {'duration': 500, 'link': 'cancel'});
          fx.addEvent('onComplete', function(){
            block = false;
            if (fix_hud) return;
            if (hud.getStyle('opacity') === 1) {
              timer = fx.start.delay(1000, fx, {'opacity': 0});
            }
          });
          // --- Events
          controls.addEvent('mouseenter', function(){
            $clear(timer);
            fix_hud = true;
          })
          controls.addEvent('mouseout', function(){
            fix_hud = false;
            timer = fx.start.delay(1000, fx, {'opacity': 0});
          });
          c_next.addEvent('click', function(){ change_img('next', c_next); });
          c_prev.addEvent('click', function(){ change_img('prev', c_prev); });
        }
        // --- Inject
        fx.set({'opacity': 0});
        hud.inject(document.body);

        // DOCUMENT EVENTS
        window.addEvent('mousemove', function(){
          if (block) return;
          block = true;
          $clear(timer);
          fx.start({'opacity': 1});
        });
        document.addEvent('keydown', function(event){
          switch(event.code) {
            case 27:  // Esc
            case 88:  // 'x'
            case 67:  // 'c'
            close();
            break;
            case 40:  // down
            location = path_php+'?img='+link.getProperty('href');
            break;
            case 37:  // Left arrow
            case 80:  // 'p'
            change_img('prev', c_prev);
            break;  
            case 39:  // Right arrow
            case 78:  // 'n'
            change_img('next', c_next);
          }
        });

        // ======================
        // = INTERACTIVE EVENTS =
        // ======================

        // CLOSING EVENT
        function close(){
          closed = true;
          if (indicator) indicator.dispose();
          frame.dispose();
          hud.dispose();
          fx_o.start({'opacity': 0}).chain(function(){
            overlay.dispose();
          });
          document.removeEvents('keydown');
          window.removeEvents('mousemove');
          window.removeEvents('resize');
        }

        // UPDATE HUD, AND PRELOAD
        function update(){
          // Test prev/next images
          if (link.getParent().getNext()) {
            c_next.removeClass('inactive');
            // Preloading
            new Asset.image(link.getParent().getNext().getFirst().getProperty('href'));
          }
          else {
            c_next.addClass('inactive');
          }
          if (link.getParent().getPrevious()) {
            c_prev.removeClass('inactive');
            // Preloading
            new Asset.image(link.getParent().getPrevious().getFirst().getProperty('href'));
          }
          else {
            c_prev.addClass('inactive');
          }
          // Set the HREF for the download controller
          c_down.setProperty('href', path_php+'?img='+link.getProperty('href'));
        }

        // IMAGE IS READY
        function img_ready(){
          loading = false;
          if (closed) return;
          // Timeout pour firefox qui fait un glitch visuel sinon
          setTimeout(function(){ indicator.dispose(); }, 100);
          img.inject(frame);
          img_width = img.getSize().x;
          img_height = img.getSize().y;
          resize_img();
        }

        // PREV/NEXT IMAGES CALL
        function change_img(to, button){
          if (button.hasClass('inactive')) return;
          img.dispose();
          if (!$('busy')) indicator.grab(busy);
          indicator.removeClass('error').inject(document.body);
          // Update HUD
          if (to == "next") {
            link = link.getParent().getNext().getFirst();
          }
          else {
            link = link.getParent().getPrevious().getFirst();
          }
          update();
          // Do the asset now
          loading = true;
          img = new Asset.image(link.getProperty('href'), {
            'title': link.getProperty('title'),
            'alt': link.getProperty('title'),
            'onerror': function(){
              indicator.empty().setProperty('class', 'error');
            },
            'onload': function(){
              img_ready();
            }
          });
        }

        // RESIZE IMAGE
        function resize_img(){
          // Get some informations
          var win_width = window.getSize().x;
          var win_height = window.getSize().y;

          var ratio = img_width / img_height;
          var height; var width;

          // Resizing function
          function resize(dimension){
            if (dimension == "x") {
              width = win_width - 20;
              height = width / ratio;
            }
            else {
              height = win_height - 20;
              width = height * ratio;
            }
          }

          // Let's do the tests
          if (win_width >= img_width) {
            // Pas tronquée
            if (win_height >= img_height) {
              width = img_width;
              height = img_height;
            }
            // Tronquée en hauteur
            else {
              resize('y');
            }
          }
          else {
            // Tronquée en largeur
            if (win_height >= img_height) {
              resize('x');
            }
            // Tronquée en hauteur & largeur
            else {
              // Fenêtre en portrait
              if (win_width < win_height) {
                // Image en paysage ou en carré
                if (ratio >= 1) {
                  resize('x');
                }
                // Image en portrait
                else if (ratio < 1) {
                  // Image plus rapidement redimensionnée en hauteur qu'en largeur
                  if (img_width - win_width > img_height - win_height) {
                    resize('y');
                  }
                  // Inversement
                  else {
                    resize('x');
                  }
                }
              }
              // Fenêtre en paysage
              else {
                // Image en paysage
                if (ratio > 1) {
                  // Image plus rapidement redimensionnée en hauteur qu'en largeur
                  if (img_width - win_width > img_height - win_height) {
                    resize('x');
                  }
                  // Inversement
                  else {
                    resize('y');
                  }
                }
                // Image en portrait ou en carré
                else if (ratio <= 1) {
                  resize('y');
                }
              }
            }
          }
          // POSITION : TOP & LEFT
          var left = (win_width - width) / 2;
          var top = (win_height - height) / 2;
          // SET THE STYLES
          img.setProperties({'width': width, 'height': height});
          img.set('style', 'top:'+top+'px;left:'+left+'px');
        }

        // ==================
        // = FIRST SEQUENCE =
        // ==================

        // DEPLOY OVERLAY
        fx_o.start({'opacity': 0.8}).chain(function(){
          if (!loading) return;
          indicator.inject(document.body);
        });

        // LOAD FIRST IMAGE
        loading = true;
        img = new Asset.image(this.getProperty('href'), {
          'title': this.getProperty('title'),
          'alt': this.getProperty('title'),
          'onerror': function(){
            indicator.empty().setProperty('class', 'error');
          },
          'onload': function(){
            img_ready();
            window.addEvent('resize', function(){
              resize_img();
            });
          }
        });

        // UPDATE HUD
        update();
      });
    });
  }

  return Fastbox;  
})();