<?php

/**
 * @file
 * Logic for retrieving and caching data from the Ontology server for Archibald.
 */

/**
 * Fetch an Ontology vocabulary.
 *
 * @param string $vocabulary_id
 *    The ID of the vocabulary on the Ontology server.
 * @param bool $raw
 *    (optional) Whether the data should be returned raw. Defaults to false.
 *
 * @return array
 *    An array of vocabulary terms, keyed by their term ID and the value being
 *    the LangString value in the current language.
 */
function archibald_ontology_load($vocabulary_id, $raw = FALSE) {
  global $language;
  $static_cache = &drupal_static(__FUNCTION__, array());

  $cid = "archibald:ontology:$vocabulary_id:{$language->language}";
  $cid .= $raw ? ':raw' : '';

  if (isset($static_cache[$cid])) {
    return $static_cache[$cid];
  }

  $cache = cache_get($cid);

  if (!empty($cache->data)) {
    return $cache->data;
  }

  // Check if the connection with the ReST API is usable. We do this AFTER
  // checking the cache, because this allows us to use this function in our
  // unit tests without actually communicating with the API.
  if (!archibald_check_module_usable(TRUE)) {
    return array();
  }

  // See if we already fetched the full tree recently. If so, we don't want to
  // load it again. We also check the static cache, as this function can be
  // called many times in a single page request.
  $full_tree_cid = 'archibald:ontology:full:raw';

  if (isset($static_cache[$full_tree_cid])) {
    $data = $static_cache[$full_tree_cid];
  }
  else {
    // Not in the static cache. Check the Drupal cache.
    $cache = cache_get($full_tree_cid);

    // Still no luck. Fetch again from the API.
    if (!isset($cache->data)) {
      try {
        $client = archibald_get_client_based_on_config();
        $data = $client->loadOntologyData('tree', array('lom-v1'));

        // Cache for the next time.
        cache_set($full_tree_cid, $data, 'cache', CACHE_TEMPORARY);
        $static_cache[$full_tree_cid] = $data;
      }
      catch (Exception $e) {
        watchdog('archibald:ontology', "Could not fetch ontology data from the ReST API. Error: %e", array('%e' => $e->getMessage()), WATCHDOG_ERROR);
        return array();
      }
    }
    else {
      $data = $cache->data;
    }
  }

  if (!empty($data[$vocabulary_id])) {
    if ($raw) {
      $terms = $data[$vocabulary_id]['terms'];
    }
    else {
      $terms = array();
      foreach ($data[$vocabulary_id]['terms'] as $term) {
        // Is this a term, or a group? If in a group, we "group" the terms under
        // its name.
        if (!empty($term['terms'])) {
          // Group.
          $name = \Educa\DSB\Client\Utils::getLSValue(
            $term['name'],
            archibald_language_fallback_list()
          );

          $terms[$name] = array();
          foreach ($term['terms'] as $child_term) {
            $terms[$name][$child_term['identifier']] = \Educa\DSB\Client\Utils::getLSValue(
              $child_term['name'],
              archibald_language_fallback_list()
            );
          }
        }
        else {
          $terms[$term['identifier']] = \Educa\DSB\Client\Utils::getLSValue(
            $term['name'],
            archibald_language_fallback_list()
          );
        }
      }
    }

    // Cache.
    $static_cache[$cid] = $terms;
    cache_set($cid, $terms, 'cache', CACHE_TEMPORARY);

    return $terms;
  }
  else {
    watchdog('archibald:ontology', "Could not fetch ontology data from the ReST API. The server responded, but the requested data was not in the payload.", array(), WATCHDOG_ERROR);
    return array();
  }
}

/**
 * Get the context information from the Ontology data for a specific item.
 *
 * @param string $vocabulary_id
 * @param string $item_id
 * @param string $default
 * 
 * @return string
 */
function archibald_get_ontology_context($vocabulary_id, $item_id, $default = 'LOMv1.0') {
  $vocabularies = &drupal_static(__FUNCTION__);

  if (empty($vocabularies)) {
    // We have to load the raw data. This is different from the "raw" data in
    // archibald_ontology_load(), which represents the raw tree. We want the
    // actual raw data from the Ontology server.
    $cid = "archibald:ontology:context";
    $cache = cache_get($cid);

    // Still no luck. Fetch again from the API.
    if (!isset($cache->data)) {
      $client = archibald_get_client_based_on_config();
      try {
        $data = $client->authenticate()->loadOntologyData('raw', array('lom-v1'));

        // Cache for the next time.
        cache_set($cid, $data, 'cache', CACHE_TEMPORARY);
        $vocabularies = $data;
      }
      catch (Exception $e) {
        watchdog('archibald:ontology', "Could not fetch ontology data from the ReST API. Error: %e", array('%e' => $e->getMessage()), WATCHDOG_ERROR);
        return array();
      }
    }
    else {
      $vocabularies = $cache->data;
    }
  }

  if (
    isset($vocabularies['vocabularies'][$vocabulary_id]) && 
    !empty($vocabularies['vocabularies'][$vocabulary_id]['terms'])
  ) {
    foreach ($vocabularies['vocabularies'][$vocabulary_id]['terms'] as $term) {
      if ($term['identifier'] == $item_id) {
        return $term['context'];
      }
    }
  }
  return $default;
}
