<?php

require_once "api/tripal_organism.api.inc";
require_once "includes/tripal_organism.admin.inc";

/**
 * @file
 * @defgroup tripal_organism Organism Module
 * @ingroup tripal_modules
 */

/**
 *
 * @ingroup tripal_organism
 */
function tripal_organism_init() {

  // add the jGCharts JS and CSS
  drupal_add_js(drupal_get_path('theme', 'tripal') . '/js/tripal_organism.js');
  drupal_add_css(drupal_get_path('theme', 'tripal') . '/css/tripal_organism.css');
}
/**
 *  Provide information to drupal about the node types that we're creating
 *  in this module
 *
 * @ingroup tripal_organism
 */
function tripal_organism_node_info() {
  $nodes = array();
  $nodes['chado_organism'] = array(
    'name' => t('Organism'),
    'module' => 'chado_organism',
    'description' => t('An organism from the chado database'),
    'has_title' => FALSE,
    'title_label' => t('Organism'),
    'has_body' => FALSE,
    'body_label' => t('Organism Description'),
    'locked' => TRUE
  );
  return $nodes;
}

/**
 * Display block with organisms
 * @param op    - parameter to define the phase being called for the block
 * @param delta - id of the block to return (ignored when op is list)
 * @param edit  - when op is save, contains the submitted form data
 *
 * @ingroup tripal_organism
 */
function tripal_organism_block($op = 'list', $delta = '0', $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks['base']['info'] = t('Tripal Organism Details');
      $blocks['base']['cache'] = BLOCK_NO_CACHE;

      $blocks['description']['info'] = t('Tripal Organism Description');
      $blocks['description']['cache'] = BLOCK_NO_CACHE;

      $blocks['image']['info'] = t('Tripal Organism Image');
      $blocks['image']['cache'] = BLOCK_NO_CACHE;

      return $blocks;

    case 'view':
      if (user_access('access chado_feature content') and arg(0) == 'node' and is_numeric(arg(1))) {
        $nid = arg(1);
        $node = node_load($nid);

        $block = array();
        switch ($delta) {
          case 'base':
            $block['subject'] = t('Organism Details');
            $block['content'] = theme('tripal_organism_base', $node);
            break;
          case 'description':
            $block['subject'] = t('Organism Description');
            $block['content'] = theme('tripal_organism_description', $node);
            break;
          case 'image':
            $block['subject'] = t('Organism Image');
            $block['content'] = theme('tripal_organism_image', $node);
            break;
          default:
        }
        return $block;
      }
  }
}
/**
 *  Menu items are automatically added for the new node types created
 *  by this module to the 'Create Content' Navigation menu item.  This function
 *  adds more menu items needed for this module.
 *
 * @ingroup tripal_organism
 */
function tripal_organism_menu() {
  $items = array();

  // the administative settings menu
  $items['admin/tripal/tripal_organism'] = array(
   'title' => 'Organisms',
   'description' => 'Basic Description of Tripal Organism Module Functionality',
   'page callback' => 'theme',
   'page arguments' => array('tripal_organism_admin'),
   'access arguments' => array('adminster tripal organism'),
   'type' => MENU_NORMAL_ITEM,
  );

  $items['admin/tripal/tripal_organism/configuration'] = array(
   'title' => 'Configuration',
   'description' => 'Manage integration of Chado organisms including associated features',
   'page callback' => 'drupal_get_form',
   'page arguments' => array('tripal_organism_admin'),
   'access arguments' => array('adminster tripal organism'),
   'type' => MENU_NORMAL_ITEM,
  );


  return $items;
}
/**
 *  We need to let drupal know about our theme functions and their arguments.
 *  We create theme functions to allow users of the module to customize the
 *  look and feel of the output generated in this module
 *
 * @ingroup tripal_organism
 */
function tripal_organism_theme() {
  return array(
    'tripal_organism_base' => array(
       'arguments' => array('node' => NULL),
       'template' => 'tripal_organism_base',
    ),
    'tripal_organism_description' => array(
       'arguments' => array('node' => NULL),
       'template' => 'tripal_organism_description',
    ),
    'tripal_organism_image' => array(
       'arguments' => array('node' => NULL),
       'template' => 'tripal_organism_image',
    ),
    'tripal_organism_teaser' => array(
       'arguments' => array('node' => NULL),
       'template' => 'tripal_organism_teaser',
    ),
    'tripal_organism_admin' => array(
      'template' => 'tripal_organism_admin',
      'arguments' =>  array(NULL),
      'path' => drupal_get_path('module', 'tripal_organism') . '/theme'
    ),
  );
}
/**
 *  The following function proves access control for users trying to
 *  perform actions on data managed by this module
 *
 * @ingroup tripal_organism
 */
function chado_organism_access($op, $node, $account) {
  if ($op == 'create') {
    if (!user_access('create chado_organism content', $account)) {
      return FALSE;
      }
  }
  if ($op == 'update') {
    if (!user_access('edit chado_organism content', $account)) {
      return FALSE;
    }
  }
  if ($op == 'delete') {
    if (!user_access('delete chado_organism content', $account)) {
      return FALSE;
    }
  }
  if ($op == 'view') {
    if (!user_access('access chado_organism content', $account)) {
      return FALSE;
      }
  }
  return NULL;
}
/**
  *  Set the permission types that the chado module uses.  Essentially we
  *  want permissionis that protect creation, editing and deleting of chado
  *  data objects
  *
  *
  @ingroup tripal_organism
  */
function tripal_organism_perm() {
  return array(
    'access chado_organism content',
    'create chado_organism content',
    'delete chado_organism content',
    'edit chado_organism content',
    'adminster tripal organism',
  );
}


/**
 *
 * @ingroup tripal_organism
 */
function tripal_organism_nodeapi(&$node, $op, $teaser, $page) {

  switch ($op) {
    case 'view':
      switch ($node->type) {

      }
  }
}
/**
 *
 * @ingroup tripal_organism
 */
function tripal_organism_cron() {
   // we want to make sure that any new organisms or features that were
   // added to the database external to drupal automatically get new
   // nodes created for themselves in drupal.
//   tripal_organism_sync_organisms();
}

/**
 *
 * @ingroup tripal_organism
 */
function chado_organism_validate($node, &$form) {
  // if this is an update, we want to make sure that a different organism doesn't
  // already have this genus and speces
  if ($node->organism_id) {
    $sql = "SELECT *
          FROM {organism} O
          WHERE genus = '%s' and species = '%s' AND NOT organism_id = %d";
    $result = db_fetch_object(chado_query($sql, $node->genus, $node->species, $node->organism_id));
    if ($result) {
      form_set_error('genus', t("Update cannot proceed. The organism genus
        '$node->genus' and species '$node->species' is already present in the database."));
      watchdog('tripal_organism',
        'Update organism: genus and species already exists: %values',
        array('%values' => "genus = $node->genus, species = $node->species"),
        WATCHDOG_WARNING);
    }
  }
  // if this is an insert then check to make sure the genus and species are unique
  else {
    $values = array(
      'genus' => $node->genus,
      'species' => $node->species,
    );
    $organism = tripal_core_chado_select('organism', array('organism_id'), $values);
    if (sizeof($organism) > 0) {
      form_set_error('genus', 'Cannot add the organism with this genus and species.
        The organism already exists.');
      watchdog('tripal_organism',
        'Insert organism: genus and species already exists: %values',
        array('%values' => "genus = $node->genus, species = $node->species"),
        WATCHDOG_WARNING);
    }
  }
}
/**
 *  When a new chado_organism node is created we also need to add information
 *  to our chado_organism table.  This function is called on insert of a new node
 *  of type 'chado_organism' and inserts the necessary information.
 *
 * @ingroup tripal_organism
 */
function chado_organism_insert($node) {

  $values = array(
    'genus' => $node->genus,
    'species' => $node->species,
    'abbreviation' => $node->abbreviation,
    'common_name' => $node->common_name,
    'comment' => $node->description
  );
  // if there is an organism_id in the $node object then this must be a sync so
  // we can skip adding the organism as it is already there, although
  // we do need to proceed with the rest of the insert
  if (!$node->organism_id) {
    $organism = tripal_core_chado_insert('organism', $values);
    if (!$organism) {
      drupal_set_message(t('Unable to add organism.', 'warning'));
      watchdog('tripal_organism',
        'Insert Organism: Unable to create organism where values:%values',
        array('%values' => print_r($values, TRUE)),
        WATCHDOG_WARNING
      );
      return;
    }
    $organism_id = $organism['organism_id'];
  }
  else {
    $organism_id = $node->organism_id;
  }

  // Make sure the entry for this organism doesn't already exist in the
  // chado_organism table if it doesn't exist then we want to add it.

  if (!chado_get_id_for_node('organism', $node) ) {
  // next add the item to the drupal table
  $sql = "INSERT INTO {chado_organism} (nid, vid, organism_id) ".
         "VALUES (%d, %d, %d)";
  chado_query($sql, $node->nid, $node->vid, $organism_id);
  }

  // set the title for the node
  $record = new stdClass();
  $record->title = "$node->genus $node->species";
  $record->nid = $node->nid;
  drupal_write_record('node', $record, 'nid');
  drupal_write_record('node_revisions', $record, 'nid');

  // add the image
  chado_organism_add_image($node);
}
/**
 * Update organisms
 *
 * @ingroup tripal_organism
 */
function chado_organism_update($node) {
  if ($node->revision) {
    // there is no way to handle revisions in Chado but leave
    // this here just to make not we've addressed it.
  }
  $match = array(
    'organism_id' => chado_get_id_for_node('organism', $node),
  );
  $values = array(
    'genus' => $node->genus,
    'species' => $node->species,
    'abbreviation' => $node->abbreviation,
    'common_name' => $node->common_name,
    'comment' => $node->description
  );
  $org_status = tripal_core_chado_update('organism', $match, $values);

  // set the title for the node
  $record = new stdClass();
  $record->title = "$node->genus $node->species";
  $record->nid = $node->nid;
  drupal_write_record('node', $record, 'nid');
  drupal_write_record('node_revisions', $record, 'nid');

  // add the image
  chado_organism_add_image($node);
}
/**
 * Delete organism from both drupal and chado databases. Check dependency before
 * deleting from chado.
 *
 * @ingroup tripal_organism
 */
function chado_organism_delete($node) {
  $organism_id = chado_get_id_for_node('organism', $node);

  // if we don't have an organism id for this node then this isn't a node of
  // type chado_organism or the entry in the chado_organism table was lost.
  if (!$organism_id) {
    return;
  }

  // Remove data from the {chado_organism}, {node}, and {node_revisions} tables
  $sql_del = "DELETE FROM {chado_organism} ".
             "WHERE nid = %d ".
             "AND vid = %d";
  db_query($sql_del, $node->nid, $node->vid);
  $sql_del = "DELETE FROM {node} ".
             "WHERE nid = %d ".
             "AND vid = %d";
  db_query($sql_del, $node->nid, $node->vid);
  $sql_del = "DELETE FROM {node_revisions} ".
             "WHERE nid = %d ".
             "AND vid = %d";
  db_query($sql_del, $node->nid, $node->vid);

  // Test dependency before deleting from chado database. If a library or
  // feature depends on this organism, don't delete it

  $sql = "SELECT feature_id FROM {feature} WHERE organism_id = %d";
  $check_feature = db_result(chado_query($sql, $organism_id));
  $sql = "SELECT library_id FROM {library} WHERE organism_id = %d";
  $check_lib = db_result(chado_query($sql, $organism_id));

  if ($check_lib == 0 && $check_feature == 0) {
    tripal_core_chado_delete('organism', array('organism_id' => $organism_id));
  }
  else {
    drupal_set_message(t("Organism deleted from drupal. Warning: at least one ".
                       "library or feature depends on this organism. It was ".
               "not removed from chado."));
  }
}
/**
 *
 *
 * @ingroup tripal_organism
 */
function chado_organism_add_image($node) {
  // check to see if a file was uploaded. If so then copy it to the images
  // directory for display with the organism
  if (isset($_FILES['files']) && $_FILES['files']['name']['organism_image'] &&
    is_uploaded_file($_FILES['files']['tmp_name']['organism_image'])) {
      $dest = file_directory_path() . "/tripal/tripal_organism/images";
      $validators = array(
        'file_validate_is_image' => array(),
      );
      file_check_directory($dest, FILE_CREATE_DIRECTORY, 'organism_image');
      if (!$file = file_save_upload('organism_image', $validators, $dest)) {
        drupal_set_message(t("Organism image was not uploaded."));
      }
      // move this image into the images directory
      file_move($file->filepath, $dest . "/" . $node->nid . ".jpg", FILE_EXISTS_REPLACE);
  }
}


/**
 *  When editing or creating a new node of type 'chado_organism' we need
 *  a form.  This function creates the form that will be used for this.
 *
 * @ingroup tripal_organism
 */
function chado_organism_form($node, $param) {
  $organism = $node->organism;

  // add in the comment since it is a text field and may not be included if too big
  $organism = tripal_core_expand_chado_vars($organism, 'field', 'organism.comment');

  // get form defaults
  $abbreviation = $node->abbreviation;
  if (!$abbreviation) {
    $abbreviation = $organism->abbreviation;
  }
  $genus = $node->genus;
  if (!$genus) {
    $genus = $organism->genus;
  }
  $species = $node->species;
  if (!$species) {
    $species = $organism->species;
  }
  $common_name = $node->common_name;
  if (!$common_name) {
    $common_name = $organism->common_name;
  }
  $description = $node->description;
  if (!$description) {
    $description = $organism->comment;
  }
  $organism_image = $node->organism_image;


  $form = array();
  $form['#attributes']['enctype'] = 'multipart/form-data';

  // keep track of the organism id if we have one.  If we do have one then
  // this would indicate an update as opposed to an insert.
  $form['organism_id'] = array(
    '#type' => 'value',
    '#value' => $organism->organism_id,
  );

  $form['abbreviation']= array(
    '#type' => 'textfield',
    '#title' => t('Abbreviation'),
    '#required' => TRUE,
    '#default_value' => $organism->abbreviation,
    '#weight' => 3
  );
  $form['genus']= array(
    '#type' => 'textfield',
    '#title' => t('Genus'),
    '#required' => TRUE,
    '#default_value' => $organism->genus,
    '#weight' => 1
  );
  $form['species']= array(
    '#type' => 'textfield',
    '#title' => t('Species'),
    '#required' => TRUE,
    '#default_value' => $organism->species,
    '#weight' => 2
  );
  $form['common_name']= array(
    '#type' => 'textfield',
    '#title' => t('Common Name'),
    '#required' => TRUE,
    '#default_value' => $organism->common_name,
    '#weight' => 4
  );
  $form['description']= array(
    '#type' => 'textarea',
    '#rows' => 15,
    '#title' => t('Description'),
    '#required' => TRUE,
    '#default_value' => $organism->comment,
    '#weight' => 5
  );
  $form['organism_image']= array(
    '#type' => 'file',
    '#title' => t('Organism Image'),
    '#description' => 'Add an image for this organism',
    '#weight' => 6
  );
  return $form;
}

/**
 *  When a node is requested by the user this function is called to allow us
 *  to add auxiliary data to the node object.
 *
 * @ingroup tripal_organism
 */
function chado_organism_load($node) {
  // find the organism and add in the details
  $organism_id = chado_get_id_for_node('organism', $node);
  $values = array('organism_id' => $organism_id);

  $organism = tripal_core_generate_chado_var('organism', $values);

  // add in the description field
  $organism = tripal_core_expand_chado_vars($organism, 'field', 'organism.comment');

  $additions = new stdClass();
  $additions->organism = $organism;
  return $additions;
}

/**
 *  This function customizes the view of the chado_organism node.  It allows
 *  us to generate the markup.
 *
 * @ingroup tripal_organism
 */
function chado_organism_view($node, $teaser = FALSE, $page = FALSE) {
  // use drupal's default node view:
  $node = node_prepare($node, $teaser);
  return $node;
}


/**
 * Display help and module information
 * @param path which path of the site we're displaying help
 * @param arg array that holds the current path as would be returned from arg()
 * function
 * @return help text for the path
 *
 * @ingroup tripal_organism
 */
function tripal_organism_help($path, $arg) {
  $output = '';
  switch ($path) {
    case "admin/help#tripal_organism":
      $output = '<p>'.
                  t("Displays links to nodes created on this date") .
                '</p>';
      break;
  }
  return $output;
}


/**
 * This function uses organism_id's of all drupal organism nodes as input and
 * pull the organism information (genus, species, common_name, comment) from
 * chado database. The return type is an object array that stores $organism
 * objects sorted by common_name
 *
 * @ingroup tripal_organism
 */
function get_chado_organisms() {
  $sql_drupal = "SELECT COUNT (organism_id) FROM {chado_organism}";
  $no_orgs = db_result(db_query($sql_drupal));
  if ($no_orgs != 0) {
    $sql = "SELECT organism_id, nid FROM {chado_organism}";
    $result = chado_query($sql);
    $sql = "SELECT genus, species, common_name, comment ".
           "FROM {Organism} ".
           "WHERE organism_id=%d";
    $organisms = array();
    $count = 0;
    while ($data = db_fetch_object($result)) {
      $organism = db_fetch_object(chado_query($sql, $data->organism_id));
      $organism->node_id = $data->nid;
      // Use common_name plus $count as the key so we can sort by common
      // name later. Since common_name is not unique, we need to add $count
      // to the key
      $key = drupal_strtolower($organism->common_name) . $count;
      $organisms [$key] = $organism;
      $count ++;
    }

    //Sort organisms by common name
    ksort($organisms, SORT_STRING);
    return $organisms;
  }
}


/**
 * Implements hook_views_api()
 * Purpose: Essentially this hook tells drupal that there is views support for
 *  for this module which then includes tripal_db.views.inc where all the
 *  views integration code is
 *
 * @ingroup tripal_organism
 */
function tripal_organism_views_api() {
  return array(
    'api' => 2.0,
  );
}
/**
 *
 *
 * @ingroup tripal_organism
 */
function tripal_organism_job_describe_args($callback, $args) {

  $new_args = array();
  if ($callback == 'tripal_organism_sync_organisms') {
    $organism = tripal_core_chado_select('organism', array('genus', 'species'), array('organism_id' => $args[0]));
    $new_args['Organism'] = $organism[0]->genus ." ". $organism[0]->species;
  }
  return $new_args;
}