<?php


/**
 * Implements hook_init()
 */
function tripal_ws_init() {
  global $base_url;

  $version = 'v0.1';
  $api_url = $base_url . '/ws/' . $version;

  // Following the WC3 Hydra documentation, we want to add  LINK to the header
  // of the site that indicates where the API documentation can be found.
  // This allows a hydra-enabled client to discover the API and use it.
  $attributes = array(
    'rel' => 'http://www.w3.org/ns/hydra/core#apiDocumentation',
    'href' => $api_url . '/ws-doc/',
  );
  drupal_add_html_head_link($attributes, $header = FALSE);
}

/**
 * Implements hook_menu().
 * Defines all menu items needed by Tripal Core
 *
 * @ingroup tripal_ws
 */
function tripal_ws_menu() {

  // Web Services API callbacks.
  $items['ws'] = array(
    'title' => 'Tripal Web Services API',
    'page callback' => 'tripal_ws_services',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  $items['remote/%/%/%/%'] = array(
    'page callback' => 'tripal_ws_load_remote_entity',
    'page arguments' => array(1, 2, 3, 4),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  // Tripal Web Services setting groups
  $items['admin/tripal/storage/ws'] = array(
    'title' => 'Remote Tripal Sites',
    'description' => t("Create mashups of content using data from this site and remote Tripal sites."),
    'weight' => 20,
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array('administer tripal'),
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'),
  );
  $items['admin/tripal/storage/ws/tripal_sites'] = array(
    'title' => 'Configuration',
    'description' => t('Provides information about other Tripal sites.
        This allows data exchange and communication betwen Tripal
        enabled sites through the web services.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('tripal_ws_tripal_sites_form'),
    'access arguments' => array('administer tripal'),
    'type' => MENU_NORMAL_ITEM,
    'weight' => 0,
    'file' => 'includes/tripal_ws.admin.inc',
    'file path' => drupal_get_path('module', 'tripal_ws'),
  );
  $items['admin/tripal/storage/ws/tripal_sites/edit'] = array(
    'title' => 'Add Tripal Site',
    'description' => 'Add a Tripal site',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('tripal_ws_tripal_sites_edit_form'),
    'access arguments' => array('administer tripal'),
    'file' =>  'includes/tripal_ws.admin.inc',
    'file path' => drupal_get_path('module', 'tripal_ws'),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 2
  );
  $items['admin/tripal/storage/ws/tripal_sites/remove/%'] = array(
    'title' => 'Remove Tripal Site',
    'description' => 'Remove a Tripal site',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('tripal_ws_tripal_sites_remove_form', 6),
    'access arguments' => array('administer tripal'),
    'file' =>  'includes/tripal_ws.admin.inc',
    'file path' => drupal_get_path('module', 'tripal_ws'),
    'type' => MENU_CALLBACK,
    'weight' => 2
  );
  return $items;
}

/**
 * The callback function for all RESTful web services.
 *
 */
function tripal_ws_services() {
  $ws_path = func_get_args();
  $params = $_GET;
  unset($params['q']);

  // The web services should never be cached.
  drupal_page_is_cacheable(FALSE);

  // Using the provided version number, determine which web services
  // verion to call.
  $version = array_shift($ws_path);
  if ($version and preg_match('/v\d+\.\d+/', $version)) {

    $api_url = 'ws/' . $version;

    // Add the file with the appropriate web services.
    module_load_include('inc', 'tripal_ws', 'includes/tripal_ws.rest_' . $version);
    $version = preg_replace('/\./', '_', $version);
    $function = 'tripal_ws_services_' . $version;
    $response = array();
    if (function_exists($function)) {
      $response = $function($api_url, $ws_path, $params);
    }
  }
  else {
    // TODO: What do we do if no version is provided?
  }

  drupal_add_http_header('Content-Type', 'application/ld+json');
  print drupal_json_encode($response);
}

function tripal_ws_entity_load($entities, $type) {
  foreach ($entities as $entity) {
    //if ($entiy->type = 'TripalEntity') {
    //  dpm($entity);
    //}
  }
}

function tripal_ws_load_remote_entity($site_id, $api_version, $ctype, $id) {

  // Get the content from the web services of the remote site.
  $url = "https://dev.bioinfo.wsu.edu/~ccheng/tripal3/ws/v0.1/content/gene/12";
  $json = file_get_contents($url);
  $response = json_decode($json, TRUE);
  //dpm($response);

  // Set the title for this page to match the title provided.
  drupal_set_title($response['label']);

  // Attribute this data to the proper source.
  $source_url = l($response['label'], $response['itemPage'], array('attributes' => array('target' => '_blank')));
  $content = '<div><strong>Source:</strong> Chun-huai\'s amazing test site: ' . $source_url . '</div>';

  // Fake an entity so we can display this content using the same
  // entity type on this site.
  $entity = new TripalEntity(array(), 'TripalEntity');
  $entity->id = 807;
  $entity->type = 'TripalEntity';
  $entity->bundle = 'bio_data_266';
  $entity->term_id = 266;
  $entity->title = $response['label'];
  $entity->uid = 1;
  $entity->status = 1;

  // Get the fields and create a list of those that are attached to the bundle.
  $fields = field_info_fields();
  $my_fields = array();
  foreach ($fields as $field) {
    if (isset($field['bundles']['TripalEntity'])) {
      foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
        if ($bundle_name == 'bio_data_266') {
          $my_fields[] = $field;
        }
      }
    }
  }

  // For each field we know about that should be attached to our bundle,
  // see if we can find a corresponding entry in the results returned from
  // the web service call. If so, then add the field to our fake entity.
  foreach ($my_fields as $field) {
    // Get the semantic web term for this field.
    $field_name = $field['field_name'];
    $settings = $field['settings'];

    // If the field does not have a semantic web mapping, then skip it.
    if (!isset($settings['semantic_web'])) {
      continue;
    }

    // Convert the term into it's db and accession elements and look it up
    // for more details.
    list($vocabulary, $accession) = explode(':', $settings['semantic_web']);
    $term = tripal_get_term_details($vocabulary, $accession);

    // Convert the term to lowercase and remove spaces so we can compare
    // correctly.
    $term_name = strtolower(preg_replace('/ /', '_', $term['name']));

    // TODO: check for the term in the response makes the assumption
    // that the term is the same on both sides. This may not be true. The
    // acutal vocab and accession for both terms should be compared.
    if (isset($response[$term_name])) {

      // If this field is of type '@id' then this links out to another
      // URL where that information can be retrieved. We'll have to
      // handle that separately.
      if (isset($response['@context'][$term_name]['@type']) and
          $response['@context'][$term_name]['@type'] == '@id') {
        continue;
      }

      // For all fields that are currently attached, add the field and
      // value to the entity.
      $f = array();
      $f['und'][0]['value'] = $response[$term_name];
      $entity->$field_name = $f;
    }
  }

//   // For fields that are links rather than values then we
//   $sequences_json = file_get_contents($response['sequence']);
//   $sequences = json_decode($sequences_json, TRUE);
//   $entity->feature__residues = array();
//   foreach ($sequences['member'] as $delta => $value) {
//     $entity->feature__residues['und'][$delta]['value'] = $sequences['member'][$delta];
//   }
//   dpm($entity);

  // Generate the View for this entity
  $entities = array();
  $entities[] = $entity;
  $view = entity_view('TripalEntity', $entities);
  $content .= drupal_render($view['TripalEntity'][807]);

  return $content;

}