/**
 * @file
 * JS glue for the archibald_curricula form element.
 *
 * This code activates the Curricula UI JS component for the archibald_curricula
 * fields, parsing settings and loading data.
 */
(function($) {

Drupal.behaviors.archibaldCurricula = {

  apps: [],
  checkedFullScreen: false,
  hasFullScreen: false,
  hooks: {
    appRegistered: [],
    appReady: []
  },
  invokeAll: function(hook, data) {
    $.each(Drupal.behaviors.archibaldCurricula.hooks[hook], function(key, callback) {
      if ($.isFunction(callback)) {
        callback(data);
      }
   });
  },
  isFullScreen: function() {
    return document.fullscreenElement ||
      document.webkitFullscreenElement ||
      document.mozFullScreenElement ||
      document.msFullscreenElement;
  },
  goFullScreen: function(element) {
    if (element.requestFullscreen) {
      element.requestFullscreen();
    }
    else if (element.webkitRequestFullscreen) {
      element.webkitRequestFullscreen();
    }
    else if (element.mozRequestFullScreen) {
      element.mozRequestFullScreen();
    }
    else if (element.msRequestFullscreen) {
      element.msRequestFullscreen();
    }
  },
  cancelFullScreen: function(element) {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    }
    else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    }
    else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    }
    else if (document.msExitFullscreen) {
      document.msExitFullscreen();
    }
  },

  attach: function(context, settings) {
    var wrappers = $('.archibald-curricula-field__editor:not(.js-archibald-curricula-processed)', context);

    if (wrappers.length) {
      wrappers.each(function() {
        var $this = $(this),
            $parent = $this.parent(),
            $valueField = $parent.find('.archibald-curricula-field__item-ids'),
            activeIds = _.map($valueField.val().split(','), function(id) {
              return id.trim();
            });

        // Load the data asynchronously, activating the application once loaded.
        $.ajax({
          url: $this.attr('data-archibald-data-src'),
          dataType: 'json',
          success: function(json) {
            var app = new ArchibaldCurriculum.Core(json),
                $suggestionWrapper, settings;
            app.src = $this.attr('data-archibald-data-src');
            app.curriculum = $this.attr('data-archibald-curricula');

            // Bind our event listener, so we can add some custom markup on
            // render. This is the reason we do not pass the wrapper to the
            // constructor. If we did, it would render before we could attach
            // our event listener.
            app.on( 'app:render', function() {
              app.getWrapper().prepend('\
              <div class="archibald-curricula-field__editor__opts">\
                <div class="archibald-curricula-field__editor__opts__opt archibald-curricula-field__editor__opts__opt--confirm-opt-out">\
                  <label><input type="checkbox" checked> \
                  ' + Drupal.t("Ask for confirmation when unchecking items") + '\
                  </label>\
                </div>\
                <div class="archibald-curricula-field__editor__opts__opt archibald-curricula-field__editor__opts__opt--full-screen">\
                  ' + Drupal.t("Full screen") + '\
                </div>\
                <div class="archibald-curricula-field__editor__opts__opt archibald-curricula-field__editor__opts__opt--search">\
                  ' + Drupal.t("Search") + '\
                </div>\
              </div>\
              ');
            });

            // Allow other modules to interact with our new app.
            Drupal.behaviors.archibaldCurricula.invokeAll('appRegistered', app);

            // Store the application.
            Drupal.behaviors.archibaldCurricula.apps.push(app);

            settings = $.parseJSON($this.attr('data-archibald-settings'));
            if (typeof settings.editorLabel === 'undefined') {
              settings.editorLabel = Drupal.t("Editor", {}, { context: 'archibald:node_form' });
            }
            if (typeof settings.summaryLabel === 'undefined') {
              settings.summaryLabel = Drupal.t("Summary", {}, { context: 'archibald:node_form' });
            }
            app.setSettings(settings);
            app.setWrapper($this);
            app.createRootColumn(true);
            app.activateResponsiveLogic();

            // Activate items.
            _.each(app.getItemDatabase().filter(function(model) {
              return activeIds.indexOf(model.get('id')) !== -1;
            }), function(model) {
              model.set('active', true);
            });

            // If an item is (de)activated, update the value field. We simply
            // store all item IDs, separated by a comma.
            app.getItemDatabase().on( 'change:active', function() {
              $valueField.val(
                _.map(app.getItemDatabase().where({ active: true }), function(model) {
                  return model.get('id');
                }).join(',')
              );
            });

            // Opt out of confirm dialog logic.
            // Although we have a checkbox per editor, it is actually a global
            // setting (because of the cookie). Make sure all other applications
            // are updated as well.
            app.getWrapper().find('.archibald-curricula-field__editor__opts__opt--confirm-opt-out input').change(function() {
              var checked = $(this).is(':checked');

              // Update the settings for all applications. Don't use
              // setSettings() again, as we don't need everything to be
              // re-computed. We just want to update the prompt option.
              _.map(Drupal.behaviors.archibaldCurricula.apps, function(app) {
                app.settings.recursiveCheckPrompt = checked;
              });

              // Set a cookie to remember the selection.
              // Careful, cookies don't like Booleans... and jQuery.cookie() has
              // a really hard time returning data that can be cast to a
              // boolean. Use integer casting and strict comparison instead.
              $.cookie('archibald_confirm_opt_out', checked ? 0 : 1, { expires: 7, path: '/' });

              // Update all other checkboxes.
              $('.archibald-curricula-field__editor__opts__opt--confirm-opt-out input')
                .not(this).prop('checked', checked);
            }).attr('checked', parseInt($.cookie('archibald_confirm_opt_out')) === 0).change();

            // Search logic.
            app.getWrapper().find('.archibald-curricula-field__editor__opts__opt--search').click(function() {
              app.showSearch(true);
            });

            // Did we already check if full screen is available? If not, check
            // now.
            if (!Drupal.behaviors.archibaldCurricula.checkedFullScreen) {
              if (
                document.fullscreenEnabled ||
                document.webkitFullscreenEnabled ||
                document.mozFullScreenEnabled ||
                document.msFullscreenEnabled
              ) {
                $('html').addClass('archibald-curricula-has-fullscreen');
                Drupal.behaviors.archibaldCurricula.hasFullScreen = true;
              }
              Drupal.behaviors.archibaldCurricula.checkedFullScreen = true;
            }

            // If full screen is available, add an event listener to our button.
            if (Drupal.behaviors.archibaldCurricula.hasFullScreen) {
              app.getWrapper().find('.archibald-curricula-field__editor__opts__opt--full-screen').click(function() {
                var element = app.getWrapper();

                if (!Drupal.behaviors.archibaldCurricula.isFullScreen()) {
                  element.addClass('archibald-curricula-field__editor--is-fullscreen');
                  Drupal.behaviors.archibaldCurricula.goFullScreen(element[0]);
                }
                else {
                  element.removeClass('archibald-curricula-field__editor--is-fullscreen');
                  Drupal.behaviors.archibaldCurricula.cancelFullScreen(element[0]);
                }
              });
            }

            // Allow other modules to interact with our new app.
            Drupal.behaviors.archibaldCurricula.invokeAll('appReady', app);

            $parent.removeClass('loading');
          },
          error: function(xhr, status, error) {
            if (
              typeof xhr.responseJSON !== 'undefined' &&
              typeof xhr.responseJSON.message !== 'undefined'
            ) {
              $this.prepend('\
              <div class="messages error">\
              ' + xhr.responseJSON.message + '\
              </div>\
              ');
            }
          }
        });

        $parent.addClass('loading').addClass('js-archibald-curricula-processed');
        $this.addClass('js-archibald-curricula-processed');
      });
    }
  },

};

})(jQuery);
