/*
   _                            _
  |_|___ _ _ ___ ___ ___    ___| |_    ___ ___ ___ ___ ___ ___ ___
  | | -_| | |   | -_|_ -|  | -_|  _|  | -_|   | . | .'| . | -_|_ -|
 _| |___|___|_|_|___|___|  |___|_|    |___|_|_|_  |__,|_  |___|___|
|___|                                         |___|   |___|

     Bachir Soussi Chiadmi
     2015
*/

jQuery(document).ready(function($) {
  // console.log('Hello Jee');

  // http://stackoverflow.com/questions/2890898/preventing-mouse-emulation-events-ie-click-from-touch-events-in-mobile-safari
  // FastClick.attach(document.body);

  var _debug = false,
      _avgDelay = 1,
      _lastDraw = new Date,
      _fps,
      _$nav_cursor,
      // _History = window.History;
      _isInIFrame = window.location !== window.parent.location;

  var _$body = $('body'),
      _is_mobile = $('html').is('.mobile'),
      _$header = $("#header"),
      _$chapitres = $('.node-chapitre', '#main'),
      _chapitres_len = _$chapitres.length,
      _chapters = [],
      _$container = $('#main'),
      _container = {
        w:_$container.width(),
        h:_$container.height()
      },
      _center = {x:_container.w/2,y:_container.h/2},
      _nav_pos = {x:0, y:0},
      _mouse_down_pos = {x:0,y:0},
      _prev_mouse_pos = {x:0,y:0},
      _fps = 1000/12,
      _dragging = false, _timeout_dragging,
      _previewed_chapter = false;

  var _$chapter_wrapper = $('<div>').attr('id', 'chapter-wrapper').appendTo(_$container),
      _loaded_chapter = false;

  var _bubbles = new Array(),
      _stars = new Array();

  var _$footer = $('#footer'),
      _$static_wrapper = $('<div><div class="inner"></div></div>').attr('id', 'static-wrapper').appendTo(_$container),
      _$close_static = $('<div>').addClass('close').appendTo(_$static_wrapper);
      _loaded_static = false;

  var _$loader = $('<div>').attr('id','loader').appendTo(_$body);

  var _touch_started = false;

  function init(){
    if(_debug)
      initDebug();

    initChapterWrapper();
    initChapters();
    initStaticLinks();

    // initHistoryNav();

    launchNav();

    // FULL SCREEN
    var $fullscreenBtn = $('<div>Plein écran</div>').attr('id','fullscreen-btn').appendTo("#root");
    $fullscreenBtn.on('click', onFullScreen);


    // create bubbles
    for (var i = 2; i > 0; i--) {
      _bubbles.push($('<div>').addClass('bubble bubble-'+i).prependTo(_$container));
    };

    // create stars
    // for (var i = 20; i > 0; i--) {
    //   _stars.push(
    //     $('<div>')
    //       .addClass('star star-'+i)
    //       .css({
    //         left:randB(-400, _container.w+400),
    //         top:randB(-400, _container.h+400)
    //       })
    //       .prependTo(_$container)
    //   );
    // };

    initHashNav();
  };

  function initDebug(){
    $('<p>').attr('id', 'fps').appendTo(_$container);
    _fps = document.getElementById('fps');
    requestAnimationFrame(displayFps);

    _$nav_cursor = $('<div id="nav-cursor"></div>').appendTo(_$container);
    moveDebugCursor();
  };

  function displayFps(){
    requestAnimationFrame(displayFps);
    var now = new Date;
    var delay = now - _lastDraw;
    _avgDelay += (delay - _avgDelay) / 10;
    _lastDraw = now;

    _fps.innerHTML = (1000/_avgDelay).toFixed(1) + " fps";
  };

  function moveDebugCursor(){
    _$nav_cursor.css({
      left:_nav_pos.x+_center.x+"px",
      top:_nav_pos.y+_center.y+"px"
    });
  };

  function initChapterWrapper(){
    if(!_isInIFrame){
      $('<div id="home-btn">')
        .on("click", onCloseChapterWrapper)
        .appendTo(_$chapter_wrapper);
    }
  };

  function onCloseChapterWrapper(e){
    _loaded_chapter.stopAndClose();
    _loaded_chapter = false;
    _$chapter_wrapper.removeClass('visible');
    _$body.removeClass('chapter-displayed');
    setTimeout(function(){
      _$chapter_wrapper.find('.node').remove();
    }, 2000);
    updateHash('');
  };

  function initChapters(){
    // Place each chapters on the ellipse contained on the screen
    var base_a = Math.random() *360;
    _$chapitres.each(function(i, e) {
      // Lets create the chapter object and place him self
      _chapters.push(new Chapter(i, e, base_a));

    });
  };

  function launchNav(){

    $("#block-system-main")
      /*
       ____  _____ _____ _____ _____ _____ _____    _____ _____ _____ _____ _____ _____
      |    \|   __|   __|  |  |_   _|     |  _  |  |   __|  |  |   __|   | |_   _|   __|
      |  |  |   __|__   |    -| | | |  |  |   __|  |   __|  |  |   __| | | | | | |__   |
      |____/|_____|_____|__|__| |_| |_____|__|     |_____|\___/|_____|_|___| |_| |_____|
      */
      .on('mousemove', function(e){
        e.preventDefault();

        // prevent firing mousemove with touch events
        if(_touch_started)
          return false;

        console.log('document mousemove');
        clearTimeout(_timeout_dragging);

        // if(_previewed_chapter || _loaded_chapter || _loaded_static)
        //   return false;

        // activate dragging if already activated
        if(!_dragging){
          _dragging = true;

          startMoveNav();
        }else{
          updateNavPos(e.clientX, e.clientY, false, false);
        }
      })
      .on('mouseup', function(e){
        e.preventDefault();

        if(e.target !== this)
          return false;

        console.log('document mouseup');

        if(_loaded_chapter || _loaded_static)
          return false;

        for (var i = _chapitres_len - 1; i >= 0; i--)
          _chapters[i].closePreview().unMitigate();
      })
      /*
       _____ _____ _____ _____ _____    _____ _____ _____ _____ _____ _____
      |_   _|     |  |  |     |  |  |  |   __|  |  |   __|   | |_   _|   __|
        | | |  |  |  |  |   --|     |  |   __|  |  |   __| | | | | | |__   |
        |_| |_____|_____|_____|__|__|  |_____|\___/|_____|_|___| |_| |_____|
      */
      .on('touchstart', function(e){
        // e.preventDefault();
        console.log('document touchstart');

        _touch_started = true;

        clearTimeout(_timeout_dragging);

        if(_loaded_chapter || _loaded_static)
          return false;

        // set initial pos
        updateNavPos(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY, true, true);

        // activate dragging if already activated
        if(!_dragging){
          _dragging = true;
          startMoveNav();
        }
      })
      .on('touchmove', function(e){
        e.preventDefault();
        console.log('document touchmove');

        if(_loaded_chapter || _loaded_static)
          return false;

        updateNavPos(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY, true, false);
      })
      .on('touchend', function(e){
        // e.preventDefault();
        console.log("document touchend");

        if(_loaded_chapter || _loaded_static)
          return false;

        stopMoveNav();

        setTimeout(function(){_touch_started = false;}, 500);

      });

      // TODO : nav on scroll events
  };

  function updateNavPos(x,y,touch,init){
    if(touch){
      if(!init){
        _nav_pos.x += x - _prev_mouse_pos.x;
        _nav_pos.y += y - _prev_mouse_pos.y;

        // constrain nav pos on container
        _nav_pos.x = _nav_pos.x < -_center.x*2
          ? -_center.x*2
          : _nav_pos.x > _center.x*2
            ? _center.x*2
            : _nav_pos.x;
        _nav_pos.y = _nav_pos.y < -_center.y*2
          ? -_center.y*2
          : _nav_pos.y > _center.y*2
            ? _center.y*2
            : _nav_pos.y;
      }
    }else{
      _nav_pos.x = (_center.x -x)*0.5;
      _nav_pos.y = (_center.y -y)*0.5;
    }

    _prev_mouse_pos.x = x;
    _prev_mouse_pos.y = y;
    // debuging cursor
    if(_debug)
      moveDebugCursor();
  };

  function startMoveNav(){
    window.requestAnimationFrame(moveNav);
  };

  function moveNav(){
    // console.log("moveNav");
    if(!_dragging) return;

    window.requestAnimationFrame(moveNav);

    // move chapters
    for (var i = _chapitres_len - 1; i >= 0; i--)
      _chapters[i].move();

    // move header
    // _$header.css({
    //   transform:"translate3d("+(_nav_pos.x)*0.2+"px, "+(_nav_pos.y)*0.2+"px,0)"
    // });
    _$header.translate3d({x:_nav_pos.x*0.2,y:_nav_pos.y*0.2});

    // bubbles and stars dont move so smoothly on tablette ...
    // should keep it only on desktop

    // move bubbles
    // for (var i = _bubbles.length - 1; i >= 0; i--) {
      // _bubbles[i].translate3d({x:_nav_pos.x*0.4,y:_nav_pos.y*0.4});
    // };

    // move stars
    // for (var i = _stars.length - 1; i >= 0; i--) {
    //   _stars[i].translate3d({x:_nav_pos.x*-0.3,y:_nav_pos.y*-0.3});
    // };
  };

  function stopMoveNav(){
    console.log('stopMoveNav');
    clearTimeout(_timeout_dragging);
    _timeout_dragging = setTimeout(function(){
      console.log("dragging stoped");
      _dragging = false;
    },3000);
  };

  function onFullScreen(e){
    if(_$body.is('fullscreen')){
      exitFullscreen();
      _$body.removeClass('fullscreen');
    }else{
      launchIntoFullscreen(document.getElementById("root"));
      _$body.addClass('fullscreen');
    }
    if(_loaded_chapter)
      setTimeout(_loaded_chapter.buildVideos(), 100);
  };

  /*
      __               __
     / /_  ____ ______/ /_     ____  ____ __   __
    / __ \/ __ `/ ___/ __ \   / __ \/ __ `/ | / /
   / / / / /_/ (__  ) / / /  / / / / /_/ /| |/ /
  /_/ /_/\__,_/____/_/ /_/  /_/ /_/\__,_/ |___/

  */
  function updateHash(h){
    window.location.hash = h;
  };

  function initHashNav(){
    if(window.location.hash !== ''){
      // console.log("hash = "+window.location.hash);
      var p = window.location.hash.match('^#principe-([0-9]+)$');
      // console.log("p :", p);
      if(p){
        // console.log($('li.node-readmore a[href="/node/'+p[1]+'"]', 'section#node-'+p[1]));
        setTimeout((function(nid){
          $('li.node-readmore a[href="/node/'+nid+'"]', 'section#node-'+nid).trigger('click').delay(1000).trigger('click');
        }(p[1])), 500);
      }else{
        var h = window.location.hash.match('^#(.+)$');
        // console.log("h :", h);
        setTimeout((function(href){
          $('a[href="'+href+'"]', '#block-menu-menu-footer-menu').trigger('click');
        }(h[1])), 500);
      }

    }
  };
  /*
   _____ _____ _____ _____ _____ _____ _____
  |   __|_   _|  _  |_   _|     |     |   __|
  |__   | | | |     | | | |-   -|   --|__   |
  |_____| |_| |__|__| |_| |_____|_____|_____|

  */
  function initStaticLinks(){
    $('ul.menu a', _$footer).on('click', onClickStaticLink);
    _$close_static.on('click', onCloseStatic);
  };

  function onClickStaticLink(e){
    e.preventDefault();
    _$static_wrapper.removeClass('visible');
    loadStaticContent($(this).attr("href"));

    _$body.addClass('loading');
    _loaded_static = true;
    return false;
  };

  function loadStaticContent(h){
    // change hash address bar
    updateHash(h);

    $.getJSON(
      '/jee/static',
      {"href":h},
      onStaticLoaded
    );
  };

  function onStaticLoaded(data, textstatus){
    console.log('data',data);
    displayStatic(data.node);
  };

  function displayStatic(node){
    _$static_wrapper.addClass('visible').find('.inner').html(node);
    _$body.removeClass('loading');
  };

  function onCloseStatic(e){
    updateHash('');
    _$static_wrapper.removeClass('visible');
    _loaded_static = false;
  };

  /*
     ________                __
    / ____/ /_  ____ _____  / /____  _____
   / /   / __ \/ __ `/ __ \/ __/ _ \/ ___/
  / /___/ / / / /_/ / /_/ / /_/  __/ /
  \____/_/ /_/\__,_/ .___/\__/\___/_/
                  /_/
  */
  function Chapter(i, e, base_a){

    // $e.obj = this;
    this.i = i;
    this.e = e;
    this.$e = $(e);
    this.nid = this.$e.attr("id").match(/^node-(\d+)/)[1];
    this.geom = {
      base_a:base_a,
      a:0,
      r:0,
      w:this.$e.outerWidth(true),
      h:this.$e.outerHeight(true)
    }
    this.pos = {x:0,y:0};
    this.trans = {x:0, y:0,z:0};
    this.trans_previewed = {x:0, y:0,z:0};
    this.ease = randB(0.05, 0.2);

    //drifting
    // this.$title = $('h2.node-title', this.$e);
    // this.$content = $('.content:first', this.$e);
    // this.title_x = 0;
    // this.content_x = 0;
    // this.drifting_direction = Math.random()-0.5 > 0 ? 1 : -1;
    // this.drifting_time = null;

    //preview
    this.is_previewed = false;

    //mitigate
    this.is_mitigated = false;

    //parties
    this.$parties = $('.field-name-field-partie', e);
    this.parts_pos = {xs:new Array(), ys:new Array()};
    this.lines = new Array();
    this.displayPreviewAnimeStartTime = 0,
    this.displayPreviewAnimeDuration = 4000, // milli sec
    this.are_lines_animated = false;

    // chapter
    this.$n = false;
    this.$blocks = false;
    this.$vids_container = false;
    this.$vids = false;
    this.texts_pos = shuffleArray([1,2,3]);
    this.dimvideo = {w:0, h:0};
    this.$slider = null;
    this.cur_vid_playing = 0;

    // prototypes
    if (typeof Chapter.initialized == "undefined") {

      Chapter.prototype.init = function(){
        this.setInitPos();
        this.drawLines();
        this.setEvents();
        // this.initDrifiting();

        // enable nodes after intro anime
        setTimeout(
          (function(t){
            return function(){
              t.$e.addClass('enabled');
            }
          }(this)),
          randB(5000, 8000));
      };

      Chapter.prototype.setInitPos = function(){
        // distribute elements arround the center
        this.geom.a = (360/_chapitres_len*this.i+this.geom.base_a)*Math.PI/180;

        // console.log("Chapter :: setInitPos", this.$e);
        this.geom.c = Math.cos(this.geom.a);
        this.geom.s = Math.sin(this.geom.a);
        this.geom.abs_c = Math.abs(this.geom.c);
        this.geom.abs_s = Math.abs(this.geom.s);

        if (this.geom.abs_c * _container.h > this.geom.abs_s * _container.w) {
          // It crosses left or right side
          this.geom.r = (_center.x / this.geom.abs_c)*0.5;
        }else {
          // Top or bottom side
          this.geom.r = (_center.y / this.geom.abs_s)*0.5;
        }

        // change randomly radius
        if(this.i%2){
          this.geom.r = randB(this.geom.r*1.5, this.geom.r*2);
        }else{
          this.geom.r = randB(this.geom.r*0.8, this.geom.r*1.5);
        }

        this.pos.x = Math.round(_center.x+this.geom.r *  this.geom.c) - this.geom.w/2;
        this.pos.y = Math.round(_center.y+this.geom.r * -this.geom.s) - this.geom.h/2;

        // calculate the translation needed for the previewed position (center top)
        this.trans_previewed.x = -(this.pos.x - _center.x) - this.geom.w*0.5;
        this.trans_previewed.y = -this.pos.y+this.$e.find('.node-title').height()*1.3;

        this.$e.css({
          left:this.pos.x,
          top:this.pos.y
        });
      };

      Chapter.prototype.setEvents = function(){
        //http://technify.me/user-experience/javascript/jquery/trigger-custom-events-with-jquery/
        // click to preview chapter
        // $('h2.node-title, .field-name-field-partie:first>.field-name-field-vignette', this.$e)

        this.$e
          .on('click', this, function(e){
            if(_is_mobile){
              e.data.loadNode(e);
            }else{
              e.data.preview(e);
            }
          });
          // .on('click', this, function(e){
          //   // e.stopImmediatePropagation();
          //   console.log('click on chapter');
          //   e.stopPropagation();
          //   e.preventDefault();

          //   e.data.preview(e);
          //   return false;
          // });

        $('.links a, .field-name-field-vignette img', this.$e)
          .on('click', this, function(e){
            if(e.data.is_previewed){
              console.log('click, is previewed');
              e.stopPropagation();
              e.preventDefault();
              e.data.loadNode();
              return false;
            }
          });
      };

      // Chapter.prototype.initDrifiting = function(){
      //   // an other option could be to drift the whole page with the same engine than draging
      //   requestAnimationFrame(this.drift.bind(this));
      // };

      // Chapter.prototype.drift = function(timestamp){
      //   requestAnimationFrame(this.drift.bind(this));

      //   var now = new Date().getTime(),
      //       dt = now - (this.drifting_time || now);

      //   this.drifting_time = now;

      //   if(!this.is_previewed){

      //     this.title_x += (10/1000)*dt*this.drifting_direction;
      //     this.content_x += (6/1000)*dt*this.drifting_direction;

      //     this.drifting_direction =
      //       this.content_x > randB(100,130)
      //         ? -1
      //         : this.content_x < -randB(100,130)
      //           ? 1
      //           : this.drifting_direction;

      //     this.$title.translate3d({x:this.title_x});
      //     this.$content.translate3d({x:this.content_x});
      //   }
      // };

      Chapter.prototype.move = function(){
        if(this.is_previewed)
          return false;

        this.trans.x += (_nav_pos.x - this.trans.x)*this.ease;
        this.trans.y += (_nav_pos.y - this.trans.y)*this.ease;

        // this.trans.z = Math.floor(Math.sqrt(
        //   Math.pow(
        //     _center.x-(this.pos.x+this.trans.x)
        //     ,2
        //   )
        //   +
        //   Math.pow(
        //     _center.y-(this.pos.y+this.trans.y)
        //     ,2
        //   )
        // ));

        // if(this.i === 0)
        //   console.log(this.i+" this.trans.z", this.trans.z);

        this.$e.translate3d({x:this.trans.x,y:this.trans.y});
      };

      Chapter.prototype.preview = function(e){
        e.stopPropagation();
        e.preventDefault();
        console.log('preview : e',e);
        console.log('preview : this',this);

        // don't relaunch preview more that one time
        if(this.is_previewed) return false;

        console.log('is_previewed', this.is_previewed);

        this.is_previewed = true;
        _previewed_chapter = this;

        this.unMitigate();

        // close other chapters
        for (var i = _chapitres_len - 1; i >= 0; i--)
          if(i !== this.i)
            _chapters[i].closePreview().mitigate();

        this.displayPreview();

        return false;
      };

      Chapter.prototype.displayPreview = function(e){
        // define randomly position of parties
        this.resetPartsPos();

        this.are_lines_animated = false;
        requestAnimationFrame(this.animePreviewDisplay.bind(this));
      };

      Chapter.prototype.resetPartsPos = function(){
        this.parts_pos = {xs:new Array(), ys:new Array()};

        var h = _container.h * 0.6;

        for (var i = 0; i < 2; i++) {
          switch(i){
            case 0:
              this.parts_pos.xs.push(randB(180,280));
              this.parts_pos.ys.push(randB(h*0.55,h*0.6));
              break;
            case 1:
              this.parts_pos.xs.push(randB(-280,-180));
              this.parts_pos.ys.push(randB(h*0.65,h));
              break;
          }
        };
        this.parts_pos.xs = shuffleArray(this.parts_pos.xs);
        this.parts_pos.ys = shuffleArray(this.parts_pos.ys);

        // always place the first circle on top center
        this.parts_pos.xs.unshift(randB(-30,30));
        this.parts_pos.ys.unshift(120);
      };

      Chapter.prototype.closePreview = function(){
        if(!this.is_previewed) return this;

        this.$e.removeClass('previewed')
          .find('.field-name-field-partie')
          .css({transform:"none"});

        this.is_previewed = false;
        _previewed_chapter = false;

        requestAnimationFrame(this.animePreviewDisplay.bind(this));
        return this;
      };

      Chapter.prototype.mitigate = function(){
        if(this.is_mitigated) return this;
        this.$e.addClass('mitigated');
        return this;
      };

      Chapter.prototype.unMitigate = function(){
        if(this.is_mitigated) return this;
        this.$e.removeClass('mitigated');
        return this;
      };

      Chapter.prototype.drawLines = function(){
        for (var i = 0; i < 2; i++) {
          this.lines.push({
            $line:$("<div>").addClass('line', 'line-'+i).prependTo(this.$parties[i])
          });
        };
      };

      Chapter.prototype.animePreviewDisplay = function(timestamp){
        // console.log("anime line "+this.nid);
        // get the time on first anime launch
        if(this.displayPreviewAnimeStartTime === 0)
          this.displayPreviewAnimeStartTime = timestamp;

        // limit the animation time
        if(timestamp - this.displayPreviewAnimeStartTime < this.displayPreviewAnimeDuration){
          requestAnimationFrame(this.animePreviewDisplay.bind(this));
        }else{
          this.displayPreviewAnimeStartTime = 0;
        }

        // first move chapter to previewed pos (center top screen)
        if(this.is_previewed && !this.are_lines_animated){
          this.trans.x = this.trans.x + (this.trans_previewed.x - this.trans.x)*0.4;
          this.trans.y = this.trans.y + (this.trans_previewed.y - this.trans.y)*0.4;
          this.$e.translate3d({x:this.trans.x,y:this.trans.y});

          // append just once when positioning is done
          if(Math.abs(this.trans_previewed.x - this.trans.x) < 5){
            // apply new position to parties
            var that = this;
            this.$parties.each(function(i, e) {
              setTimeout(
                (function(i, e, xs, ys){
                  return function(){
                    $(e).translate3d({x:xs[i],y:ys[i]});
                  }
                }(i, e, that.parts_pos.xs, that.parts_pos.ys)),
              10);
            }); // each $parties

            //activate lines anime for next frame
            this.are_lines_animated = true;
            this.$e.addClass('previewed');
          }
        }

        // after positiong juste anime lines
        if(this.are_lines_animated){
          // get the lines length
          var l, a, pos1, pos2;
          for (var i = 0; i < this.lines.length; i++) {
            pos1 =  this.$parties.eq(i).position();
            pos2 = this.$parties.eq(i+1).position();

            l = Math.sqrt(
              Math.pow(
                pos2.left - pos1.left
                ,2
              )
              +
              Math.pow(
                pos2.top - pos1.top
                ,2
              )
            );

            // get the rotation
            a = 180 / 3.14 * Math.acos((pos2.top - pos1.top) / l);
            if(pos2.left > pos1.left)
              a *= -1;

            // console.log("a = "+a);
            this.lines[i].$line.css({
              'height':l
            }).rotate3d({z:1,a:a});
          };
        }
      };

      //  _____ _____ _____ _____    _____ _____ _____ _____ _____ _____ _____
      // |     |  _  |   __|   | |  |     |  |  |  _  |  _  |_   _|   __| __  |
      // |  |  |   __|   __| | | |  |   --|     |     |   __| | | |   __|    -|
      // |_____|__|  |_____|_|___|  |_____|__|__|__|__|__|    |_| |_____|__|__|

      Chapter.prototype.loadNode = function(e){
        console.log("Chapter :: open : nid", this.nid);

        // change hash address bar
        updateHash("principe-"+this.nid);

        _$body.addClass('loading');

        $.getJSON(
          '/jee/chapter/'+this.nid,
          {},
          this.nodeLoaded.bind(this)
        );
        _$body.addClass('chapter-displayed');
      };

      Chapter.prototype.nodeLoaded = function(json, textstatus){
        console.log('Chapter :: nodeLoaded '+this.nid+' : json', json);

        // remove previous loaded nodes
        _$chapter_wrapper.find('.node').remove();

        // insert ajax loaded into dom
        _$chapter_wrapper.append(json.node);

        // record some usefull data
        this.$n = $('.node-chapitre', _$chapter_wrapper);
        this.$blocks = $('.field-type-text-long, .field-type-text', this.$n);
        this.$vids_container = $('.field-name-field-partie', this.$n);
        this.$vids = $('iframe', this.$vids_container);
        // record the current loaded chapter
        // this will stop first interface to run
        _loaded_chapter = this;

        // wait to build correct display of chapter
        setTimeout(this.displayNode.bind(this), 100);
      };

      Chapter.prototype.displayNode = function(){
        console.log('Chapter :: displayNode '+this.nid);

        // place text blocks
        if(!_is_mobile){
          this.texts_pos = shuffleArray([1,2,3,4]);
          this.$blocks
            .each(this.placeText.bind(this))
            .pep({
              allowDragEventPropagation:false,
              disableSelect:true,
              velocityMultiplier:1
            });
        }

        // build video player
        this.buildVideos();

        // show the whole thing
        _$chapter_wrapper.addClass('visible');

        // this.$vids.eq(this.cur_vid_playing).vimeo('play');

        _$body.removeClass('loading');
      };

      Chapter.prototype.placeText = function(i, e){
        // console.log("Chapter :: placeText", e);
        switch(this.texts_pos[i]){
          case 1: // top left
            $(e)
              .css({
                top:randB(_container.h*0.05-$(e).height(),_container.h*0.15-$(e).height()),
                left:randB(_container.w*0.1,_container.w*0.2)
              })
              // .pep({debug:true, startPos:{bottom:randB(80,90),right:randB(80,90)}})
              .find('.field-label')
                .appendTo(e);
          break;
          case 2: // top right
            $(e)
              .css({
                top:randB(_container.h*0.05-$(e).height(),_container.h*0.15-$(e).height()),
                left:randB(_container.w*0.8-$(e).width(),_container.w*0.9-$(e).width())
              })
              // .pep({debug:true, startPos:{bottom:randB(80,90),right:randB(80,90)}})
              .find('.field-label')
                .appendTo(e);
          break;
          case 3: // bottom left
            $(e).css({
              top:randB(_container.h*0.8,_container.h*0.9),
              left:randB(_container.w*0.1,_container.w*0.2)
            });
            // $(e).pep({debug:true, startPos:{top:randB(80,90),left:randB(10,30)}});
          break;
          case 4: // bottom right
            $(e).css({
              top:randB(_container.h*0.8,_container.h*0.9),
              left:randB(_container.w*0.7,_container.w*0.9-$(e).width())
            });
            // $(e).pep({debug:true, startPos:{top:randB(80,90),right:randB(10,30)}});
          break;
        }
      };

      Chapter.prototype.buildVideos = function(){
        console.log('Chapter :: buildVideos');
        var $first_vid = this.$vids.eq(0);

        // compute proportional video width regarding the parent height
        this.dimvideo.h = this.$vids_container.height();
        this.dimvideo.w = (this.dimvideo.h * parseInt($first_vid.attr("width")))/parseInt($first_vid.attr("height"));

        // if resulted width if larger than container
        // first get good width and then calculate proportional height
        if(this.dimvideo.w > _container.w){
          this.dimvideo.w = _container.w *0.8;
          this.dimvideo.h = (this.dimvideo.w * parseInt($first_vid.attr("height")))/parseInt($first_vid.attr("width"));
        }

        // redim each iframe to fit
        this.$vids
          .each(this.redimVideo.bind(this))
          .each(this.setVidsEvents.bind(this));


        var marge = (_container.w-this.dimvideo.w)/4;
        this.$vids_container.css({
          width:this.dimvideo.w+marge,//*1.2,
          // height:this.dimvideo.h,
          marginLeft:marge
        });

        if(!_is_mobile){
          this.$vids_container.css({
            height:this.dimvideo.h
          });

          // add a mask on top of each iframe to avoid bad interaction with vimeo
          this.$vids.after('<div class="mask"></div>');
          // create the slider with peppermint
          this.$slider = $('.field-items', this.$vids_container).Peppermint({
            onSlideChange:this.onSlideChange.bind(this)
          });
        }
      };

      Chapter.prototype.redimVideo = function(i,e){
        var $e = $(e);
        // apply thees sizes
        $e
          .css({ width:this.dimvideo.w, height:this.dimvideo.h })
          .attr({ width:this.dimvideo.w, height:this.dimvideo.h });

        // add some padding to parent for slider display
        $e.parent()
          .css({
            paddingLeft:(_container.w-this.dimvideo.w)/4,
          });
      };

      Chapter.prototype.setVidsEvents = function(i,e){
        $(e).on("finish", this.onVidFinished.bind(this));
      };

      Chapter.prototype.onVidFinished = function(){
        if( this.cur_vid_playing < 2 ){
          this.$slider.data('Peppermint').next();
        }
      };

      // not used
      Chapter.prototype.onClickVid = function(e){
        e.stopPropagation();
        e.preventDefault();
        console.log('Chapter :: onClickVid '+this.nid, e);

        var $vid = $('iframe', e.currentTarget);

        $vid.vimeo('paused', function(data){
          console.log('paused : ', data)
          if(data){
            $vid.vimeo('play');
          }else{
            $vid.vimeo('pause');
          }
        });
        return false;
      };

      Chapter.prototype.onSlideChange = function(){
        console.log('onSlideChange nid :'+this.nid+'| current : ', this.$slider.data('Peppermint').getCurrentPos());

        //stop current video playing
        this.$vids.eq(this.cur_vid_playing).vimeo('pause');

        // start new current video
        this.cur_vid_playing = this.$slider.data('Peppermint').getCurrentPos();
        this.$vids.eq(this.cur_vid_playing).vimeo('play');
      };

      Chapter.prototype.stopAndClose = function(){
        console.log('stopAndClose nid :'+this.nid+'| current : '+this.cur_vid_playing);
        this.$vids.eq(this.cur_vid_playing).vimeo('unload');
      };

      Chapter.initialized = true;
    };

    this.init();
  };//Chapter


  /*
      __  __________    ____  __________  _____
     / / / / ____/ /   / __ \/ ____/ __ \/ ___/
    / /_/ / __/ / /   / /_/ / __/ / /_/ /\__ \
   / __  / /___/ /___/ ____/ /___/ _, _/___/ /
  /_/ /_/_____/_____/_/   /_____/_/ |_|/____/

  */
  function randB(min, max){
    return Math.random() * (max - min) + min;
  };

  //+ Jonas Raoni Soares Silva
  //@ http://jsfromhell.com/array/shuffle [v1.0]
  function shuffleArray(o){ //v1.0
    for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
  };

  if (!Date.now) {
    Date.now = function now() {
      return new Date().getTime();
    };
  }

  // http://davidwalsh.name/fullscreen
  // http://www.sitepoint.com/html5-full-screen-api/
  function launchIntoFullscreen(element) {
    // Find the right method, call on correct element
    if(element.requestFullscreen) {
      element.requestFullscreen();
    } else if(element.mozRequestFullScreen) {
      element.mozRequestFullScreen();
    } else if(element.webkitRequestFullscreen) {
      element.webkitRequestFullscreen();
    } else if(element.msRequestFullscreen) {
      element.msRequestFullscreen();
    }
  }
  // Whack fullscreen
  function exitFullscreen() {
    if(document.exitFullscreen) {
      document.exitFullscreen();
    } else if(document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if(document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    }
  }


  /*
      _       _ __
     (_)___  (_) /_
    / / __ \/ / __/
   / / / / / / /_
  /_/_/ /_/_/\__/

  */
  init();
});

/*
    ____  __________  __  ___________________   ___    _   ________  ______  ______________  _   __   __________  ___    __  _________
   / __ \/ ____/ __ \/ / / / ____/ ___/_  __/  /   |  / | / /  _/  |/  /   |/_  __/  _/ __ \/ | / /  / ____/ __ \/   |  /  |/  / ____/
  / /_/ / __/ / / / / / / / __/  \__ \ / /    / /| | /  |/ // // /|_/ / /| | / /  / // / / /  |/ /  / /_  / /_/ / /| | / /|_/ / __/
 / _, _/ /___/ /_/ / /_/ / /___ ___/ // /    / ___ |/ /|  // // /  / / ___ |/ / _/ // /_/ / /|  /  / __/ / _, _/ ___ |/ /  / / /___
/_/ |_/_____/\___\_\____/_____//____//_/    /_/  |_/_/ |_/___/_/  /_/_/  |_/_/ /___/\____/_/ |_/  /_/   /_/ |_/_/  |_/_/  /_/_____/

*/
(function() {
  var lastTime = 0;
  var vendors = ['ms', 'moz', 'webkit', 'o'];
  for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                 || window[vendors[x]+'CancelRequestAnimationFrame'];
  }

  if (!window.requestAnimationFrame)
    window.requestAnimationFrame = function(callback, element) {
      var currTime = new Date().getTime();
      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
      var id = window.setTimeout(function() { callback(currTime + timeToCall); },
        timeToCall);
      lastTime = currTime + timeToCall;
      return id;
  };

  if (!window.cancelAnimationFrame)
    window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}());


/*
    ____  __    __  _____________   _______
   / __ \/ /   / / / / ____/  _/ | / / ___/
  / /_/ / /   / / / / / __ / //  |/ /\__ \
 / ____/ /___/ /_/ / /_/ // // /|  /___/ /
/_/   /_____/\____/\____/___/_/ |_//____/
*/
// translate3d
(function($) {
  $.fn.translate3d = function(opt) {
    opt = $.extend({x:0,y:0,z:0}, opt);
    var t = "translate3d("+opt.x+"px, "+opt.y+"px,"+opt.z+"px)";
    this.css({
      "-webkit-transform": t,
      "-moz-transform":    t,
      "-ms-transform":     t,
      "-o-transform":      t,
      "transform":         t
    });
  };
  $.fn.rotate3d = function(opt) {
    opt = $.extend({x:0,y:0,z:0,a:0}, opt);
    // transform:"rotate3d(0,0,1,"+a+"deg)"
    var t = "rotate3d("+opt.x+", "+opt.y+","+opt.z+","+opt.a+"deg)";
    this.css({
      "-webkit-transform": t,
      "-moz-transform":    t,
      "-ms-transform":     t,
      "-o-transform":      t,
      "transform":         t
    });
  };
})(jQuery);

