<?php

/**
 * @file
 * Provide a base module for using the educa.ch Curricula UI component.
 *
 * The Archibald Curricula module allows other modules to use the Curricula UI
 * Javascript component. This component is designed to help editors select
 * curricula data for descriptions, like PER (https://www.plandetudes.ch/) or
 * LP21 (http://lehrplan.ch/).
 */

/**
 * Implements hook_theme().
 */
function archibald_curricula_theme() {
  $path = drupal_get_path('module', 'archibald_curricula');

  $base = array(
    'file' => 'theme.inc',
    'path' => "$path/theme",
  );

  return array(
    'archibald_curricula_summary' => array(
      'variables' => array('items' => NULL, 'html' => FALSE),
    ) + $base,
    'archibald_curricula_json_curricula' => array(
      'variables' => array(
        'items' => NULL,
        'item_theme_callback' => 'archibald_curricula_json_curricula_item',
        'langcode' => NULL,
      ),
    ) + $base,
    'archibald_curricula_json_curricula_item' => array(
      'variables' => array(
        'item' => NULL,
        'children' => NULL,
        'langcode' => NULL,
        'html' => FALSE,
      ),
    ) + $base,
    'archibald_curricula_json_classification' => array(
      'variables' => array(
        'items' => NULL,
        'item_theme_callback' => 'archibald_curricula_json_classification_item',
      ),
    ) + $base,
    'archibald_curricula_json_classification_item' => array(
      'variables' => array('item' => NULL, 'langcode' => NULL),
    ) + $base,
  );
}

/**
 * Implements hook_element_info().
 */
function archibald_curricula_element_info() {
   return array(
    'archibald_curricula' => array(
     '#input' => TRUE,
     '#theme_wrappers' => array('form_element'),
     '#process' => array('archibald_curricula_field_process'),
     '#curricula_data_src' => NULL,
     '#curricula_settings' => array(),
     '#curricula_name' => NULL,
  ));
}

/**
 * Implements hook_libraries_info().
 */
function archibald_curricula_libraries_info() {
  return array(
    'backbone' => array(
      'name' => 'Backbone',
      'vendor url' => 'http://backbonejs.org/',
      'download url' => 'https://github.com/jashkenas/backbone/releases',
      'drush download url' => 'https://github.com/jashkenas/backbone/archive/1.3.3.zip',
      'version arguments' => array(
        'file' => 'package.json',
        'pattern' => '/"version":\s*"(\d+\.\d+\.\d+)"/',
        'lines' => 50,
      ),
      'files' => array(
        'js' => array('backbone.js'),
      ),
    ),
    'underscore' => array(
      'name' => 'Underscore',
      'vendor url' => 'http://underscorejs.org/',
      'download url' => 'https://github.com/jashkenas/underscore/releases',
      'drush download url' => 'https://github.com/jashkenas/underscore/archive/1.8.3.zip',
      'version arguments' => array(
        'file' => 'package.json',
        'pattern' => '/"version":\s*"(\d+\.\d+\.\d+)"/',
        'lines' => 50,
      ),
      'files' => array(
        'js' => array('underscore.js'),
      ),
    ),
    'nanoScrollerJS' => array(
      'name' => 'nanoScrollerJS',
      'vendor url' => 'https://jamesflorentino.github.io/nanoScrollerJS/',
      'download url' => 'https://github.com/jamesflorentino/nanoScrollerJS/releases',
      'drush download url' => 'https://github.com/jamesflorentino/nanoScrollerJS/archive/0.8.7.zip',
      'version arguments' => array(
        'file' => 'package.json',
        'pattern' => '/"version":\s*"(\d+\.\d+\.\d+)"/',
        'lines' => 50,
      ),
      'files' => array(
        'js' => array('bin/javascripts/jquery.nanoscroller.js'),
        'css' => array('bin/css/nanoscroller.css'),
      ),
    ),
    'curricula-ui' => array(
      'name' => 'Curricula UI',
      'vendor url' => 'http://org.educa.ch/',
      'download url' => 'https://github.com/educach/curricula-ui/releases',
      'drush download url' => 'https://github.com/educach/curricula-ui/archive/1.0.0.zip',
      'version callback' => 'archibald_get_library_version',
      'files' => array(
        'js' => array(
          'app/js/models.js',
          'app/js/views.js',
          'app/js/core.js',
        ),
        'css' => array(
          'app/css/styles.css',
        ),
      ),
    ),
  );
}

/**
 * Process callback for our custom archibald_curricula element.
 */
function archibald_curricula_field_process($element, &$form_state, $complete_form) {
  if (!archibald_curricula_load_libraries()) {
    drupal_set_message(t("Please check your site's status. Some libraries are missing, and the Curricula UI element cannot be started."), 'error');
    // Create an element, so forms don't loose previous data.
    $element['item_ids'] = array(
      '#type' => 'hidden',
      '#value' => $element['#value'],
    );
    return $element;
  }

  $path = archibald_curricula_get_path();
  $element['#attached'] = array(
    'js' => array("$path/js/archibald_curricula.js"),
    'css' => array("$path/css/archibald_curricula.css"),
    'library' => array(
      array('system', 'ui.autocomplete'),
    ),
  );

  // We have special styles for certain admin themes, to make them look a
  // bit better. We use the Archibald archibald_enhance_admin_themes setting for
  // this. Although this module doesn't specifically depend on Archibald, it is
  // not worth the effort to have a similar setting just for our module.  Make
  // sure the admin theme is active, that it is and that the user has access
  // to it.
  if (variable_get('archibald_enhance_admin_themes', 0) &&
    in_array(variable_get('admin_theme', 0), array('seven', 'adminimal')) &&
    user_access('view the administration theme')
  ) {
    $element['#attached']['css'][] = "$path/css/archibald_curricula.admin_theme." . variable_get('admin_theme', 0) . '.css';
  }

  $element['editor'] = array(
    '#markup' => '<div ' . drupal_attributes(array(
      'data-archibald-data-src' => $element['#curricula_data_src'],
      'data-archibald-settings' => json_encode((object) $element['#curricula_settings']),
      'data-archibald-curricula' => isset($element['#curricula_name']) ?
        $element['#curricula_name'] :
        NULL,
      'class' => array('archibald-curricula-field__editor'),
    )) . '></div>',
  );

  $element['item_ids'] = array(
    '#type' => 'textarea',
    '#value' => isset($element['#value']['item_ids']) ? $element['#value']['item_ids'] : (
      isset($element['#value']) ?
        $element['#value'] :
        ''
    ),
    '#attributes' => array(
      'class' => array('archibald-curricula-field__item-ids'),
    ),
  );

  return $element;
}

/**
 * Helper function to load all libraries.
 *
 * @return bool
 *    True if all libraries were correctly installed and loaded, false
 *    otherwise.
 */
function archibald_curricula_load_libraries() {
  $result = &drupal_static(__FUNCTION__);
  if (!isset($result)) {
    $result = TRUE;
    foreach (array(
      'underscore',
      'backbone',
      'nanoScrollerJS',
      'curricula-ui',
    ) as $library_name) {
      $library = libraries_load($library_name);

      if (empty($library['installed'])) {
        $result = FALSE;
        return $result;
      }
    }
  }
  return $result;
}

/**
 * Helper function to get the module's path.
 *
 * This information is statically cached.
 *
 * @return string
 *    The path to the Archibalc curricula module.
 */
function archibald_curricula_get_path() {
  $path = &drupal_static(__FUNCTION__);
  if (!isset($path)) {
    $path = drupal_get_path('module', 'archibald_curricula');
  }
  return $path;
}

/**
 * Get an error message when curriculum data is not available.
 *
 * This message is only useful for modules which provide a way to refresh their
 * curriculum data via the site's report page. The reason this function is
 * provided is to remain DRY, as several Archibald submodules require a similar
 * message to be displayed. As they all rely on Archibald Curricula, it makes
 * sense to provide this helper function here, although it is not, strictly
 * speaking, useful for the module itself.
 *
 * @param string $name
 *    The name of the curriculum.
 *
 * @return string
 *    The error message.
 */
function archibald_curricula_curricula_load_error($name) {
  $message =  t("Could not load the %name curriculum data.", array('%name' => $name));
  if (user_access('administer site configuration')) {
    $message .= ' ' . t("Please go to <a href='!url'>the status page</a> to refresh the data.", array(
      '!url' => url('admin/reports/status'),
    ));
  }
  else {
    $message .= ' ' . t("Please contact your site administrator.");
  }

  return $message;
}
