<?php

/**
 * Implements hook_menu().
 */
function eolapi_specimen_menu() {
  return array(
    'eolapi_specimen' => array(
      'title' => 'EOLAPI Callback',
      'description' => 'Endpoint to enable dynamic creation of EOLAPI content.',
      'page callback' => 'eolapi_specimen_callback',
      'file' => 'eolapi_specimen.ajax.inc',
      'access arguments' => array(
        'access content'
      ),
      'type' => MENU_CALLBACK
    ),
    'admin/structure/eolapi_specimen' => array(
      'title' => 'Antweb Specimen Import',
      'description' => 'Antweb Specimen import settings',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('eolapi_specimen_form'),
      'access arguments' => array('access administration pages'),
    ),
    'admin/eolapi_specimen_process_batch' => array(
      'title' => 'Antweb Specimen Import',
      'description' => 'Antweb Specimen import settings',
      'page callback' => 'eolapi_specimen_process_batch',
      'access arguments' => array('access administration pages'),
      'type' => MENU_CALLBACK,
    ),
  );
}

/**
 * Implements hook_entity_info_alter().
 */
function eolapi_specimen_entity_info_alter(&$entity_info){
  $entity_info['eolapi']['view modes']['specimen'] = array(
    'label' => t('Specimen'),
    'custom settings' => TRUE,
  );
}

/**
 * Implementation of hook_theme().
 */
function eolapi_specimen_theme(){
  $theme['eolapi_stillimage_specimen'] = array(
    'variables' => array(
      'entity' => array()
    ),
    'file' => 'eolapi_specimen.theme.inc',
  );
  return $theme;
}

/**
 * Implements hook_schema_alter().
 */
function eolapi_specimen_schema_alter(&$schema) {
  $schema['eolapi']['fields']['catalogue_number'] = array(
    'type' => 'varchar',
    'length' => 255,
    'default' => '',
    'initial' => '',
  );
  $schema['eolapi_revision']['fields']['catalogue_number'] = array(
    'type' => 'varchar',
    'length' => 255,
    'default' => '',
    'initial' => '',
  );

  $schema['eolapi']['fields']['specimen_identifier'] = array(
    'type' => 'varchar',
    'length' => 255,
    'default' => '',
    'initial' => '',
  );
  $schema['eolapi_revision']['fields']['specimen_identifier'] = array(
    'type' => 'varchar',
    'length' => 255,
    'default' => '',
    'initial' => '',
  );
}

/**
 * Implements hook_entity_property_info_alter().
 */
function eolapi_specimen_entity_property_info_alter(&$info) {
  $properties = &$info['eolapi']['bundles']['stillimage']['properties'];

  $properties['catalogue_number'] = array(
    'label' => t("Catalogue Number"),
    'type' => 'string',
    'schema field' => 'catalogue_number',
    'getter callback' => 'entity_property_verbatim_get',
    'setter callback' => 'entity_property_verbatim_set',
  );

  $properties['specimen_identifier'] = array(
    'label' => t("Specimen identifier"),
    'type' => 'string',
    'schema field' => 'specimen_identifier',
    'getter callback' => 'entity_property_verbatim_get',
    'setter callback' => 'entity_property_verbatim_set',
  );
}

/**
 * Implements hook_views_data_alter().
 */
function eolapi_specimen_views_data_alter(&$data) {
  $data['eolapi']['catalogue_number']['argument']['handler'] = 'eolapi_specimen_catalogue_number_argument';
}


function eolapi_specimen_form($form, $form_state) {

  ctools_include('dependent');

  $fid = variable_get('eolapi_specimen_xml_fid', 0);

  if ($fid && $file = file_load($fid)) {

    $form['fid'] = array(
      '#type' => 'value',
      '#value' => $fid,
    );

    $form['eol_file_info'] = array(
      '#type' => 'fieldset',
      '#title' => t('File information'),
    );
    $form['eol_file_info']['name'] = array(
      '#type' => 'item',
      '#title' => t('Name'),
      '#markup' => $file->filename,
    );
    $form['eol_file_info']['upload_date'] = array(
      '#type' => 'item',
      '#title' => t('Upload date'),
      '#markup' => format_date($file->timestamp),
    );
    $form['eol_file_info']['file_size'] = array(
      '#type' => 'item',
      '#title' => t('File size'),
      '#markup' => format_size($file->filesize) . ' (' . format_plural($file->filesize, '1 byte', '@count bytes', array()) . ')',
    );
  }

  $form['eol_file'] = array(
    '#type' => 'managed_file',
    '#title' => t('Choose new eol.xml'),
    '#upload_validators' => array(
      'file_validate_extensions' => array('xml')
    ),
    '#upload_location' => 'public://',
  );


  $form['resource'] = array(
    '#type' => 'fieldset',
    '#title' => t('Specimen content type'),
  );

  $node_type = variable_get('eolapi_specimen_node_type', NULL);
  $catalogue_field = variable_get('eolapi_specimen_catalogue_field', NULL);

  $options = array();
  $node_types = node_type_get_types();
  foreach ($node_types as $type) {
    $options[$type->type] = $type->name;
  }
  $form['resource']['node_type'] = array(
    '#type' => 'select',
    '#title' => t('Choose specimen content type'),
    '#options' => $options,
    '#default_value' => $node_type,
    '#required' => TRUE,
  );

  $fields = field_info_instances('node');
  foreach ($node_types as $type) {
    $options = array();
    foreach ($fields[$type->type] as $fieldname => $field_info) {
      $options[$fieldname] = $field_info['label'];
    }
    $form['resource']['catalogue_field_' . $type->type] = array(
      '#type' => 'select',
      '#title' => t('Choose catalogue nubmer field'),
      '#prefix' => '<div id="catalogue-field-wrapper">',
      '#suffix' => '</div>',
      '#options' => $options,
      '#process' => array('ctools_dependent_process'),
      '#dependency' => array('edit-node-type' => array($type->type)),
    );

    if ($type->type == $node_type) {
      $form['resource']['catalogue_field_' . $type->type]['#default_value'] = $catalogue_field;
    }
  }

  $form['run_batch'] = array(
    '#type' => 'checkbox',
    '#title' => t('Process EOL.XML on submit'),
    '#default_value' => TRUE,
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
//print_r($form);
  return $form;
}

function eolapi_specimen_form_submit($form, $form_state) {
  // Load the file via file.fid.

  $node_type = $form_state['values']['node_type'];
  $fieldname = $form_state['values']['catalogue_field_' . $node_type];
  variable_set('eolapi_specimen_node_type', $node_type);
  variable_set('eolapi_specimen_catalogue_field', $fieldname);

  $fid = 0;
  $file = file_load($form_state['values']['eol_file']);
  if ($file) {
    $fid = $file->fid;
    if (isset($form_state['values']['fid']) && !empty($form_state['values']['fid'])) {
      // Delete old file.
      $oldfile = file_load($form_state['values']['fid']);
      if ($oldfile) {
        file_delete($oldfile);
      }
    }
    // Change status to permanent.
    $file->status = FILE_STATUS_PERMANENT;
    // Save.
    file_save($file);
    variable_set('eolapi_specimen_xml_fid', $fid);
  } elseif (isset($form_state['values']['fid'])) {
    $fid = $form_state['values']['fid'];
  }

  // Run batch process.
  if ($form_state['values']['run_batch']) {
    if ($fid && $batch = _eolapi_specimen_generate_batch($fid, $node_type, $fieldname)) {
      batch_set($batch);
    } else {
      drupal_set_message(t('Cannot start batch. No eol.xml file found.'), 'warning');
    }
  }
}

/**
 * Implementation of hook_views_api().
 */
function eolapi_specimen_views_api() {
  return array(
    'api' => '3',
    'path' => drupal_get_path('module', 'eolapi_specimen') . '/views'
  );
}

function _eolapi_specimen_generate_batch($fid, $node_type, $fieldname) {

  $operations = array();

  $file = file_load($fid);
  if (!$file) {
    return FALSE;
  }

  // Clean up module table.
 db_delete('eolapi_specimen_batch')->execute();

  $query = db_select('taxonomy_term_data', 't');
  $query->leftJoin('taxonomy_vocabulary', 'tv', 'tv.vid = t.vid');
  $query->fields('t', array('tid', 'name'))
    ->condition('tv.machine_name', 'taxa');

  $result = $query->execute();

  $path = drupal_realpath($file->uri);

  foreach ($result as $record) {
    $operations[] = array('_eolapi_specimen_batch_prepare_process', array($record->tid, $record->name, $path));
  }

  $batch = array(
    'title' => t('Importing specimens'),
    'operations' => $operations,
    'finished' => '_eolapi_specimen_batch_finished',
  );

  return $batch;
}

function _eolapi_specimen_batch_prepare_process($tid, $taxa_name, $url, &$context) {
  $low_taxa_name = strtolower($taxa_name);
  $xml = new XMLReader();
  $xml->open($url);
  $xml_result = array();
  $taxon = NULL;
  $marker = FALSE;
  while ($xml->read()) {
    if ($xml->nodeType == XMLREADER::ELEMENT && $xml->name == 'taxon') {
      $taxon = $xml->expand();
      $xml_taxon_name = $taxon->getElementsByTagName('identifier')->item(0)->nodeValue;
      if (strtolower($xml_taxon_name) == $low_taxa_name) {
        $marker = TRUE;
      }
    }

    if ($marker && strtolower($xml_taxon_name) != $low_taxa_name) {
      break;
    }

    if ($marker && $xml->nodeType == XMLREADER::ELEMENT && $xml->name == 'dataObject' &&
      stripos($xml->readString(), 'casent')) {
      $nodeList = $xml->expand()->childNodes;
      $nodeInfo = array();
      foreach ($nodeList as $node) {
        if (!preg_match('/^\s*$/', $node->nodeValue)) {
          $nodeInfo[$node->nodeName] = $node->nodeValue;
        }
      }
      $xml_result[] = $nodeInfo;
    }
  }
  if (!empty($xml_result)) {
    $query = db_insert('eolapi_specimen_batch')->fields(array('tid', 'term_name', 'info'));
    foreach ($xml_result as $record) {
      $values = array(
        'tid' => $tid,
        'term_name' => $taxa_name,
        'info' => serialize($record),
      );
      $query->values($values);
    }
    $query->execute();
  }

  $context['results']['processed'][] = $tid;
  $xml->close();
  $context['message'] = t('!number prepared.', array('!number' => $taxa_name));
}

function _eolapi_specimen_batch_process($tid, $taxa_name, $info, &$context) {
  $info = unserialize($info);
  _eolapi_specimen_save_eolapi($tid, $info);

  $context['results']['processed'][] = $tid;
  $context['message'] = t('!number processed.', array('!number' => $taxa_name));
}

function _eolapi_specimen_batch_finished($success, $results, $operations) {
  if ($success) {
    $message = format_plural(isset($results['prepared']) ? count($results['prepared']) : 0, 'One item prepared.', '@count items prepared.');
    drupal_goto('admin/eolapi_specimen_process_batch');
  } else {
    $message = t('Preparing finished with an error.');
  }
  drupal_set_message($message);
}

function eolapi_specimen_process_batch() {
  $batch = _eolapi_specimen_process_batch_generate();
  batch_set($batch);
  batch_process('admin/structure/eolapi_specimen');
  exit;
}

function _eolapi_specimen_process_batch_generate() {
  $operations = array();
  $query = db_select('eolapi_specimen_batch', 'esb');
  $query->fields('esb', array('tid', 'term_name', 'info'));

  $result = $query->execute();

  foreach ($result as $record) {
    $operations[] = array('_eolapi_specimen_batch_process', array($record->tid, $record->term_name, $record->info));
  }

  $batch = array(
    'title' => t('Importing specimens'),
    'operations' => $operations,
    'finished' => '_eolapi_specimen_process_batch_finished',
  );

  return $batch;
}

function _eolapi_specimen_process_batch_finished($success, $results, $operations) {
  if ($success) {
    $message = format_plural(isset($results['processed']) ? count($results['processed']) : 0, 'One item processed.', '@count items processed.');
  } else {
    $message = t('Processing finished with an error.');
  }
  // Clean up module table.
  db_delete('eolapi_specimen_batch')->execute();
  drupal_set_message($message);
  drupal_goto('admin/structure/eolapi_specimen');
}

function _eolapi_specimen_save_eolapi($tid, $imageinfo) {
  if (!is_array($imageinfo) || empty($imageinfo)) {
    return FALSE;
  }
  set_time_limit(60);
  $order = array(
    'head' => '0',
    'profile' => '1',
    'dorsal' => '2',
    'label' => '3',
    'low' => '4',
  );

  if (!isset($imageinfo['dc:identifier']) || empty($imageinfo['dc:identifier'])) {
    return FALSE;
  }

  preg_match('/casent[0-9]+/i', $imageinfo['dc:identifier'], $matches);
  if (!is_array($matches) || empty($matches)) {
    return FALSE;
  }

  $number = strtoupper(current($matches));

  $row = db_select('eolapi', 'e')
    ->condition('specimen_identifier', $imageinfo['dc:identifier'])
    ->condition('catalogue_number', $number)
    ->fields('e')
    ->range(0,1)
    ->execute()
    ->fetch();

  if ($row) {
    $eolapi = entity_load_single('eolapi', $row->eid);
  } else {
    // New eolapi data object
    $eolapi = new stdClass();
    $eolapi->type = isset($imageinfo['dataType']) ? strtolower($imageinfo['dataType']) : 'stillimage';
    if(substr($eolapi->type, 0, 4) == 'http'){
      $eolapi->type = array_pop(explode("/", $eolapi->type));
    }

    $eolapi->license = isset($imageinfo['license']) ? $imageinfo['license'] : '';
    $eolapi->data = serialize($imageinfo);
    $eolapi->catalogue_number = $number;
    $eolapi->specimen_identifier = $imageinfo['dc:identifier'];

    // Add taxonomy term tid.
    $eolapi->eolapi_taxonomy = array(
      'und' => array(
        array(
          'tid' => $tid
        )
      )
    );

    entity_save('eolapi', $eolapi);
  }

  if($eolapi->type == 'stillimage' && isset($eolapi->eolapi_image) && count($eolapi->eolapi_image)) {
    if (isset($eolapi->eolapi_image[LANGUAGE_NONE][0]['title'])) {
      $matches = array();
      preg_match('/(head|profile|dorsal|label|low)/', $eolapi->eolapi_image[LANGUAGE_NONE][0]['title'], $matches);
      if (!empty($matches)) {
        $matches = current($matches);
        $matches = strtolower($matches);
        $eolapi->weight = (isset($order[$matches])) ? $order[$matches] : 0;
      }
    }
    entity_save('eolapi', $eolapi);
  }

  if($eolapi->type == 'stillimage' && (!isset($eolapi->eolapi_image) || !count($eolapi->eolapi_image))) {
    // Download the original image so that we can perform image_styles magic on
    // it.
    $file = file_save_data(@file_get_contents($imageinfo['mediaURL']));
    if(!$file->filesize || !$file->uri){
      //continue;
    }

    if (isset($imageinfo['dc:title'])) {
      $matches = array();
      preg_match('/(head|profile|dorsal|label|low)/', $imageinfo['dc:title'], $matches);
      if (!empty($matches)) {
        $matches = current($matches);
        $matches = strtolower($matches);
        $eolapi->weight = (isset($order[$matches])) ? $order[$matches] : 0;
      }
    }

    $toolkit = image_get_toolkit();
    $image = new stdClass();
    $image->source = $file->uri;
    $image->toolkit = $toolkit;
    $details = image_toolkit_invoke('get_info', $image);
    $file = file_move($file, 'public://eolapi/' . $eolapi->eid . '-' . $eolapi->erid . '.' . $details['extension'], FILE_EXISTS_REPLACE);
    $file->title = isset($imageinfo['dc:title']) ? $imageinfo['dc:title'] : '';
    $file->alt = '';
    $file->width = $details['width'];
    $file->height = $details['height'];
    $file->filename = $eolapi->eid . '-' . $eolapi->erid . '.' . $details['extension'];
    file_save($file);
    $eolapi->eolapi_image = array(
      'und' => array(
        (array)$file
      )
    );
    entity_save('eolapi', $eolapi);
  }
}
