<?php
/**
 * @file
 * Install for a tripal data entity - creates the base table for our entity.
 */

/**
 * Implements hook_install().
 */
function tripal_entities_install() {

  // Add tripal bundle variables needed for storing additional settings for Tripal Bundles.
  tripal_insert_variable('title_format', 'A pattern including tokens that can be used to generate tripal entity titles.');
  tripal_insert_variable('url_format', 'A pattern including tokens that can be used to generate tripal entity url aliases.');
  tripal_insert_variable('description', 'The description of a Tripal Entity type/bundle.');

}

/**
 * Implements hook_uninstall().
 */
function tripal_entities_uninstall() {

/*
  // So somehow I was able to uninstall this module without deleting the bundles. This
  // caused aweful errors because fields weren't deleted so when I re-installed, the code
  // tried to create fields that were inactive (despite checking if the field exists 
  // before creating). The following code was meant to ensure that all content was deleted
  // before uninstall so these errors would not occur. Unfortunatly I am now unable to 
  // test this because the Field API module is disabling uninstall of Tripal Chado until 
  // all the content is deleted. Thus ensuring the errors described above don't occur.
  // But I'm Sure I was able to uninstall with content before... 
  // **I am slowly going crazy; Crazy going slowly am I**
  // Anyway, I'll leaving the solution code here in case I am able to repeat it in
  // the future.
  // @see https://www.drupal.org/node/1262092
  // @see https://www.drupal.org/node/1861710
  
  // First delete all TripalEntities.
  $entity_ids = (new EntityFieldQuery)->entityCondition("entity_type", "TripalEntity")->execute(); 
  $entity_ids = reset($entity_ids);
  entity_delete_multiple("TripalEntity", array_keys($entity_ids));

  // Then delete all TripalBundles.
  $bundle_ids = (new EntityFieldQuery)->entityCondition("entity_type", "TripalBundle")->execute(); 
  $bundle_ids = reset($bundle_ids);
  entity_delete_multiple("TripalBundle", array_keys($bundle_ids));
  
  // @TODO: Should we delete all TripalVocabularies and TripalTerms?
  
  // Finally purge all fields that are no longer used.
  field_purge_batch(100);
  */
}

/**
 * Implements hook_schema().
 */
function tripal_entities_schema() {

  // Adds a table for managing TripalEntity entities.
  $schema['tripal_vocab'] = tripal_entities_tripal_vocab_schema();
  $schema['tripal_term'] = tripal_entities_tripal_term_schema();
  $schema['tripal_entity'] = tripal_entities_tripal_entity_schema();
  $schema['tripal_bundle'] = tripal_entities_tripal_bundle_schema();

  // Adds a table for additional information related to bundles.
  $schema['tripal_bundle_variables'] = tripal_entities_tripal_bundle_variables_schema();

  return $schema;
}

/**
 * @section
 * Schema Definitions.
 */

/**
 * The base table for Biological Data Entities.
 *
 * This contains the actual data. For example, if you have a 5 genes and 10 mRNA then
 * this table will have 15 records and include both genes and mRNA's.
 */
function tripal_entities_tripal_entity_schema() {

  $schema = array(
    'description' => 'The base table for Tripal Vocabulary-based entities.',
    'fields' => array(
      'id' => array(
        'description' => 'The primary identifier for a vocabulary entity.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'type' => array(
        'description' => 'The type of entity. This should be an official vocabulary ID (e.g. SO, RO, GO).',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'bundle' => array(
        'description' => 'The type of bundle. This should be an official vocabulary ID (e.g. SO, RO, GO) followed by an underscore and the term accession.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'term_id' => array(
        'description' => 'The term_id for the type of entity. This term_id corresponds to a TripalTerm record.',
        'type' => 'int',
        'not null' => TRUE,
      ),
      'title' => array(
        'description' => 'The title of this node, always treated as non-markup plain text.',
        'type' => 'text',
        'not null' => TRUE,
        'default' => '',
      ),
      'uid' => array(
        'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'status' => array(
        'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 1,
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the node was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the node was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'term_id' => array('term_id'),
      'entity_changed' => array('changed'),
      'entity_created' => array('created'),
      'type' => array('type'),
      'uid' => array('uid'),
    ),
    'unique keys' => array(),
    'primary key' => array('id'),
  );
  return $schema;
}

/**
 * The base table for TripalVocab schema.
 *
 * This contains the actual data. For example, if you have a 5 genes and 10 mRNA then
 * this table will have 15 records and include both genes and mRNA's.
 */
function tripal_entities_tripal_vocab_schema() {

  // This schema only provides enough information to assign a unique ID
  // to the vocabulary. Any additonal information is added to the Entity object
  // by the selected database back-end.
  $schema = array(
    'description' => 'The base table for TripalVocab entities.',
    'fields' => array(
      'id' => array(
        'description' => 'The primary identifier for a vocab entity.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'namespace' => array(
        'description' => 'The namespace for the vocabulary (e.g. SO, PATO, etc.).',
        'type' => 'varchar',
        'length' => 10,
        'not null' => TRUE,
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the entity was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the entity was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'namespace' => array('namespace'),
      'entity_changed' => array('changed'),
      'entity_created' => array('created'),
    ),
    'unique keys' => array('namespace' => array('namespace')),
    'primary key' => array('id'),
  );
  return $schema;
}

/**
 * The base table for TripalTerm entities.
 *
 * This contains the actual data. For example, if you have a 5 genes and 10 mRNA then
 * this table will have 15 records and include both genes and mRNA's.
 */
function tripal_entities_tripal_term_schema() {

  // This schema only provides enough information to assign a unique ID
  // to the term and associate it to it's vocabulary. Any additonal information
  // is added to the Entity object by the selected database back-end.
  $schema = array(
    'description' => 'The base table for TripalTerm entities.',
    'fields' => array(
      'id' => array(
        'description' => 'The primary identifier for a term entity.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'vocab_id' => array(
        'description' => 'The vocabulary_id of the TripalVocab entity to which this term belongs.',
        'type' => 'int',
        'not null' => TRUE,
      ),
      'accession' => array(
        'description' => 'The id (or accession) of this term in the vocabulary.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'name' => array(
        'description' => 'The human readable name for this term.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the entity was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the entity was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'vocab_id' => array('vocab_id'),
      'accession' => array('accession'),
      'entity_changed' => array('changed'),
      'entity_created' => array('created'),
    ),
    'foreign keys' => array(
      'tripal_vocab' => array(
        'table' => 'tripal_vocab',
        'columns' => array(
          'vocab_id' => 'vocab_id',
        ),
      ),
    ),
    'unique keys' => array('vocab_term' => array('vocab_id', 'accession')),
    'primary key' => array('id'),
  );
  return $schema;
}

/**
 * The base table for TripalEntity entities.
 *
 * This table contains a list of Biological Data Types.
 * For the example above (5 genes and 10 mRNAs), there would only be two records in
 * this table one for "gene" and another for "mRNA".
 */
function tripal_entities_tripal_bundle_schema() {

  $schema = array(
    'description' => 'Stores information about defined tripal data types.',
    'fields' => array(
      'id' => array(
        'type' => 'serial',
        'not null' => TRUE,
        'description' => 'Primary Key: Unique numeric ID.',
      ),
      'type' => array(
        'description' => 'The type of entity (e.g. TripalEntity).',
        'type' => 'varchar',
        'length' => 64,
        'not null' => TRUE,
        'default' => '',
      ),
      'term_id' => array(
        'description' => 'The term_id for the type of entity. This term_id corresponds to a TripalTerm record.',
        'type' => 'int',
        'not null' => TRUE,
      ),
      'name' => array(
        'description' => 'The name of the bundle. This should be an official vocabulary ID (e.g. SO, RO, GO) followed by an underscore and the term accession.',
        'type' => 'varchar',
        'length' => 1024,
        'not null' => TRUE,
        'default' => '',
      ),
      'label' => array(
        'description' => 'The human-readable name of this bundle.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
    ),
    'indexes' => array(
      'name' => array('name'),
      'term_id' => array('term_id'),
    ),
    'primary key' => array('id'),
    'unique keys' => array(
      'name' => array('name'),
    ),
  );
  return $schema;
}

/**
 * Additional Tripal Bundle Information.
 *
 * This table is used for storing any additonal information describing
 * a tripal bundle. For example, this is a good place to store title/url formats.
 */
function tripal_entities_tripal_bundle_variables_schema() {

  $schema = array(
    'description' => 'This table is used for storing any additonal information describing
      a tripal bundle. For example, this is a good place to store title/url formats.',
    'fields' => array (
      'bundle_variable_id' => array (
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'bundle_id' => array (
        'type' => 'int',
        'not null' => TRUE,
      ),
      'variable_id' => array (
        'type' => 'int',
        'not null' => TRUE,
      ),
      'value' => array (
        'type' => 'text',
        'not null' => FALSE,
      ),
      'rank' => array (
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'primary key' => array (
      0 => 'bundle_variable_id',
    ),
    'unique keys' => array (
      'tripal_bundle_variables_c1' => array (
        0 => 'bundle_id',
        1 => 'variable_id',
        2 => 'rank',
      ),
    ),
    'indexes' => array (
      'tripal_bundle_variables_idx1' => array (
        0 => 'variable_id',
      ),
    ),
    'foreign keys' => array (
      'tripal_variables' => array (
        'table' => 'tripal_variables',
        'columns' => array (
          'variable_id' => 'variable_id',
        ),
      ),
    ),
  );

  return $schema;
}