/* display video on top of page at the gallery */

(function () {
  'use strict';

  var thumbnail_link_ids = [],
      current_video = 0,
      original_url = window.location.href,
      original_title = document.title;

  function update_url(name) {
    if (!name) {
      // go back to original url
      document.title = original_title;
      history.replaceState({}, original_title, original_url);
    }
    else {
      document.title = name+' - loopvid';
      history.replaceState({}, document.title, '/'+name);
    }
  }

  function set_video_max_height() {
    /* calculates and sets video video's max-height according to the screen's
     * height */
    var video, buttons, info, used_space, available_height, max_height;
    video = document.getElementById('video0');
    if (!video) { return; }
    buttons = document.getElementById('cover_buttons');
    info = document.getElementById('cover_video_info');

    /* used space is cover_inner's margins + frame's padding + info's height
     * and margin + buttons height +  4 borders */
    used_space = 2*20 + 10 + 2*4 + 4 + info.clientHeight + buttons.clientHeight;
    available_height = window.innerHeight - used_space;

    // set minimum value
    max_height = available_height;
    if (max_height < 200) {
      max_height = 200;
    }
    video.style.maxHeight = max_height+'px';
  }

  function remove_loading() {
    var video;
    document.getElementById('cover_video_frame').classList.remove('loading');
    video = document.getElementById('video0');
    if (video) {
      video.classList.remove('loading');
      video.removeEventListener('canplay', remove_loading);
    }
  }

  function increment_displayed_view_count(element) {
    var found, view_count, views;

    found = element.getElementsByClassName('view_count');
    if (found.length === 0) { return; }

    view_count = found[0];
    views = parseInt(view_count.dataset.count) + 1;
    view_count.dataset.count = views;
    view_count.innerHTML = views;
  }

  function count_view(name) {
    /* counts view for video via ajax */
    var request = new window.XMLHttpRequest();
    request.open('POST', '/blog/json/count_view', true);
    var data = new window.FormData();
    data.append('name', name);
    request.onerror = function() {
      console.log('Error counting view for video '+name);
    };
    request.send(data);

    /* increments displayed view count by one */
    increment_displayed_view_count(document.getElementById(name+'_info'));
    increment_displayed_view_count(document.getElementById('cover_video_info'));
  }

  function clear_videos() {
    /* make sure all videos are removed (there seems to be a firefox bug where
     * they'll remain playing in the background if you time a video change just
     * as the video loops) */
    var found, video;
    found = document.getElementsByTagName('video');
    while (found.length > 0) {
      video = found[0];
      // pause video
      video.pause();
      // remove sources
      while (video.firstChild) {
        video.removeChild(video.firstChild);
      }
      // remove video
      video.parentNode.removeChild(video);
    }
  }

  function populate_video_frame(sources) {
    /* creates video element and load failure info div and inserts them into
     * the video frame */
    var i, frame, video, fail_info, reload_link, sources_list, new_element;

    frame = document.getElementById('cover_video_frame');

    // clear old video
    clear_videos();

    // add new video
    frame.innerHTML = '<video id="video0" loop="loop" controls="controls" preload="auto" autoplay="autoplay"></video>';
    video = document.getElementById('video0');

    // add fail info div
    fail_info = document.getElementById('failed_to_load_info_template').cloneNode(true);
    fail_info.setAttribute('id', 'failed_to_load_info');

    // set up reload link
    reload_link = fail_info.querySelector('a.video_reloader');

    reload_link.addEventListener('click', function(event) {
      event.preventDefault();
      event.stopPropagation();

      create_video();
    });

    frame.appendChild(fail_info);

    // insert sources
    sources_list = fail_info.getElementsByClassName('sources_list')[0];

    for (i=0; i < sources.length; i++) {
      // insert list item
      new_element = document.createElement('li');
      new_element.appendChild(document.createElement('a'));
      new_element.firstChild.setAttribute('rel', 'noreferrer');
      new_element.firstChild.setAttribute('href', sources[i]);
      new_element.firstChild.appendChild(document.createTextNode(sources[i]));
      sources_list.appendChild(new_element);

      // insert source element
      new_element = document.createElement('source');
      new_element.setAttribute('src', sources[i]);
      video.appendChild(new_element);
    }

    frame.classList.add('loading');
    video.classList.add('loading');
    video.addEventListener('canplay', remove_loading);
  }

  function create_video() {
    /* creates video inside video frame using the sources found in the current
     * video's thumbnail link dataset */
    var thumbnail_link, sources, video, i, info_from, info_to;

    if (current_video > thumbnail_link_ids.length) { return; }

    // show video count
    document.getElementById('cover_video_count').innerHTML = (current_video+1)+'/'+thumbnail_link_ids.length;

    thumbnail_link = document.getElementById(thumbnail_link_ids[current_video]);
    if (!thumbnail_link) { return; }

    sources = thumbnail_link.dataset.sources.split(' ');

    // insert video and failed to load info div
    populate_video_frame(sources);

    video = document.getElementById('video0');

    // flag video as having audio
    if (thumbnail_link.dataset.has_audio === 'true') {
      video.classList.add('has_audio');
    }

    // fire custom event for other scripts to operate on the new video
    window.dispatchEvent(new window.Event('newVideoCreated'));

    // count view
    video.addEventListener('canplay', function() {
      if (thumbnail_link.dataset.viewed === 'false') {
        thumbnail_link.dataset.viewed = 'true';
        count_view(thumbnail_link.dataset.name);
      }
    });

    /* display video information */
    info_from = document.getElementById(thumbnail_link.dataset.name+'_info');
    if (info_from) {
      info_to = document.getElementById('cover_video_info');
      info_to.innerHTML = '';
      for (i=0; i < info_from.childNodes.length; i++) {
        info_to.appendChild(info_from.childNodes[i].cloneNode(true));
      }
    }

    // update url to current video
    update_url(thumbnail_link.dataset.name);

    // set video's max-height
    set_video_max_height();
  }

  function display_cover(thumbnail_link) {
    // show cover
    var cover = document.getElementById('cover');
    cover.classList.remove('hidden');

    // hide overflow for body
    document.body.classList.add('overflow_hidden');

    // create video
    if (thumbnail_link) {
      current_video = parseInt(thumbnail_link.dataset.number);
    }
    create_video();

    // capture arrow keys for navigating videos
    document.body.addEventListener('keydown', navigate);
    // adjust video video's max-height on window resize
    window.addEventListener('resize', set_video_max_height);
  }

  function thumbnail_link_click_handler(event) {
    /* jshint validthis:true */
    // only capture clicks for the left button
    if (event.button !== 0) { return; }
    // only capture unmodified cliks
    if (event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) { return; }

    event.preventDefault();

    display_cover(this);

    return false;
  }

  function close_video(event) {
    /* jshint validthis:true */

    // don't do anything unless this element is the event's target
    if (event.type === 'click' && this !== event.target) { return; }
    event.stopPropagation();
    event.preventDefault();

    // destroy video and info
    clear_videos();
    document.getElementById('cover_video_frame').innerHTML = '';
    document.getElementById('cover_video_info').innerHTML = '';

    // hide cover
    document.getElementById('cover').classList.add('hidden');
    document.body.classList.remove('overflow_hidden');

    // stop capturing keys
    document.body.removeEventListener('keydown', navigate);
    // stop listening to window resizes
    window.removeEventListener('resize', set_video_max_height);

    // go back to original url
    update_url(null);
  }

  function open_prev_video(event) {
    event.preventDefault();
    current_video--;
    // go around if necessary
    if (current_video < 0) {
      current_video += thumbnail_link_ids.length;
    }
    create_video();
  }

  function open_next_video(event) {
    event.preventDefault();
    current_video++;
    // go around if necessary
    if (current_video >= thumbnail_link_ids.length) {
      current_video -= thumbnail_link_ids.length;
    }
    create_video();
  }

  function navigate(event) {
    if (event.keyCode === 37) {
      // left arrow key, open previous video
      open_prev_video(event);
    }
    else if (event.keyCode === 39) {
      // right arrow key, open next video
      open_next_video(event);
    }
    else if (event.keyCode === 27) {
      // escape key, close video
      close_video(event);
    }
  }

  function find_thumbnail_link(name) {
    /* finds thumbnail_link based on video's name */
    var i, found;

    found = document.getElementsByClassName('thumbnail_link');
    for (i=0; i < found.length; i++) {
      if (found[i].dataset.name === name) {
        return found[i];
      }
    }
    return null;
  }

  function setup() {
    var i, found, autoplay;

    // go through all videos in gallery, store and setup events
    found = document.getElementsByClassName('thumbnail_link');
    for (i=0; i < found.length; i++) {
      thumbnail_link_ids.push(found[i].id);
      found[i].dataset.number = i;

      found[i].addEventListener('click', thumbnail_link_click_handler);
    }

    // setup button events
    document.getElementById('cover_prev_button').addEventListener('click', open_prev_video);
    document.getElementById('cover_next_button').addEventListener('click', open_next_video);
    document.getElementById('cover_close_button').addEventListener('click', close_video);

    // also close video if user clicks anywhere on the margins
    document.getElementById('cover').addEventListener('click', close_video);
    document.getElementById('cover_inner').addEventListener('click', close_video);

    /* if the user specified autoplay, open specified video if it exists, or
     * the first video if not */
    autoplay = document.getElementById('autoplay');
    if (autoplay && thumbnail_link_ids.length > 0) {
      /* if we should change the location, do it first before calling
       * display_cover() */
      if (autoplay.dataset.location) {
        original_url = autoplay.dataset.location;
        history.replaceState({}, document.title, autoplay.dataset.location);
      }

      if (autoplay.dataset.video) {
        display_cover(find_thumbnail_link(autoplay.dataset.video));
      }
      else {
        display_cover(null);
      }
    }
  }

  document.addEventListener('DOMContentLoaded', setup);
  /* remove possible leftover video before unloading the page */
  window.addEventListener('unload', clear_videos);
}());
