<?php

define('ETS_CONDITIONS_KEY', 'ets_conditions');

define('ETS_CONDITION_SATISFIED',     1);
define('ETS_CONDITION_NOT_SATISFIED', 2);
define('ETS_CONDITION_CANT_SAY',      3);

function ets_conditions_get_experiment_conditions($node) {

  $result = db_query('SELECT nid, 
                             conditions 
                        FROM {ets_conditions}
                       WHERE nid = :nid', array(':nid' => $node->nid));

  $row = $result->fetchObject();

  if ($row) {
    return unserialize($row->conditions);
  } else {
    return array();
  }
  
}

function ets_conditions_check_condition($name, $cond, $account) {
  
  list($name, $tmp) = (explode(':', $name));

  $rc = ETS_CONDITION_CANT_SAY;
  if (function_exists("ets_conditions_check_{$name}")) {
    $rc = call_user_func_array("ets_conditions_check_{$name}", array($cond, $account));
  }
  
  return $rc;
}

function ets_conditions_check_AGE($cond, $account) {
  $dob = ets_get_user_field($account, "dob");
  //watchdog('test', '--- DOB: '.print_r($dob,true));

  if (!$dob) {
    return ETS_CONDITION_CANT_SAY;
  }

  $d1 = new DateObject($dob[0]);
  $age = $d1->difference(new DateObject(), 'years');
  return ets_conditions_test_expression($age, $cond);
}

function ets_conditions_check_EDUCATION($cond, $account) {
  $edu = ets_get_user_field($account, "education");
  //watchdog('test', '--- EDU: '.print_r($edu,true));
  
  if (FALSE === $edu) {
    return ETS_CONDITION_CANT_SAY;
  }

  // Condition is saved as an index, so we can use the simple test helper
  return ets_conditions_test_expression($edu[0], $cond);
}

function ets_conditions_check_SEX($cond, $account) {

  $sex = ets_get_user_field($account, "sex");
  //watchdog('test', '--- SEX: '.print_r($sex,true));

  if (!$sex) {
    return ETS_CONDITION_CANT_SAY;
  }

  // Condition is saved as an index, so we can use the test number helper
  return ets_conditions_test_expression($sex[0], $cond);

}

function ets_conditions_check_LANGUAGE_SP($cond, $account) {

  $lan = ets_get_user_field($account, "language_sp");
  //watchdog('test', '--- LANG: '.print_r($lan,true));

  if (!$lan) {
    return ETS_CONDITION_CANT_SAY;
  }

  // Condition is saved as an index, so we can use the test number helper
  return ets_conditions_test_expression($lan, $cond);
}

// This works for numbers as well as for strings provided that the condition
// for strings is only "eq" or "ne"
function ets_conditions_test_expression($lvalue, $cond) {
  $op = $cond['op'];
  $rvalue = $cond['val'];

  //watchdog('test', 'cond: <pre>'.print_r($cond,true).' </pre> lvalue: <pre>'.print_r($lvalue,true).' </pre>rvalue: <pre>'.print_r($rvalue,true).' </pre>');

  if (("gt" == $op && $lvalue >  $rvalue)  ||
      ("lt" == $op && $lvalue <  $rvalue)  ||
      ("ne" == $op && $lvalue != $rvalue)  ||
      ("eq" == $op && $lvalue == $rvalue)) {
    return ETS_CONDITION_SATISFIED;    
  }

  if ("in" == $op || "ni" == $op) {
    $rvalue = drupal_explode_tags($rvalue);
    $intx = array_intersect($lvalue, $rvalue);
    //watchdog("ETS Client", "rvalue: ".print_r($rvalue,true)." intx: ".print_r($intx,true)." lvalue: ".print_r($lvalue,true), array(), WATCHDOG_NOTICE);

    if (($intx && "in" == $op) ||
        (!$intx && "ni" == $op)) {
      return ETS_CONDITION_SATISFIED;    
    }
  }

  return ETS_CONDITION_NOT_SATISFIED;
}

function ets_conditions_load_conditions($where, $nids = null) {
  if ('session' == $where) {
    if (isset($_SESSION[ETS_CONDITIONS_KEY])) {
      $conditions = $_SESSION[ETS_CONDITIONS_KEY];
    }else{
      $conditions = '';
    }
  } else {
    // Works on an array of nids to be compatible with ets_node_load()    
    $result = db_query('SELECT nid, 
                               conditions 
                          FROM {ets_conditions}
                         WHERE nid IN(:nids)', array(':nids' => $nids));
  
    $conditions = array();
    foreach ($result as $record) {
      $conditions[$record->nid] = unserialize($record->conditions);
    }
  }
  return $conditions;    
}

function ets_conditions_save_conditions($where, $nid = null, $data = null) {
  
  if ('session' == $where) {
    $conditions = array();
  
    if (!$data) {
      if (isset($_POST['cond_name'])) {
        foreach ($_POST['cond_name'] as $cond) {
          list($name, $idx) = explode(':', $cond);
          $val = $_POST["cond_val_{$idx}"];
          if (!is_array($val)) {
            $val = trim($val);
          }
          if (!empty($val) && $val !== '--') {
            $conditions[$cond] = array(
              "op"  => $_POST["cond_op_{$idx}"],
              "val" => $_POST["cond_val_{$idx}"]
            );
          }
        }
      }
    } else {
      $conditions = $data;
    }
    
    $_SESSION[ETS_CONDITIONS_KEY] = $conditions;
  } else {
    ets_conditions_delete_conditions('db', $nid);
  
    db_insert('ets_conditions')
           ->fields(array('nid'        => $nid,
                          'conditions' => serialize(ets_conditions_load_conditions('session'))))
           ->execute();
  }
}

function ets_conditions_delete_conditions($where, $nid = null) {
  if ('session' == $where) {
    $_SESSION[ETS_CONDITIONS_KEY] = array();
  } else {
    db_delete('ets_conditions')
           ->condition('nid', $nid)
           ->execute();
  }
}

function ets_conditions_ac($name='', $string) {
  
  $f = ets_conditions_get_field($name);

  $matches = array();
  if (function_exists("ets_conditions_ac_{$name}")) {
    $matches = call_user_func_array("ets_conditions_ac_{$name}", array($string));
  }
  
  drupal_json_output($matches);
}

// Language autocomplete callback
function ets_conditions_ac_LANGUAGE_SP($string) {
  
  $matches = array();

  // Users could have been inserted comma separated strings.
  $strings_typed = drupal_explode_tags($string);
  $string = array_pop($strings_typed);

  $info = field_info_field('field_language_sp');
  
  $data = array_values($info['settings']['allowed_values']);
  
  $prefix = count($strings_typed) ? drupal_implode_tags($strings_typed) . ', ' : '';

  foreach ($data as $value) {
    if (FALSE !== stripos($value, $string)) {
      $matches[$prefix . $value] = check_plain($value);      
    }
  }
  
  return $matches;
  
}

// Education options callback
function ets_conditions_options_EDUCATION() {
  $info = field_info_field('field_education');
  return $info['settings']['allowed_values'];
}

/* Ajax callback to add conditions to the experiment form */
function ets_conditions_load_ahah() {
  
  // We always load the conditions from session because the session has already
  // been populated on node load
  $conditions = ets_conditions_load_conditions('session');

  if (!$conditions) {
    return "";
  }

  $output = '';
  foreach ($conditions as $cond => $values) {
    list($name, $i) = explode(':', $cond);
    $output .= theme('ets_conditions_condition', array(
                       'field_name' => $name,
                       'index'      => $i,
                       'value'      => $values['val'],
                       'operator'   => $values['op'])
                    );
  }
  
  ets_conditions_delete_conditions('session');
  
  return $output;
}

/* Ajax callback for each "Add" condition */
function ets_conditions_new_ahah() {
  return theme('ets_conditions_condition', array(
                       'field_name' => $_REQUEST['f'],
                       'index'      => $_REQUEST['i'],
                       'value'      => null,
                       'operator'   => null)
              );
}


/* Returns the operator for each field type */
function ets_conditions_get_ops($f) {

  switch ($f['type']) {
    
    case 'select_broad':
    case 'text':
    case 'number':
      return array(
        'gt' => 'greater than',        
        'lt' => 'less than',        
        'eq' => 'equal to',        
        'ne' => 'not equal to',        
      );
    
    case 'select_close':
      return array(
        'eq' => 'equal to',        
        'ne' => 'not equal to',        
      );
      break;
    
    case 'autocomplete':
    case 'multiselect':
      return array(
        'in' => 'one of',
        'ni' => 'not one in',     
      );
      break;
    
  }

  return array();
}

/*
  This functions returns an array of fields to be used as conditions
  Every autocomplete field needs a ets_conditions_ac_FIELD_NAME() function
  to retrieve possibile data
*/
function ets_conditions_get_fields() {
  
  return array(
    
    // Age
    'age' => array(
      'label' => t('Age'),
      'type'  => 'number',
      'help'  => t('The user\'s age')
    ),

    // Education
    'education' => array(
      'label' => t('Education'),
      'type'  => 'select_broad',
      'help'  => t('Education level of the user')
    ),

    // Instances started
    'inst_started' => array(
      'label' => t('Started instances'),
      'type'  => 'number',
      'disabled' => true,
    ),
    
    // Instance ended
    'inst_ended' => array(
      'label' => t('Ended instances'),
      'type'  => 'number',
      'disabled' => true,
    ),

    // Instance started/ended ratio
    'inst_ratio' => array(
      'label' => t('Ended/Started ratio'),
      'type'  => 'number',
      'disabled' => true,
    ),
    
    // Experiment score
    'score' => array(
      'label' => t('Score'),
      'type'  => 'number',
      'disabled' => true,
      'disabled' => true,
    ),
    
    // Sex
    'sex' => array(
      'label' => t('Sex'),
      'type'  => 'select_close',
      'options' => array('M' => 'Male', 'F' => 'Female')
    ),
    
    // spoken language
    'language_sp'  => array(
      'label'   => t('Spoken language'),
      'type'    => 'autocomplete',
      'help'    => t('You can choose languages using autocomplete. If you want to choose more than one language, please divide them with commas. Ex: English, Italian')
    ),
    
    // Country
    'country' => array(
      'label' => t('Country'),
      'type'  => 'autocomplete',
      'disabled' => true,
    ),
    
    // City
    'city' => array(
      'label' => t('City'),
      'type'  => 'autocomplete',
      'disabled' => true,
    ),
    
  );
  
}

function ets_conditions_get_field($name) {
  $fields = ets_conditions_get_fields();
  return isset($fields[$name]) ? $fields[$name] : null;
}

function theme_ets_conditions_inline_select($elements) {
  $select = array_pop($elements);
  return "<label>" . check_plain($select['#title']) . "</label>" . $select['#children'];
}

function theme_ets_conditions_condition($data) {

  extract($data);

  $f = ets_conditions_get_field($field_name);
  
  if (!$f) {
    return "Error {$field_name}";
  }

  $f_html = _ets_conditions_render_input($field_name, "cond_val_{$index}", $f, $value);

  $ops = theme('select', array('element' => array(
    '#type'    => 'select',
    '#value'   => $operator,
    '#name'    => "cond_op_{$index}",
    '#options' => ets_conditions_get_ops($f)
  )));
  
  $rm_txt = t('Remove');

  $help = '';
  if (!empty($f['help'])) {
    $help = "<p class=\"help\">{$f['help']}</p>";
  }
  
  return <<<EOHTML
  <div class="ets-condition"><b>{$f['label']}</b> is 
    {$ops}
    {$f_html}
    <a href="#" class="rm-cond">{$rm_txt}</a>
    {$help}
    <input type="hidden" name="cond_name[]" value="{$field_name}:{$index}">
  </div>
EOHTML;

}

function _ets_conditions_render_input($name, $fname, $f, $v) {

  $el = array();
  $input = '';
  
  switch ($f['type']) {

    case 'autocomplete':
      $el['element'] = array(
        '#type'  => 'textfield',
        '#size'  => '20',
        '#value' => $v,
        '#name'  => $fname,
        '#autocomplete_path' => "ets/conditions/ac/{$name}",
        '#attributes' => array('id' => $fname)
      );
      $input = theme($el['element']['#type'], $el);
      break;
    
    case 'text':
    case 'number':
      $el['element'] = array(
        '#type'  => 'textfield',
        '#size'  => '5',
        '#value' => $v,
        '#name'  => $fname,
        '#attributes' => array('class' => array($f['type']))
      );
      $input = theme($el['element']['#type'], $el);
      break;
    
    case 'multiselect':
    case 'select_close':
    case 'select_broad':
      $multiple = ($f['type'] == 'multiselect');
      
      $el['element'] = array(
        '#type'     => 'select',
        '#name'     => $fname,
        '#value'    => $v,
        '#multiple' => $multiple,
       );
      
      if (isset($f['options']) && is_array($f['options'])) {
        $options = $f['options'];
      } else {
        if (function_exists("ets_conditions_options_{$name}")) {
          $options = call_user_func("ets_conditions_options_{$name}");
        } else {
          $options = array();
        }
      }
      
      if ($multiple) {
        $el['element']['#attributes'] = array('multiple' => 'multiple');
        $el['element']['#name'] .= '[]';
      }

      $el['element']['#size'] = ($multiple ? min(12, count($options)) : 0);
      $el['element']['#options'] = $options;

      $input = theme($el['element']['#type'], $el);
      break;
  }
  
  return $input;
}

/* Languages
--
Abkhazian
Afar
Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Assamese
Avar
Avestan
Aymara
Azerbaijani
Bambara
Bashkir
Basque
Belarusian
Bengali
Bhutani
Bihari
Bislama
Bosnian
Breton
Bulgarian
Burmese
Cambodian
Catalan
Chamorro
Chechen
Chichewa
Chinese, Simplified
Chinese, Traditional
Chuvash
Cornish
Corsican
Cree
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faeroese
Filipino
Fiji
Finnish
French
Frisian
Fulah
Galician
Georgian
German
Greek
Greenlandic
Guarani
Gujarati
Hausa
Hebrew
Herero
Hindi
Hiri Motu
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Interlingue
Inuktitut
Inupiak
Irish
Italian
Japanese
Javanese
Kannada
Kanuri
Kashmiri
Kazakh
Kikuyu
Kinyarwanda
Kirghiz
Kirundi
Komi
Kongo
Korean
Kurdish
Kwanyama
Laothian
Latin
Latvian
Lingala
Lithuanian
Luganda
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maldivian
Maltese
Manx
Maori
Marathi
Marshallese
Moldavian
Mongolian
Nauru
Navajo
Ndonga
Nepali
North Ndebele
Northern Sami
Norwegian Bokmål
Norwegian Nynorsk
Occitan
Old Slavonic
Oriya
Oromo
Ossetian
Pali
Pashto
Persian
Polish
Portuguese, Brazil
Portuguese, Portugal
Punjabi
Quechua
Rhaeto-Romance
Romanian
Russian
Samoan
Sango
Sanskrit
Sardinian
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Shona
Sindhi
Singhalese
Siswati
Slovak
Slovenian
Somali
South Ndebele
Spanish
Sudanese
Swahili
Swedish
Tagalog
Tahitian
Tajik
Tamil
Tatar
Telugu
Thai
Tibetan
Tigrinya
Tonga
Tsonga
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Venda
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zhuang
Zulu
*/