<?php

// -----------------------------------------------------------------------
// Hooks

/**
 * Implementation of hook_permission().
 */
function ets_permission() {
  return array(
    'perform experiments' => array(
      'title' => t('Can perform experiments'),
      'description' => t('Can perform experiments'),
    ),
    'perform inactive experiments' => array(
      'title' => t('Can perform INACTIVE experiments'),
      'description' => t('Can perform inactive experiments.'),
    ),
  );
}

function ets_init() {
  module_load_include('inc', 'ets', 'ets.conditions');
  drupal_add_css(drupal_get_path('module', 'ets') . '/css/experiment.css', array('type' => 'file'));
  drupal_add_js(drupal_get_path('module', 'ets') . '/ets.js');
}

/**
 * Implementation of hook_menu().
 */
function ets_menu() {
  $items = array();
  $items['ets/services/watchdog'] = array(
    'title'            => 'Log a message in the watchdog (ajax)',
    'page callback'    => 'ets_services_watchdog',
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/ping'] = array(
    'title'            => 'We are alive!',
    'page callback'    => 'ets_services_ping',
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/instance-scores'] = array(
    'title'            => 'We are alive!',
    'page callback'    => 'ets_services_instance_scores',
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/options-save/%node'] = array(
    'title'            => 'Saving custom experiment options',
    'page callback'    => 'ets_services_options_save',
    'page arguments'   => array(3),
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/options-load/%node'] = array(
    'title'            => 'Loading custom experiment options',
    'page callback'    => 'ets_services_options_load',
    'page arguments'   => array(3),
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/user-stats'] = array(
    'title'            => 'Update endpoint for users stats',
    'page callback'    => 'ets_services_user_stats',
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/exp-stats'] = array(
    'title'            => 'Update endpoint for experiments stats',
    'page callback'    => 'ets_services_experiment_stats',
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/user-info/%user'] = array(
    'title'            => 'User info (AJAX)',
    'page callback'    => 'ets_services_user_info',
    'page arguments'   => array(3),
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/exp-info/%node'] = array(
    'title'            => 'Experiment info (AJAX)',
    'page callback'    => 'ets_services_experiment_info',
    'page arguments'   => array(3),
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/services/close-hunged-instances'] = array(
    'title'            => 'Close hunged instances',
    'page callback'    => 'ets_services_close_hunged_instances',
    'access arguments' => array('access content'),
    'file'             => 'ets.services.inc',
    'type'             => MENU_CALLBACK,
  );
  $items['ets/exp-join/%node'] = array(
    'title'            => 'Joining an experiment',
    'page callback'    => 'ets_join_experiment',
    'file'             => 'ets.pages.inc',
    'page arguments'   => array(2),
    'access arguments' => array('perform experiments'),
    'type'             => MENU_CALLBACK,
  );
  $items['ets/exp-perform/%node'] = array(
    'title'            => 'Perform an experiment',
    'page callback'    => 'ets_perform_experiment',
    'file'             => 'ets.pages.inc',
    'page arguments'   => array(2,3,4),
    'access arguments' => array('perform experiments'),
    'type'             => MENU_CALLBACK,
  );
  $items['ets/exp-perform-raw/%node'] = array(
    'title'            => 'Perform an experiment (raw version)',
    'page callback'    => 'ets_perform_experiment_raw',
    'file'             => 'ets.pages.inc',
    'page arguments'   => array(2,3,4),
    'access arguments' => array('perform experiments'),
    'type'             => MENU_CALLBACK,
  );
  /*$items['ets/monitor'] = array(
    'title'            => 'Monitor',
    'page callback'    => 'ets_monitor',
    'file'             => 'ets.pages.inc',
    //'access arguments' => array('perform experiments'),
    'access arguments' => TRUE,
    'type'             => MENU_CALLBACK,
  );*/
  $items['ets/shared_experiments'] = array(
    'title'            => 'Shared Experiments',
    'page callback'    => 'ets_shared_experiments',
    'file'             => 'ets.pages.inc',
    'access arguments' => array('administer site configuration'),
    'type'             => MENU_NORMAL_ITEM,
  );
  $items['ets/instances-monitor'] = array(
    'title'            => 'Instances Monitor',
    'page callback'    => 'ets_instances_monitor',
    'file'             => 'ets.pages.inc',
    'access arguments' => array('administer site configuration'),
    'type'             => MENU_NORMAL_ITEM,
  );
  $items['ets/managers-monitor'] = array(
    'title'            => 'Managers Monitor',
    'page callback'    => 'ets_managers_monitor',
    'file'             => 'ets.pages.inc',
    'access arguments' => array('administer site configuration'),
    'type'             => MENU_NORMAL_ITEM,
  );
  $items['admin/config/system/ets'] = array(
    'title'            => 'ETS Services Setup',
    'page callback'    => 'drupal_get_form',
    'file'             => 'ets.pages.inc',
    'page arguments'   => array('ets_settings_form'),
    'access arguments' => array('administer site configuration'),
  );

  $items['ets/towns-update'] = array(
    'title'            => 'Updating towns coordinates',
    'page callback'    => 'ets_towns_update',
    'access arguments' => array('administer site configuration'),
    'type'             => MENU_CALLBACK,
  );
  
  $items['ets/exp-stats'] = array(
    'title'            => 'Experiments statistics',
    'page callback'    => 'ets_page_experiments_statistics',
    'file'             => 'ets.pages.inc',
    'access arguments' => array('create experiment content'), // Drupal permission
    'type'             => MENU_CALLBACK,
  );

  $items['ets/conditions'] = array(
    'access callback'   => FALSE,
  );

  $items['ets/conditions/new'] = array(
    'title'             => 'Creates the HTML for a new experiment condition',
    'page callback'     => 'ets_conditions_new_ahah',
    'delivery callback' => 'ajax_deliver',
    'file'             => 'ets.conditions.inc',
    'access callback'   => TRUE,
    'type'              => MENU_CALLBACK,
  );

  $items['ets/conditions/load'] = array(
    'title'             => 'Load the join conditions for a specific node',
    'page callback'     => 'ets_conditions_load_ahah',
    'delivery callback' => 'ajax_deliver',
    'file'              => 'ets.conditions.inc',
    'access callback'   => TRUE,
    'type'              => MENU_CALLBACK,
  );

  $items['ets/conditions/ac'] = array(
    'title'             => 'Generic autocomplete for a condition fields',
    'page callback'     => 'ets_conditions_ac',
    'file'              => 'ets.conditions.inc',
    'access callback'   => TRUE,
    'type'              => MENU_CALLBACK,
  );

  $items['user/%user/ets-stats'] = array(
    'title'             => t('Statistics'),
    'page callback'     => 'ets_page_user_statistics',
    'file'              => 'ets.pages.inc',
    'page arguments'    => array(1),
    'access callback' => 'user_view_access',
    'access arguments' => array(1),
    'type'              => MENU_LOCAL_TASK,
  );

  $items['user/%user/ets-stats-hist/%node'] = array(
    'title'             => t('History'),
    'page callback'     => 'ets_page_user_statistics_history',
    'file'              => 'ets.pages.inc',
    'page arguments'    => array(1,3),
    'access callback' => 'user_view_access',
    'access arguments' => array(1),
    'type'              => MENU_DEFAULT_LOCAL_TASK,
  );

  $items['node/%node/ets-stats'] = array(
    'title'             => t('Statistics'),
    'page callback'     => 'ets_page_experiment_statistics',
    'page arguments'    => array(1),
    'file'              => 'ets.pages.inc',
    'access arguments'  => array(1),
    'access callback'   => 'ets_access_view_experiment_statistics',
    'type'              => MENU_LOCAL_TASK,
  );

  $items['node/%node/ets-ranks'] = array(
    'title'             => t('Scores'),
    'page callback'     => 'ets_page_experiment_scores',
    'page arguments'    => array(1),
    'file'              => 'ets.pages.inc',
    'access arguments'  => array(1),
    'access callback'   => 'ets_node_is_experiment',
    'type'              => MENU_LOCAL_TASK,
  );

  # Not used
  $items['ets/get-position/%node'] = array(
    'title'            => t('Set your position'),
    'page callback'    => 'drupal_get_form',
    'page arguments'   => array('ets_position_form'),
    'access arguments' => array('perform experiments'),
    'file'             => 'ets.pages.inc',
    'type'             => MENU_NORMAL_ITEM,
  );
  
  # Not used
  $items['ets/random-point/%node'] = array(
    'title'            => t('A position, randomly'),
    'page callback'    => 'ets_random_point_page',
    'access arguments' => array('perform experiments'),
    'page arguments'   => array(2),
    'file'             => 'ets.pages.inc',
    'type'             => MENU_NORMAL_ITEM,
  );
  
  return $items;
}

function ets_node_is_experiment($node) {
  return $node->type == 'experiment';
}

function ets_access_view_experiment_statistics($node) {
  global $user;
  return $node->type == 'experiment' &&
         (user_access('administer nodes') || (user_access('edit own experiment content') && $user->uid == $node->uid));  
}

function ets_node_view($node, $view_mode ) {
  
  if ("full" == $view_mode && $node->type == 'experiment') {
    drupal_add_js('sites/all/libraries/jquery.cycle/jquery.cycle.all.js');
  }

}

function ets_towns_update() {

  // Warning: This list is the same used in the definition of geo_town Field  
  $towns = array(
    
   'London'      => 'London, UK',
   'Rome'        => 'Rome, Italy',
   'Turin'       => 'Turin, Italy',
   'Antwerpen'   => 'Antwerpen, Belgium',
   'Tursi'       => 'Tursi, Italy',
   'San Miniato' => 'San Miniato, Italy'
    
  );
  
  db_query("DELETE FROM {ets_towns}");
  
  foreach($towns as $name => $description) {
  
    $url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=" . urlencode($description);
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $r = curl_exec($ch);
    curl_close($ch);
    
    $data = json_decode($r);
    
    if (isset($data) && 'OK' == $data->status) {
      $data = $data->results[0]->geometry;
      db_query("INSERT INTO {ets_towns} (name, description, bounds_ne, bounds_sw, latitude, longitude) VALUES ('{$name}','{$description}','{$data->bounds->northeast->lat}:{$data->bounds->northeast->lng}','{$data->bounds->southwest->lat}:{$data->bounds->southwest->lng}', '{$data->location->lat}', '{$data->location->lng}')");
    }
  
  }
  
}

function ets_admin_paths() {
  $paths = array(
    'ets/get-position/*' => TRUE,
  );
  return $paths;
}

function ets_overlay_child_initialize() {
  drupal_add_js(drupal_get_path('module', 'ets') . '/ets-overlay.js');
}

// We use overlay for asking location, but we need to remove the ability to
// change the "Administrative overlay" option in the profile edit form
// We should change ets module weight or rely to the (buggy) hook_module_implements_alter
// I prefer to go hiding the fieldset with javascript
function ets_form_user_profile_form_alter(&$form, &$form_state, $form_id) {
  drupal_add_js(drupal_get_path('module', 'ets') . '/ets-form.js');
}

/**
 * Implementation of hook_page_build().
 */
function ets_page_build(&$page) {
  
  $node = menu_get_object('node', 1);

  if (!is_object($node) || arg(2) != '' ) {
    return;
  }

  if (!ets_user_can_join($node)) {
    return;
  }
    
#  $url = ets_get_node_field($node, 'geo_required') ? "ets/get-position/{$node->nid}" : "ets/exp-join/{$node->nid}";
  $url = "ets/exp-join/{$node->nid}";
  #. "?c=" . rand();

  $page['content']['join'] = array(
  //$page['content']['system_main']['nodes'][$node->nid]['join'] = array(
    '#markup' => "<p class='join-invite'>" .  l(t("Join the experiment!"), $url, array('attributes' => array('class' => 'btn btn-success'))) . "</p>", 
    '#weight' => -1, // Fields have weight 5
  );

}

function ets_page_alter(&$page) {
}

function ets_user_can_join($node) {
  global $user;

  if (!$node || 'experiment' != $node->type) {
    return FALSE;
  }
    
  if (!user_access('perform experiments')) {
    return FALSE;
  }
  
  if ($user->uid == 0 && !ets_get_node_field($node, 'anonymous_join')) {
    return FALSE;
  }
  
  if (!(ets_get_node_field($node, 'active') || user_access('perform inactive experiments') || $user->uid == $node->uid || $user->uid == 1)) {
    return FALSE;
  }

  // Get the "conditions" definition for the experiment
  $conditions = ets_conditions_get_experiment_conditions($node);

  foreach($conditions as $name => $cond) {
    // Name is something like "AGE:1" and cond is "greater than 33"
    // $rc values:
    // 1: condition is certainly satisfied
    // 2: condition is certainly NOT satisfied
    // 3: can't say (if the user data to check for is not set)
    // (those constant have a proper define in ets.conditions.inc)
    $rc = ets_conditions_check_condition($name, $cond, $user);
    
    if (ETS_CONDITION_NOT_SATISFIED == $rc) {
      //print "Not satisfied $name";
      return FALSE;
    }
     
  }
  
  return TRUE;
}

function ets_form_alter(&$form, &$form_state, $form_id) {
  
  if ($form_id == 'user_login_block') {
    $form['actions']['#weight'] = 1;
    $form['links']['#weight'] = 2;
    # Horrible, but quick
    $form['links']['#markup'] = str_replace('Request new password', 'Lost password?', $form['links']['#markup']); 
  }
  
}

function ets_block_view_alter(&$data, $block) {
  
  if (isset($block->delta) && $block->delta == 'user-menu') {
    global $user;
    if ($user->uid > 0 && isset($data['content'][15])) {
      $data['content'][15]['#title'] .= " {$user->name}";
      #array_unshift($data['content'], array('#markup' => "<p><b>{$user->name}</b></p>"));
    }
  }
}

function ets_form_experiment_node_form_alter(&$form, &$form_state) {

  $in_edit = !empty($form['nid']['#value']);
  
  $machine_name = '';
  if (isset($form_state['node']->machine_name)) {
    $machine_name = $form_state['node']->machine_name; 
  } 
  
  if (!$in_edit) {
    $form['machine_name'] = array(
      '#type'          => 'machine_name',
      '#default_value' => $machine_name,
      '#maxlength'     => 21,
      '#description'   => t("A unique machine-readable indentifier name for the experiment. Can only contain lowercase letters, numbers, and underscores.<br><strong>WARNING</strong>: you can't change it once the experiment has been created."), 
      '#required'      => TRUE,
      '#machine_name'  => array(
        'exists'       => 'ets_machine_name_exists',
      )
    );
  } else {
    $form['machine_name'] = array(
      '#type'          => 'hidden',
      '#default_value' => $machine_name,
    );
    $form['fake_machine_name'] = array(
      '#type'          => 'machine_name',
      '#default_value' => $machine_name,
      '#description'   => t("A unique machine-readable indentifier name for the experiment."),
      '#disabled'      => TRUE,
    );
  }

  $form['conditions'] = array(
    '#type'   => 'fieldset',
    '#title'  => t('Join conditions'),
    '#weight' => 3
  );
  
  // Renders the condition fields <select> and "Add" button
  $conditions_fields = ets_conditions_get_fields();
  $field_options = array('--' => '-- Select --');
  
  // Drupal does not provide a way to disable an option in a <select>, so we
  // resort using javascript
  foreach ($conditions_fields as $name => $f) {
    $field_options[$name] = ((isset($f['disabled']) && $f['disabled']) ? 'disabled ' : '') . $f['label'];
  }
  
  $form['conditions']['fields'] = array(
    '#type'    => 'select',
    '#prefix'  => "<div class='form-item'>",
    '#title'   => t('Choose an user field to set a condition against'),
    '#theme_wrappers' => array("ets_conditions_inline_select"),
    '#options' => $field_options,
  );

  $form['conditions']['add_condition'] = array(
    '#type'        => 'button',
    '#value'       => t('Add'),
    '#name'        => 'add_condition',
    '#suffix'      => "</div>",
    '#button_type' => 'button',
  );

  $form['conditions']['act_conditions'] = array(
    '#type'   => 'fieldset',
    '#title'  => 'Active conditions',
  );

  /*
  $form['conditions']['notice'] = array(
    '#type' => 'item',
    '#markup' => '<p>(<b>This is an experimental feature</b>: conditions will not be applied until this notice will be removed.)</p>'
  );
  */
  
  if ($in_edit) {
    $conditions = ets_conditions_load_conditions('db', array($form['nid']['#value']));
    if (!empty($conditions)) {
      ets_conditions_save_conditions('session', null, $conditions[$form['nid']['#value']]);
    }
  }

  $form['field_share_my_game']['#attributes'] = array('onclick' => 'if(!document.getElementById("edit-field-share-my-game-und").checked && !confirm("Revoking permission to share your experiment and saving your experiment will remove EVERY version of your experiment you previously shared. This action CANNOT BE UNDONE! Are you sure?")){ return false;}');

  $form['#validate'][] = 'ets_experiment_form_validate';
  $form['#submit'][] = 'ets_experiment_form_submit';
 
}

/**/
function ets_boot() {
  // Always create a guid, so to manage even anonymous users
  if (!isset($_SESSION['guid'])) {
    $_SESSION['guid'] = uniqid();
  }
}

function ets_user_update(&$edit, $account, $category) {
  require_once('ets.redis.inc');
  ets_redis_del(ets_redis_user_key($account->uid));
}

function ets_user_delete($account) {
  require_once('ets.redis.inc');
  ets_redis_del(ets_redis_user_key($account->uid));
}

/*
 This function gets called at the moment of a user login
*/
function ets_user_login($account) {
  //$_SESSION['guid'] = uniqid();
  // Guid for registered users is calculated through the use of an md5 + a passphrase. It is always the same.
  // Before, it was calculated using the function uniqid, but this meant that a registered user could have
  // two different guid during two different sessions. Instead, we needed a user registered to have the same
  // guid and one that could be easily calculated starting from the xtribe user id 
  // (not the reverse, for a privacy issue)
  $_SESSION['guid'] = ets_get_guid_from_uid($account['uid']);
}

function ets_get_guid_from_uid($uid) {
  return substr(md5($uid.'thistextisasimplepassphraseformd5'),19,32);
}

function ets_get_guid() {
  return $_SESSION['guid'];
}

function ets_node_load($nodes, $types = FALSE) {

  if (FALSE === array_search('experiment', $types)) {
    return;
  }

  module_load_include('inc', 'ets', 'ets.conditions');

  $result = db_query('SELECT nid, 
                             machine_name 
                        FROM {ets_experiment}
                       WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)));

  foreach ($result as $record) {
    $nodes[$record->nid]->machine_name = $record->machine_name;
  }

  $nodes_conditions = ets_conditions_load_conditions('db', array_keys($nodes));

  foreach ($nodes_conditions as $nid => $conditions) {
    $nodes[$nid]->ets_conditions = $conditions;
  }
 
}

function ets_machine_name_exists($machine_name) {
  $result = db_query('SELECT nid
                        FROM {ets_experiment}
                       WHERE machine_name = :mn', array(':mn' => $machine_name));
  
  return $result->rowCount() == 1;
}

function ets_node_insert($node) {

  if ('experiment' == $node->type) {
    db_insert('ets_experiment')
           ->fields(array('nid' => $node->nid,
                          'machine_name' => $node->machine_name))
           ->execute();

    db_insert('ets_experiment_stats')
           ->fields(array('nid' => $node->nid))
           ->execute();

    ets_conditions_save_conditions('db', $node->nid);
  }

  // adds automatically aliases to page of templeton project (needed to have templeton page use a specific theme)
  if ('kreyon_page' == $node->type) {
    $node->path['alias'] = 'kreyon/'.$node->nid;
  }
}

function ets_node_update($node) {

  if ('experiment' == $node->type) {
    ets_conditions_save_conditions('db', $node->nid);
    require_once('ets.redis.inc');
    ets_redis_del(ets_redis_experiment_key($node->nid));
  }
  
  /*
  
  By design: You can't change the machine name at the moment
  
  if ('experiment' == $node->type) {
    db_update('ets_experiment')
           ->fields(array('machine_name' => $node->machine_name))
           ->condition('nid', $node->nid)
           ->execute();
  }
  */
}

function ets_node_delete($node) {

  if ('experiment' == $node->type) {
    require_once('ets.redis.inc');
    ets_redis_del(ets_redis_experiment_key($node->nid));
    db_delete('ets_experiment_stats')
           ->condition('nid', $node->nid)
           ->execute();

    db_delete('ets_experiment')
           ->condition('nid', $node->nid)
           ->execute();

    ets_conditions_delete_conditions('db', $node->nid);

    // Better safe than sorry
    if (trim($node->machine_name) == "") {
      return;
    }

    $tmp = file_directory_temp() . "/exp_packages/{$node->machine_name}";
    ets_rrmdir($tmp);

    $path = "public://exp_packages";
    $target = drupal_realpath($path);
    if (!empty($target)) {
      ets_rrmdir("{$target}/{$node->machine_name}");
    }
  }
}

function ets_experiment_form_submit($form, $form_state) {
  $form_state['node']->machine_name = $form_state['values']['machine_name'];

  // Check if user chose to share publicly his game

  $field_share_my_game=trim($form_state['values']['field_share_my_game']['und'][0]['value']);
  $game_machineName=$form_state['values']['machine_name'];
  $path_repo = 'public://published_games_repo/'.$game_machineName;
  // if user chose to share his game
  if ($field_share_my_game=='1') {
    // Create the game repo directory if does not exists
    drupal_mkdir($path_repo,0777);
    // load client file to move it in the right repository
    $file_field_client = $form_state['input']['field_package']['und'][0]; 
    $file_client = file_load($file_field_client['fid']);
    // load manager file to move it in the right repository
    $file_field_manager = $form_state['input']['field_share_my_manager']['und'][0]; 
    $file_manager = file_load($file_field_manager['fid']);
    //$present_path_of_file=$file->uri;
    
    // If there is at least one of the two file loaded i start the deploy of files on the repo.
    // It is possible to have no file cause the "Share my manager" checkbox is intended to give permission
    // to share, then is up to the system to choose when and how.
    if (is_a($file_client,'stdClass') || is_a($file_manager,'stdClass')){
      // Create the game repo directory for this deploy
      $path_repo = $path_repo."/".date('d-m-Y_H:i:s');
      drupal_mkdir($path_repo,0777);
      // copy client file (it should remain in client dir, too) into repository and manager file
      // only if files have been loaded
      if (is_a($file_client,'stdClass')) {
        $path_repo_client = $path_repo."/client/";
        drupal_mkdir($path_repo_client,0777);
        file_copy($file_client, $path_repo_client); 
      }
      if (is_a($file_manager,'stdClass')) {
        $path_repo_manager = $path_repo."/manager/";
        drupal_mkdir($path_repo_manager,0777);
        file_copy($file_manager, $path_repo_manager);
      }
      // Starts the bash script that add, commit and push the changes to the public games repo
      $oldPath=getcwd();
      chdir('/var/www/xtribe.eu/etsmaintenance/');
      $output= shell_exec('./push_public_game_repo.sh '.$game_machineName.' add');
      chdir($oldPath);
      watchdog("ETS Client", "Added game to public repo. Log: ".$output, array(), WATCHDOG_NOTICE);
    }
  }

  $in_edit = !empty($form['nid']['#value']);
  if ($field_share_my_game=='0' and $in_edit) {
    //watchdog("ETS Client", "Removing shared content of experiment ".$form_state['values']['machine_name'], array(), WATCHDOG_NOTICE);
    $repoExists = file_prepare_directory($path_repo);
    if ($repoExists) {
      file_unmanaged_delete_recursive($path_repo);
      // Starts the bash script that remove, commit and push the changes to the public games repo
      $oldPath=getcwd();
      chdir('/var/www/xtribe.eu/etsmaintenance/');
      $output= shell_exec('./push_public_game_repo.sh '.$game_machineName.' remove');
      chdir($oldPath);
      watchdog("ETS Client", "Removed game to public repo. Log: ".$output, array(), WATCHDOG_NOTICE);
    }
  }
}

function ets_experiment_form_validate($form, $form_state) {

  // Save in session the actual value for the conditions, so we
  // can eventually restore (and save) them
  ets_conditions_save_conditions('session');
  
/*
  stdClass Object
    [fid] => 96
    [uid] => 9
    [filename] => 335782.zip
    [uri] => public://game_packages/335782.zip
    [filemime] => application/zip
    [filesize] => 137130
    [status] => 0
    [timestamp] => 1306583034
    [rdf_mapping] => Array
*/

  // Check manager uri is correctly filled
  $mgr_uri_field = trim($form_state['values']['field_mgr_uri']['und'][0]['value']);

  if (!empty($mgr_uri_field) && !valid_url($mgr_uri_field, TRUE)) {
    form_set_error('field_mgr_uri', "The specified manager URL is not valid");
    return;
  }

  // Check machine name has been filled
  $file_field = $form_state['input']['field_package']['und'][0]; 

  $machine_name = $form_state['input']['machine_name'];

  // Se il machine name non è valido non proseguiamo
  $errors = form_get_errors();
  if (isset($errors['machine_name'])) {
    return;
  }
  
  // Controllo di obbligatorietà già fatto da Drupal
  if ($file_field['fid'] == 0) {
    return;
  }
  $file = file_load($file_field['fid']);

  // Now unzip the file in the right place
  $zip = new ZipArchive();
  
  $m = '';
  
  $path = "public://exp_packages";
  file_prepare_directory($path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
  
  $target = drupal_realpath($path) . "/{$machine_name}";

  /* Prima di cancellare la directory, verifichiamo che il file esista */

  $package = drupal_realpath($file->uri);
  
  if (empty($package)) {
    # Può succedere in fase di update: se il package non esiste e non esiste nemmeno la directory
    # contenente una eventuale precedente versione dell'esperimento, dobbiamo
    # segnalare l'errore
    if (!file_exists("{$target}/index.html")) {
      form_set_error('field_package', "Sorry, the specified package has been removed and cannot be saved");
    }
  } else {

    $tmp = file_directory_temp() . "/exp_packages/{$machine_name}";
    ets_rrmdir($tmp);
  
    if (!empty($file->uri)) {
      if ($zip->open(drupal_realpath($file->uri)) === TRUE) {
        $zip->extractTo($tmp);
        $zip->close();
        # Verifichiamo che esista un file index.html
        if (!file_exists("{$tmp}/index.html")) {
          form_set_error('field_package', "The experiment package does not contain a index.html file");
        } else {
          // @unlink("{$target}/{$machine_name}");
          // @symlink($tmp, "{$target}/{$machine_name}");
          ets_rrmdir($target);
          file_prepare_directory($target, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
          ets_rcopy($tmp, $target);
        }
        ets_rrmdir($tmp);
      } else {
        form_set_error('field_package', "Sorry, a problem occurred opening the package. Please try uploading it again.");
      }
    }
  }
}


function ets_block_info() {
  $blocks['ets_login'] = array(
    'info'  => 'ETS: Login block',
    'cache' => DRUPAL_NO_CACHE,
  );  
  return $blocks;
}

function ets_block_view($delta) {
  $block = array();
  switch ($delta) {
    case 'ets_login':
      $block = ets_block_login();
      break;
  }
  return $block;
}

/* Block shows the "Login" and "Facebook connect" buttons only */
function ets_block_login() {
  global $user;

  if ($user->uid) {
    return;
  }

  $destination = drupal_get_destination();

  $block['content'] = "<div class='login-button clearfix'><a href='/user?destination={$destination['destination']}' class='btn btn-success pull-right'>Login</a></div>";

  if (module_exists('fboauth')) {
    $block['content'] .= "<div class='clearfix'>" . fboauth_action_display('connect') . "</div>";
  }

  return $block;
}

/*
 * Helpers
 */
 
function ets_rrmdir($path) {
  return is_file($path) ?
    @unlink($path) :
    array_map('ets_rrmdir', glob($path.'/*')) == @rmdir($path)
  ;
}

function ets_rcopy($src, $dst) { 
  $dir = opendir($src); 
  @mkdir($dst); 
  while(false !== ( $file = readdir($dir)) ) { 
    if (( $file != '.' ) && ( $file != '..' )) { 
      if ( is_dir($src . '/' . $file) ) { 
        ets_rcopy($src . '/' . $file,$dst . '/' . $file); 
      } 
      else { 
        copy($src . '/' . $file,$dst . '/' . $file); 
      } 
    } 
  } 
  closedir($dir); 
} 

/* Get the raw value of a node field. Hope there is better way */
function ets_get_node_field($node, $name, $key = 'value') {

  if (substr($name, 0, 6) != 'field_') {
    $name = "field_{$name}";
  }

  $field = field_get_items('node', $node, $name);

  return $field[0][$key];
}

/* 
 * Get the raw value of a user field.
 * returns an array of values or FALSE
 */
function ets_get_user_field($account, $name, $key = 'value') {

  if (substr($name, 0, 6) != 'field_') {
    $name = "field_{$name}";
  }

  $field = field_get_items('user', $account, $name);
  if (FALSE === $field) {
    // Field may not be loaded yet
    $account = user_load($account->uid);
    $field = field_get_items('user', $account, $name);
  }

  // Can't find the rquested field
  if ($field === FALSE) {
    return FALSE;
  }
  
  $output = array();
  foreach($field as $instance) {
    $output[] = $instance[$key];
  }

  return $output;
  
}

/* Questa funzione viene chiamata dalla pagina di join e serve per
 * associare un token ad una istanza dell'esperimento e di un utente, ovvero 
 * inseriamo il token tra quelli al momento validi per il gioco.
 * 
 * Nota 1: non possiamo usare il instance id perché il EHS ce lo renderà solo 
           al momento del play
 *
 * Nota 2: questo impone che lo stesso utente non può partecipare contemporaneamente
 *         a due istanze dello stesso esperimento
 *
 * Nota 3: l'uid serve solo per statistica e non servirà in fase di verify
 *
 */
function ets_token_save($nid, $guid, $token) {
  
  global $user;
  
  /* Nella praticamente impossibile ipotesi che questo token esista già
   * per questo gioco, lo cancelliamo
   */
  db_delete('ets_experiment_token')
           ->condition('nid', $nid)
           ->condition('token', $token)
           ->execute();

  /* Resettiamo la situazione dell'utente al momento del join */
  db_delete('ets_experiment_token')
           ->condition('nid', $nid)
           ->condition('guid', $guid)
           ->execute();

  db_insert('ets_experiment_token')
         ->fields(array('nid'     => $nid,
                        'guid'    => $guid,
                        'uid'     => $user->uid,
                        'created' => time(),
                        'token'   => $token))
         ->execute();
  
}

/* Questa funzione "brucia" il token relativo ad una partita. Non lo cancella
 * in quanto lo possiamo usare per un conteggio statistico di qualche tipo
 */
function ets_token_spend($nid, $token) {
  db_update('ets_experiment_token')
         ->fields(array('spent' => 1))
         ->condition('nid', $nid)
         ->condition('token', $token)
         ->execute();
}

/* Questa funzione verifica che un token sia ancora spendibile */
function ets_token_verify($nid, $token) {
  $result = db_query('SELECT token
                        FROM {ets_experiment_token}
                       WHERE nid = :nid
                         AND token = :token
                         AND spent = 0', array(':nid' => $nid, ':token' => $token));
  return $result->rowCount() == 1;
}

function ets_token_generate($seed) {
  $part = 0;
  return substr(sha1('t' . $seed . microtime()), 0, 10);
}

function ets_get_town_data($name) {
  $result = db_query("SELECT * FROM {ets_towns} WHERE name = :name", array(':name' => $name));
  return $result->fetchObject();
}

function ets_theme() {
  return array(
    'ets_conditions_inline_select' => array(),
    'ets_conditions_condition' => array('field_name' => null, 'index' => null, 'value' => null, 'operator' => null),
  );
}

function ets_dbg($data) {
  error_log(print_r($data, true), 3, "/tmp/xtribe.log");  
}


function ets_custom_theme() {

  if (isset($_GET['theme'])) {
    return $_GET['theme'];
  }

}

