<?php

require_once "charts.php";
require_once "trees.php";
require_once "obo_loader.php";

require_once "tripal_cv.api.inc";

/*************************************************************************
*
*/
function tripal_cv_init(){

   // add the tripal_cv JS and CSS
   drupal_add_css(drupal_get_path('theme', 'tripal').
                                  '/css/tripal_cv.css');
   drupal_add_js(drupal_get_path('theme', 'tripal').'/js/tripal_cv.js');

   // add the jsTree JS and CSS
   drupal_add_css(drupal_get_path('theme', 'tripal').'/js/jsTree/source/tree_component.css');
   drupal_add_js (drupal_get_path('theme', 'tripal').'/js/jsTree/source/_lib.js');
   drupal_add_js (drupal_get_path('theme', 'tripal').'/js/jsTree/source/tree_component.js');
}
/*************************************************************************
*
*/
function tripal_cv_menu() {
   $items = array();

   $items['admin/tripal/tripal_cv/cvtermpath'] = array(
     'title' => 'Update Chado cvtermpath tables',
     'description' => 'The Chado cvtermpath table provides lineage for terms and is  useful for quickly finding any ancestor parent of a term.  However, this table must be populated.  This page allows for populating of this table one vocabulary at a time',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('tripal_cv_cvtermpath_form'),
     'access arguments' => array('administer site configuration'),
     'type' => MENU_NORMAL_ITEM,
   );

   $items['admin/tripal/tripal_cv'] = array(
     'title' => 'Controlled Vocabulary Management',
     'description' => 'Manage controlled vocabularies/ontolgoies in Chado ',
     'page callback' => 'tripal_cv_admin_page',
     'access arguments' => array('administer site configuration'),
     'type' => MENU_NORMAL_ITEM,
   );

   $items['admin/tripal/tripal_cv/new'] = array(
     'title' => 'Add a Controlled Vocabulary',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('tripal_cv_add_form'),
     'access arguments' => array('access administration pages'),
     'type' => MENU_NORMAL_ITEM,
   );
   $items['admin/tripal/tripal_cv/obo'] = array(
     'title' =>'Add/Update Ontology With OBO File',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('tripal_cv_obo_form'),
     'access arguments' => array('access administration pages'),
     'type' => MENU_NORMAL_ITEM,
   );
   $items['admin/tripal/tripal_cv/edit/js'] = array(
     'title' => 'Edit Controlled Vocabularies',
     'page callback' => 'tripal_ajax_cv_edit',
     'access arguments' => array('access administration pages'),
     'type' => MENU_CALLBACK,
   );

   $items['tripal_cv_chart'] = array(
      'path' => 'tripal_cv_chart',
      'title' => t('CV Chart'),
      'page callback' => 'tripal_cv_chart',
      'page arguments' => array(1),
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
   );

   $items['tripal_cv_tree'] = array(
      'path' => 'tripal_cv_tree',
      'title' => t('CV Term Viewer'),
      'page callback' => 'tripal_cv_tree',
      'page arguments' => array(1),
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
   );
   // menu items for working with the CV module tree browser
   $items['cv_browser'] = array(
      'title' => t('CV Relationship Browser'),
      'page callback' => 'tripal_cv_show_browser',
      'access arguments' => array('access chado_cv content'),
      'type' => MENU_CALLBACK
   );
   $items['tripal_cv_init_browser'] = array(
      'path' => 'tripal_cv_init_browser',
      'title' => t('CV Browser'),
      'page callback' => 'tripal_cv_init_browser',
      'page arguments' => array(1),
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
   );
   // menu item for interaction with the tree
   $items['tripal_cv_update_tree'] = array(
      'path' => 'tripal_cv_update_tree',
      'title' => t('CV Tree'),
      'page callback' => 'tripal_cv_update_tree',
      'page arguments' => array(2,3),
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
   );
   // menu items for working with terms
   $items['tripal_cv_cvterm_info'] = array(
      'path' => 'tripal_cv_cvterm_info',
      'title' => t('CV Term Viewer'),
      'page callback' => 'tripal_cv_cvterm_info',
      'page arguments' => array(1),
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
   );

   $items['tripal_cv_cvterm_edit'] = array(
      'path' => 'tripal_cv_edit',
      'title' => t('CV Term Editor'),
      'page callback' => 'tripal_cv_cvterm_edit',
      'page arguments' => array(1),
      'access arguments' => array('edit chado_cv content'),
      'type' => MENU_CALLBACK
   );

   return $items;
}
/*******************************************************************************
 *  The following function proves access control for users trying to
 *  perform actions on data managed by this module
 */
function chado_cv_access($op, $node, $account){
  if ($op == 'create') {
      return user_access('create chado_cv content', $account);
   }

   if ($op == 'update') {
      if (user_access('edit chado_cv content', $account)) {
         return TRUE;
      }
   }
   if ($op == 'delete') {
      if (user_access('delete chado_cv content', $account)) {
         return TRUE;
      }
   }
   if ($op == 'view') {
      if (user_access('access chado_cv content', $account)) {
         return TRUE;
      }
   }
   return FALSE;
}
/*******************************************************************************
*  Set the permission types that the chado module uses.  Essentially we
*  want permissionis that protect creation, editing and deleting of chado
*  data objects
*/
function tripal_cv_perm(){
   return array(
      'access chado_cv content',
      'create chado_cv content',
      'delete chado_cv content',
      'edit chado_cv content',
   );
}

/*************************************************************************
 * Implements hook_views_api()
 * Purpose: Essentially this hook tells drupal that there is views support for
 *  for this module which then includes tripal_cv.views.inc where all the
 *  views integration code is
 */
function tripal_cv_views_api() {
	return array('api' => 2.0);
}

/*************************************************************************
*
*/
function tripal_cv_admin_page(){
   $add_url = url("admin/tripal/tripal_cv/new");
   $obo_url = url("admin/tripal/tripal_cv/obo");
   $cvtermpath_url = url("admin/tripal/tripal_cv/cvtermpath");
   $browser_url = url("cv_browser");
   $output = "<a href=\"$add_url\">Add a new controlled vocabulary</a> | ";
   $output .= "<a href=\"$browser_url\">Browse a vocabulary</a> | ";    
   $output .= "<a href=\"$obo_url\">Add/Update Ontology With OBO File</a> | ";
   $output .= "<a href=\"$cvtermpath_url\">Update the cvtermpath table</a> ";
   $output .= drupal_get_form('tripal_cv_select_form');
   $output .= '<div id="db-edit-div">Please select a vocabulary above to view or edit</div>';
   return $output;
}
/*************************************************************************
*
*/
function tripal_cv_select_form(){

	$previous_db = tripal_db_set_active('chado');  // use chado database
	// get a list of db from chado for user to choose
	$sql = "SELECT * FROM {cv} WHERE NOT name = 'tripal' ORDER BY name ";
	$results = db_query ($sql);
	tripal_db_set_active($previous_db); // use drupal database

	$cvs = array();
   $cvs[] = '';
	while ($cv = db_fetch_object($results)){
		$cvs[$cv->cv_id] = $cv->name;
	}

	$form['cvid'] = array(
      '#title' => t('Controlled Vocabulary/Ontology Name'),
      '#type' => 'select',
      '#options' => $cvs,
      '#ahah' => array(
         'path' => 'admin/tripal/tripal_cv/edit/js',
         'wrapper' => 'db-edit-div',
         'effect' => 'fade',
         'event' => 'change',
         'method' => 'replace',
      ),
	);

   return $form;
}
/*************************************************************************
*
*/
function tripal_ajax_cv_edit (){ 
   // get the database id, build the form and then return the JSON object
   $cvid = $_POST['cvid'];
   $form = drupal_get_form('tripal_cv_edit_form',$cvid);
   drupal_json(array('status' => TRUE, 'data' => $form));
}
/*************************************************************************
*
*/
function tripal_cv_add_form(&$form_state = NULL){


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


   $form['name']= array(
      '#type'          => 'textfield',
      '#title'         => t("Controlled Vocabulary name"),
      '#description'   => t('Please enter the name for this vocabulary.  This field will be ignored if an OBO file or URL is provided above'),
      '#required'      => FALSE,
      '#default_value' => $default_cv,
      '#weight'        => 1
   );

   $form['definition']= array(
      '#type'          => 'textarea',
      '#title'         => t('Description'),
      '#description'   => t('Please enter a description for this vocabulary'),
      '#default_value' => $default_desc,
      '#weight'        => 2
   );


   $form['add'] = array (
     '#type'         => 'submit',
     '#value'        => t('Add'),
     '#weight'       => 5,
     '#executes_submit_callback' => TRUE,
   );

   $form['#redirect'] = 'admin/tripal/tripal_cv';


   return $form;
}
/*************************************************************************
*
*/
function tripal_cv_obo_form(&$form_state = NULL){


	// get a list of db from chado for user to choose
	$sql = "SELECT * FROM {tripal_cv_obo} ORDER BY obo_id";
	$results = db_query ($sql);


	$obos = array();
   $obos[] = '';
	while ($obo = db_fetch_object($results)){
		$obos[$obo->obo_id] = "$obo->name  | $obo->path";
	}


   $form['obo_existing'] = array(
      '#type' =>'fieldset',
      '#title' => t('Use a Saved Ontology OBO Reference')
   );

   $form['obo_new'] = array(
      '#type' =>'fieldset',
      '#title' => t('Use a New Ontology OBO Reference')
   );


   $form['obo_existing']['existing_instructions']= array(
      '#value' => t('The Ontology OBO files listed in the drop down below have been automatically added upon 
                     installation of the Tripal CV module or were added from a previous upload.  Select
                     an OBO, then click the submit button to load the vocabulary into the database.  If the
                     vocabularies already exist then the ontology will be updated.'),
      '#weight'        => -1
   );

	$form['obo_existing']['obo_id'] = array(
      '#title' => t('Ontology OBO File Reference'),
      '#type' => 'select',
      '#options' => $obos,
      '#weight'        => 0
	);

   $form['obo_new']['path_instructions']= array(
      '#value' => t('Provide the name and path for the OBO file.  If the vocabulary OBO file 
                     is stored local to the server provide a file name. If the vocabulry is stored remotely, 
                     provide a URL.  Only provide a URL or a local file, not both.'),
      '#weight'        => 0
   );

   $form['obo_new']['obo_name']= array(
      '#type'          => 'textfield',
      '#title'         => t('New Vocabulary Name'),
      '#description'   => t('Please provide a name for this vocabulary.  After upload, this name will appear in the drop down
                             list above for use again later.'),
      '#weight'        => 1
   );



   $form['obo_new']['obo_url']= array(
      '#type'          => 'textfield',
      '#title'         => t('Remote URL'),
      '#description'   => t('Please enter a URL for the online OBO file.  The file will be downloaded and parsed.
                             (e.g. http://www.obofoundry.org/ro/ro.obo'),
      '#default_value' => $default_desc,
      '#weight'        => 2
   );
   $form['obo_new']['obo_file']= array(
      '#type'          => 'textfield',
      '#title'         => t('Local File'),
      '#description'   => t('Please enter the full system path for an OBO definition file, or a path within the Drupal
                             installation (e.g. /sites/default/files/xyz.obo).  The path must be accessible to the
                             server on which this Drupal instance is running.'),
      '#default_value' => $default_desc,
      '#weight'        => 3
   );


   $form['submit'] = array (
     '#type'         => 'submit',
     '#value'        => t('Submit'),
     '#weight'       => 5,
     '#executes_submit_callback' => TRUE,
   );

   $form['#redirect'] = 'admin/tripal/tripal_cv/obo';


   return $form;
}
/*************************************************************************
*
*/
function tripal_cv_edit_form(&$form_state = NULL,$cvid = NULL){

  
   $sql = "SELECT * FROM {cv} WHERE cv_id = %d ";
   $previous_db = tripal_db_set_active('chado');
   $cv = db_fetch_object(db_query($sql,$cvid));
   tripal_db_set_active($previous_db);


   # set the default values.  If there is a value set in the 
   # form_state then let's use that, otherwise, we'll pull 
   # the values from the database 
   $default_db = $form_state['values']['name'];
   $default_desc = $form_state['values']['description'];
   $default_url = $form_state['values']['url'];
   $default_urlprefix = $form_state['values']['urlprefix'];
   if(!$default_db){
      $default_cv = $cv->name;
   }
   if(!$default_desc){
      $default_desc = $cv->definition;
   }
 

   $form['cvid'] = array(
      '#type' => 'hidden',
      '#value' => $cvid
   );
 
   $form['name']= array(
      '#type'          => 'textfield',
      '#title'         => t("Controlled Vocabulary name"),
      '#description'   => t('Please enter the name for this vocabulary.'),
      '#required'      => FALSE,
      '#default_value' => $default_cv,
      '#weight'        => 1
   );

   $form['definition']= array(
      '#type'          => 'textarea',
      '#title'         => t('Description'),
      '#description'   => t('Please enter a description for this vocabulary'),
      '#default_value' => $default_desc,
      '#weight'        => 2
   );

   $form['update'] = array (
     '#type'         => 'submit',
     '#value'        => t('Update'),
     '#weight'       => 5,
     '#executes_submit_callback' => TRUE,
   );
   $form['delete'] = array (
     '#type'         => 'submit',
     '#value'        => t('Delete'),
     '#weight'       => 6,
     '#executes_submit_callback' => TRUE,
   );

   $form['#redirect'] = 'admin/tripal/tripal_cv';


   return $form;
}
/************************************************************************
*
*/
function tripal_cv_edit_form_submit($form, &$form_state){

   $name =  $form_state['values']['name'];
   $desc =  $form_state['values']['definition'];
   $cvid =  $form_state['values']['cvid'];
   $op   =  $form_state['values']['op'];
  
   if(strcmp($op,'Update')==0){
      $sql = "
         UPDATE {cv} SET 
           name = '%s',
           definition = '%s'
         WHERE cv_id = %d
      ";
      $previous_db = tripal_db_set_active('chado');
      $db = db_query($sql,$name,$desc,$cvid);
      tripal_db_set_active($previous_db);
      if($db){
        drupal_set_message("Controlled vocabulary updated");
      } else {
        drupal_set_message("Failed to update controlled vocabulary.");
      }
   } 
   if(strcmp($op,'Delete')==0){
      $sql = "
         DELETE FROM {cv}
         WHERE cv_id = %d
      ";
      $previous_db = tripal_db_set_active('chado');
      $db = db_query($sql,$cvid);
      tripal_db_set_active($previous_db);
      if($db){
        drupal_set_message("Controlled vocabulary deleted");
      } else {
        drupal_set_message("Failed to delete controlled vocabulary.");
      }
   }


   return '';
}
/************************************************************************
*
*/
function tripal_cv_add_form_submit($form, &$form_state){

   $name =  $form_state['values']['name'];
   $desc =  $form_state['values']['definition'];

   $sql = "
      INSERT INTO {cv}
       (name,definition)
      VALUES 
       ('%s','%s')
   ";
   $previous_db = tripal_db_set_active('chado');
   $db = db_query($sql,$name,$desc);
   tripal_db_set_active($previous_db);
   if($db){
     drupal_set_message("Controlled vocabulary added");
   } else {
     drupal_set_message("Failed to add controlled vocabulary.");
   }


   return '';
}
/************************************************************************
*
*/
function tripal_cv_obo_form_submit($form, &$form_state){
   global $user;

   $obo_id =  $form_state['values']['obo_id'];
   $obo_name =  $form_state['values']['obo_name'];
   $obo_url =  $form_state['values']['obo_url'];
   $obo_file  = $form_state['values']['obo_file'];

   $sql = "SELECT * FROM {tripal_cv_obo} WHERE obo_id = %d";
   $obo = db_fetch_object(db_query($sql,$obo_id));

   if($obo_id){ 
      $args = array($obo_id);
      tripal_add_job("Load OBO $obo->name",'tripal_cv',
         "tripal_cv_load_obo_v1_2_id",$args,$user->uid);
   } 
   else {
      if($obo_url){ 
         $args = array($obo_name,$obo_url);
         tripal_add_job("Load OBO $obo_name",'tripal_cv',
            "tripal_cv_load_obo_v1_2_url",$args,$user->uid);
      }
      elseif($obo_file){
         $args = array($obo_name,$obo_file);
         tripal_add_job("Load OBO $obo_name",'tripal_cv',
            "tripal_cv_load_obo_v1_2_file",$args,$user->uid);
      } 
   }

   return '';
}
/*************************************************************************
*
*/
function tripal_cv_cvtermpath_form () {

	$previous_db = tripal_db_set_active('chado');  // use chado database
	// get a list of db from chado for user to choose
	$sql = "SELECT * FROM {cv} WHERE NOT name = 'tripal' ORDER BY name ";
	$results = db_query ($sql);
	tripal_db_set_active($previous_db); // use drupal database

	$cvs = array();
   $cvs[] = '';
	while ($cv = db_fetch_object($results)){
		$cvs[$cv->cv_id] = $cv->name;
	}

	$form['cvid'] = array(
      '#title' => t('Controlled Vocabulary/Ontology Name'),
      '#type' => 'select',
      '#options' => $cvs,
      '#description' => t('Select a controlled vocabulary for which you would like to upate the cvtermpath.'),
	);

   $form['description'] = array(
       '#type' => 'item',
       '#value' => t("Submit a job to update chado cvtermpath table."),
       '#weight' => 1,
   );
   $form['button'] = array(
      '#type' => 'submit',
      '#value' => t('Update cvtermpath'),
      '#weight' => 2,
   );
   return $form;
}
/*************************************************************************
*
*/
function tripal_cv_cvtermpath_form_validate($form, &$form_state) {
   global $user;

   $cvid =  $form_state['values']['cvid'];

   // first get the controlled vocabulary name:
   $previous_db = tripal_db_set_active('chado');
   $cv = db_fetch_object(db_query("SELECT * FROM {cv} WHERE cv_id = %d",$cvid));
   tripal_db_set_active($previous_db);

   // Submit a job to update cvtermpath
   $job_args = array($cvid);
   if ($form_state['values']['op'] == t('Update cvtermpath')) {
      tripal_add_job("Update cvtermpath: $cv->name",'tripal_cv',
         'tripal_cv_update_cvtermpath',$job_args,$user->uid);
   }
}

/***********************************************************
 * Update the cvtermpath table
 */
function tripal_cv_update_cvtermpath($cvid = NULL, $job_id = NULL) {

   // first get the controlled vocabulary name:
   $previous_db = tripal_db_set_active('chado');
   $cv = db_fetch_object(db_query("SELECT * FROM {cv} WHERE cv_id = %d",$cvid));
   print "\nUpdating cvtermpath for $cv->name...\n";

   // now fill the cvtermpath table
   $sql = "SELECT * FROM fill_cvtermpath('%s')";
   db_query($sql,$cv->name);         
   tripal_db_set_active($previous_db);
   return;
}

/*******************************************************************************
 *  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
 */
function tripal_cv_theme () {
   return array(
      'tripal_cv_cvterm_edit' => array (
         'arguments' => array('cvterm'),
      ),
   );
}

/*************************************************************************
*/
function tripal_cv_get_cv_id($cv_name){

   $sql = "
      SELECT cv_id FROM {cv} WHERE name = '%s'
   ";
   $previous_db = tripal_db_set_active('chado');
   $cv = db_fetch_object(db_query($sql,$cv_name));
   tripal_db_set_active($previous_db);
   return $cv->cv_id;
}
/*************************************************************************
*
*/
function tripal_cv_cvterm_edit($cvterm_id){
   $sql = "
      SELECT CVT.name as cvtermname, CVT.definition, CV.name as cvname
      FROM {CVTerm} CVT
        INNER JOIN CV on CVT.cv_id = CV.cv_id
      WHERE CVT.cvterm_id = %d
   ";
   $previous_db = tripal_db_set_active('chado');
   $cvterm = db_fetch_object(db_query($sql,$cvterm_id));
   tripal_db_set_active($previous_db);
   return theme('tripal_cv_cvterm_edit',$cvterm);
}
/*************************************************************************
*
*/
function theme_tripal_cv_cvterm_edit(&$cvterm){
   $output = "
      <div id=\"cvterm\">
      <table>
        <tr><th>Term</th><td>$cvterm->cvtermname</td></tr>
        <tr><th>Vocabulary</th><td>$cvterm->cvname</td></tr>
        <tr><th>Definition</th><td>$cvterm->definition</td></tr>
      </table>
      </div>
   ";
   return $output;
}