<?php

class CalaisTestCase extends DrupalWebTestCase {

	function setUp() {
		parent::setUp('calais_api', 'calais', 'rdf');
		
		// Create and login user
    $admin_user = $this->drupalCreateUser(array('administer taxonomy', 'administer calais', 'access calais'));
    $this->drupalLogin($admin_user);
	}

	function tearDown() {
		parent::tearDown();
	}

	function createVocabulary() {
		$vocab = array();
	  $vocab['name'] = $this->randomName(20);
	  $vocab['nodes'] = array('page' => TRUE);
    taxonomy_save_vocabulary($vocab);
		return $vocab;
	}
	
	function createTerm($vid, $overrides = array()) {
		$term = array(
			'vid' => $vid,
			'name' => $this->randomName(30),
			'description' => $this->randomName(200),
		);
		$term += $overrides;
    taxonomy_save_term($term);
		return (object)$term;
	}
}

class CalaisGetTermTestCase extends CalaisTestCase {

  function getInfo() {
    return array(
      'name' => t('Calais Get Term'),
      'description' => t('Test various finds for local Calais Terms.'),
      'group' => t('Calais')
    );
  }

	function testGetTerm() {
		$vocab = $this->createVocabulary();

		$calais_term = new CalaisTerm($this->randomName(100), 'CalaisGetTerm');
		$found = calais_get_term($vocab['vid'], $calais_term);
		$this->assertFalse($found, 'FALSE returned for nonexistent Calais term.');

		db_query("INSERT INTO {calais_term} (vid, name) VALUES (%d, '%s')", $vocab['vid'], $calais_term->name);
		$tid = db_last_insert_id('calais_term', 'tid');
		$found = calais_get_term($vocab['vid'], $calais_term);
		$this->assertTrue($found, 'Calais term found by name');
		$this->assertEqual($found->name, $calais_term->name, 'Calais term found by name matches');
		
		$calais_term->value = $this->randomName(100); // Make sure it can't be found by name on a failure
		db_query("UPDATE {calais_term} SET guid = '%s' WHERE tid = %d", $calais_term->guid, $tid);
		$found = calais_get_term($vocab['vid'], $calais_term);
		$this->assertTrue($found, 'Calais term found by guid');
		$this->assertEqual($found->guid, $calais_term->guid, 'Calais term found by guid matches');
		
		// Test getting resolved company data
		db_query("INSERT INTO {calais_term_data_company} (tid, ticker, score) VALUES (%d, '%s', %f)", $tid, 'TRI', 0.999);
		db_query("UPDATE {calais_term} SET resolved_type = '%s' WHERE tid = %d", 'company', $tid);
		$found = calais_get_term($vocab['vid'], $calais_term);
		$this->assertTrue($found, 'Calais term & data found by guid');
		$this->assertEqual(count($found->extra), 4, 'Calais resolved data has 4 values');
		$this->assertEqual($found->extra['ticker'], 'TRI', 'Calais term ticker is TRI');
		$this->assertEqual($found->extra['score'], 0.999, 'Calais term score is 0.999');		
		
		$found = calais_get_term($vocab['vid'], $tid);
		$this->assertTrue($found, 'Calais term found by tid');		
	}
}

class CalaisSaveTermTestCase extends CalaisTestCase {

  function getInfo() {
    return array(
      'name' => t('Calais Save Term'),
      'description' => t('Test various saves for local Calais Terms.'),
      'group' => t('Calais')
    );
  }

	function testSaveTerm() {
		$vocab = $this->createVocabulary();
		$vid = $vocab['vid'];

		$calais_term = new CalaisTerm($this->randomName(100), 'CalaisSaveTerm');
		$calais_term->vid = $vid;
		
		calais_save_term($calais_term);
		$this->assertNotNull($calais_term->tid, 'Term ID set for new Calais term.');
		$found = calais_get_term($vid, $calais_term->tid);
		$this->assertEqual($found->guid, $calais_term->guid, 'Inserted Calais term found');
		$this->assertNull($found->resolved_guid, 'Calais term resolved guid is null');
		
		$new_guid = $this->randomName(100);
		$calais_term->resolved_guid = $new_guid;
		calais_save_term($calais_term);
		$found = calais_get_term($vid, $calais_term->tid);
		$this->assertEqual($found->resolved_guid, $new_guid, 'Calais term resolved guid updated');
		
		$calais_term->resolved_type = 'geo';
		$calais_term->extra = array(
			'latitude' => 44.4444,
			'longitude' => -88.888,
		);
		calais_save_term($calais_term);
		$found = calais_get_term($vid, $calais_term->tid);
		$this->assertEqual(count($found->extra), 7, 'Calais resolved data has 7 values');
		$this->assertEqual($found->extra['latitude'], 44.4444, 'Calais term latitude is 44.4444');
		$this->assertEqual($found->extra['longitude'], -88.888, 'Calais term longitude is -88.888');		

		$calais_term->extra['containedbycountry'] = 'USA';
		calais_save_term($calais_term);
		$found = calais_get_term($vid, $calais_term->tid);
		$this->assertEqual(count($found->extra), 7, 'Calais resolved data has 7 values');
		$this->assertEqual($found->extra['containedbycountry'], 'USA', 'Calais term containedbycountry is USA');
	}
}

class CalaisGetKeywordsTestCase extends CalaisTestCase {
	
	function getInfo() {
    return array(
      'name' => t('Get Keywords'),
      'description' => t('Test looking up locally cached Calais keywords with threshold filtering.'),
      'group' => t('Calais')
    );
  }

	// Associating new calais terms with an existing node
	function testGetKeywords() {
		
		$vocab = $this->createVocabulary();
		$vid = $vocab['vid'];
		$node = $this->drupalCreateNode();

		$calais_terms = array();		
		$calais_terms[0] = new CalaisTerm($this->randomName(100), 'Low Relevance', 0.001);
		$calais_terms[1] = new CalaisTerm($this->randomName(100), 'Mid Relevance', 0.5);
		$calais_terms[2] = new CalaisTerm($this->randomName(100), 'High Relevance', 1.0);

		foreach ($calais_terms as $calais_term) {
			calais_associate_term($vid, $calais_term, $node);
		}
		
	  $type = drupal_strtolower($node->type);
		$thres_key = "calais_threshold_{$type}";
		
		variable_set($thres_key, 0.0);
		$keywords = calais_get_keywords($node->nid, $node->type, $vid);
		$this->assertEqual(count($keywords[$vid]), 3, "Three terms were returned for no threshold.");
		$this->assertEqual($keywords[$vid][0]->guid, $calais_terms[2]->guid, "Correct 1st ordering");
		$this->assertEqual($keywords[$vid][1]->guid, $calais_terms[1]->guid, "Correct 2nd ordering");
		$this->assertEqual($keywords[$vid][2]->guid, $calais_terms[0]->guid, "Correct 3rd ordering");

		variable_set($thres_key, 0.499);
		$keywords = calais_get_keywords($node->nid, $node->type, $vid);
		$this->assertEqual(count($keywords[$vid]), 2, "Two terms were returned for < 0.001.");

		variable_set($thres_key, 0.500);
		$keywords = calais_get_keywords($node->nid, $node->type, $vid);
		$this->assertEqual(count($keywords[$vid]), 2, "Two terms were returned for < 0.001.");

		variable_set($thres_key, 0.5001);
		$keywords = calais_get_keywords($node->nid, $node->type, $vid);
		$this->assertEqual(count($keywords[$vid]), 1, "One term was returned for > 0.001.");

		variable_set($thres_key, 1.0);
		$keywords = calais_get_keywords($node->nid, $node->type, $vid);
		$this->assertEqual(count($keywords[$vid]), 1, "One term was returned for max threshold.");

		$keywords = calais_get_keywords($node->nid, $node->type, $vid, 0.002);
		$this->assertEqual(count($keywords[$vid]), 2, "Two terms were returned for overriden threshold.");
		$this->assertEqual($keywords[$vid][0]->guid, $calais_terms[2]->guid, "Correct 1st ordering");
	}	
}

class CalaisApplyToNodeTestCase extends CalaisTestCase {

  function getInfo() {
    return array(
      'name' => t('Apply Calais Entity'),
      'description' => t('Apply a Calais Entity and Taxonomy to a Node.'),
      'group' => t('Calais')
    );
  }

	// Test filling in an existing terms guid
	function testApply() {
		$vocab = $this->createVocabulary();
		$node = $this->drupalCreateNode();

		// Test no Tax Term exists
		$calais_term1 = new CalaisTerm($this->randomName(100), $this->randomName(25));
		calais_save_term($calais_term1);

		$terms = taxonomy_get_term_by_name($calais_term1->name);
		$this->assertTrue(empty($terms), 'No term exists yet');
		$this->assertNull($calais_term1->tdid, 'CalaisTerm tdid is null');

		calais_apply_to_node($vocab['vid'], $calais_term1, $node);

		$terms = taxonomy_node_get_terms($node);
		$this->assertEqual(count($terms), 1, 'Term found that matches CalaisTerm');
		$found = calais_get_term($vocab['vid'], $calais_term1->tid);
		$this->assertEqual(reset($terms)->tid, $found->tdid, 'Term ID matches CalaisTerm tdid');

		// Test Tax Term exists
		$node2 = $this->drupalCreateNode();
		$term = $this->createTerm($vocab['vid']);
		$calais_term2 = new CalaisTerm($this->randomName(100), $term->name);
		calais_save_term($calais_term2);

		$this->assertNull($calais_term2->tdid, 'CalaisTerm tdid is null');
		calais_apply_to_node($vocab['vid'], $calais_term2, $node2);
		$this->assertEqual($term->tid, $calais_term2->tdid, 'Term ID set on CalaisTerm');
		$terms = taxonomy_node_get_terms($node2);
		$this->assertEqual(count($terms), 1, 'Term found for node');
		$found = calais_get_term($vocab['vid'], $calais_term2->tid);
		$this->assertEqual(reset($terms)->tid, $found->tdid, 'Term ID matches CalaisTerm tdid');
	}
}

class CalaisHookTaxonomyTestCase extends CalaisTestCase {
	
	function getInfo() {
    return array(
      'name' => t('Hook Taxonomy'),
      'description' => t('Test that hook_taxonomy effecitively cleans up.'),
      'group' => t('Calais')
    );
  }
  
	function testHookTaxonomy() {
		$vocab = $this->createVocabulary();
		$node = $this->drupalCreateNode();
		$term = $this->createTerm($vocab['vid']);
		$calais_term = new CalaisTerm($this->randomName(100), $term->name);
		calais_save_term($calais_term1);
		calais_apply_to_node($vocab['vid'], $calais_term, $node);
		
		$terms = taxonomy_node_get_terms($node);
		$this->assertEqual(count($terms), 1, 'Term found for node');
		$this->assertEqual(reset($terms)->tid, $calais_term->tdid, 'CalaisTerm tdid matches Term ID');
	
		taxonomy_del_term($term->tid);
		
		$found = calais_get_term($vocab['vid'], $calais_term->tid);
		$this->assertNull($found->tdid, 'CalaisTerm tdid is null');
	}
}

class CalaisFormSubmitTestCase extends CalaisTestCase {
	
	function getInfo() {
    return array(
      'name' => t('Submit Calais Form'),
      'description' => t('Test submitting the Calais tab form.'),
      'group' => t('Calais')
    );
  }

	// Associating new calais terms with an existing node
	function testFormSubmit() {
		$vocab = $this->createVocabulary();
		$vid = $vocab['vid'];
		$node = $this->drupalCreateNode();
		variable_set("calais_node_{$node->type}_process", CALAIS_PROCESS_AUTO);						
		variable_set('calais_vocabulary_names', array($vocab['name'] => $vocab['vid']));
		variable_set('calais_applied_entities_global', array($vocab['name'] => $vocab['name']));
		
		$calais_terms = array();
		$calais_terms[0] = new CalaisTerm($this->randomName(100), "TestTerm1", 1);
		$calais_terms[1] = new CalaisTerm($this->randomName(100), "TestTerm2", 1);
		$calais_terms[2] = new CalaisTerm($this->randomName(100), "TestTerm3", 1);

		foreach ($calais_terms as $calais_term) {
			calais_associate_term($vid, $calais_term, $node);
			$found = calais_get_term($vid, $calais_term->tid);
			$this->assertNull($found->tdid, 'Taxonomy Term ID is not set');
		}

		$form["taxonomy[tags][$vid]"] = "{$calais_terms[0]->name}, {$calais_terms[1]->name}";

		// Test validation error on non "tags" vocabulary
		$html = $this->drupalPost("node/{$node->nid}/calais", $form, t('Save'));
		$error = t('The @name vocabulary can not be modified in this way.', array('@name' => $vocab['name']));
		$this->assertText($error);

		$vocab['tags'] = TRUE;
		taxonomy_save_vocabulary($vocab);
		$html = $this->drupalPost("node/{$node->nid}/calais", $form, t('Save'));
		$this->assertNoText($error);
		$this->assertText(t('Calais settings have been saved.'));
		
		// //$node_terms = taxonomy_node_get_terms_by_vocabulary($node, $vid);
		$node_terms = taxonomy_node_get_terms($node);
		$this->assertEqual(count($node_terms), 2, 'Two Node Taxonomy Terms Exists');
		
		$term1 = reset($node_terms);
		$calais_term1 = calais_get_node_term_by_name($node->nid, $term1->name);
		$this->assertEqual($term1->tid, $calais_term1->tdid, 'Calais Term 1 has Tax Term ID set');
		
		$term2 = reset($node_terms);
		$calais_term2 = calais_get_node_term_by_name($node->nid, $term2->name);
		$this->assertEqual($term2->tid, $calais_term2->tdid, 'Calais Term 2 has Tax Term ID set');
	}	
}

/*
class CalaisTaxonomyTermLookupTestCase extends CalaisTestCase {
	
	function getInfo() {
    return array(
      'name' => t('Taxonomy Term Lookup'),
      'description' => t('Test finding a Taxonomy Terms fpr a Calais suggestion. This test the fall back from a GUID lookup, to a name lookup, to creation.'),
      'group' => t('Calais')
    );
  }

	// Associating new calais terms with an existing node
	function testLookupTerm() {
		$vocab = $this->createVocabulary();
		$vid = $vocab['vid'];
		$calais_term = new CalaisTerm($this->randomName(100), $this->randomName(20), 0.5);

		$current_terms = taxonomy_get_term_by_name($calais_term->value);
		$this->assertTrue(empty($current_terms), 'No Taxonomy Term Exist');

		// Find for term that does not exist
		$tid = calais_get_taxonomy_term($vid, $calais_term);
		$foundterm = taxonomy_get_term($tid);
		$this->assertTrue($foundterm, 'Taxonomy Term was created');
		$this->assertEqual($foundterm->name, $calais_term->value, 'Taxonomy Term value was setup correctly');
		
		// FInd for term that exists and has GUID set
		$term = $this->createTerm($vid, array('guid' => $this->randomName(100)));
		$calais_term = new CalaisTerm($term->guid, $term->name, 0.5);
		
		$tid = calais_get_taxonomy_term($vid, $calais_term);
		$this->assertEqual($tid, $term->tid, 'Correct Taxonomy Term was found by GUID');
		$foundterm = taxonomy_get_term($tid);
		$this->assertEqual($foundterm->name, $calais_term->value, 'Taxonomy Term value matches');
		$this->assertEqual($foundterm->guid, $calais_term->guid, 'Taxonomy Term guid matches');
		
		// Find for term that exists by name but does not have GUID set (null), GUID will get set
		$term = $this->createTerm($vid);
		$calais_term = new CalaisTerm($this->randomName(100), $term->name, 0.5);
		
		$tid = calais_get_taxonomy_term($vid, $calais_term);
		$this->assertEqual($tid, $term->tid, 'Correct Taxonomy Term was found by NAME');
		$foundterm = taxonomy_get_term($tid);
		$this->assertEqual($foundterm->name, $calais_term->value, 'Taxonomy Term value matches');
		$this->assertEqual($foundterm->guid, $calais_term->guid, 'Taxonomy Term guid was set and matches');

		// Find for term that exists by name but does not have GUID set (blank), GUID will get set
		$term = $this->createTerm($vid, array('guid' => ''));
		$calais_term = new CalaisTerm($this->randomName(100), $term->name, 0.5);
		
		$tid = calais_get_taxonomy_term($vid, $calais_term);
		$this->assertEqual($tid, $term->tid, 'Correct Taxonomy Term was found by NAME');
		$foundterm = taxonomy_get_term($tid);
		$this->assertEqual($foundterm->name, $calais_term->value, 'Taxonomy Term value matches');
		$this->assertEqual($foundterm->guid, $calais_term->guid, 'Taxonomy Term guid was set and matches');

		// Find for term that exists by name with no GUID. GUID should not get set
		$term = $this->createTerm($vid);
		//dvm(taxonomy_get_term($term->tid));
		$calais_term = new CalaisTerm(NULL, $term->name, 0.5);
		
		$tid = calais_get_taxonomy_term($vid, $calais_term);
		$this->assertEqual($tid, $term->tid, 'Correct Taxonomy Term was found by NAME');
		$foundterm = taxonomy_get_term($tid);
		$this->assertEqual($foundterm->name, $calais_term->value, 'Taxonomy Term value matches');
		$this->assertNull($foundterm->guid, 'Taxonomy Term guid was not set');

		// Find for term that exists by name with diff GUID. GUID should not get overwritten
		$term = $this->createTerm($vid, array('guid' => 'XxXxXxX'));
		$calais_term = new CalaisTerm(NULL, $term->name, 0.5);
		
		$tid = calais_get_taxonomy_term($vid, $calais_term);
		$this->assertEqual($tid, $term->tid, 'Correct Taxonomy Term was found by NAME');
		$foundterm = taxonomy_get_term($tid);
		$this->assertEqual($foundterm->name, $calais_term->value, 'Taxonomy Term value matches');
		$this->assertEqual($foundterm->guid, 'XxXxXxX', 'Taxonomy Term guid was not overwritten');
	}	
}
*/
