<?php
class PhenotypesController extends AppController {

	var $name = 'Phenotypes';
    var $helpers = array('Html', 'Form', 'Ajax', 'Javascript');
    var $components = array('RequestHandler');
    var $uses = array('Phenotype','Attribute', 'Entity');

    var $error_msg = false;

	function upload() {
		// offer options for date format
		$dateFormatOptions = array('yyyy-mm-dd' => 'yyyy-mm-dd', 'dd.mm.yyyy' => 'dd.mm.yyyy', 'dd.mm.yy' => 'dd.mm.yy', 'dd/mm/yyyy' => 'dd/mm/yyyy', 'mm/dd/yyyy' => 'mm/dd/yyyy');
		$this->set(compact('dateFormatOptions'));
		
		libxml_use_internal_errors(true);
		
		// doing some checks
		if (!empty($this->data)) {
			if ($this->data['File']['raw']['error']) { # as we cannot validate this field, give an error when it's non-existing
                    $this->Session->setFlash(__('Please select a file to upload!', true));
					return;
			}
			$xmlDoc = new DOMDocument();
			if (!$xmlDoc->load($this->data['File']['raw']['tmp_name'])) {
				$this->Session->setFlash(__('Could not load XML document! - Please check if it is readable and contains correct XML!', true));
				return;
			}
			if ($this->data['File']['validate']) { # user has chosen the validate option - the file will be checked against an xsd schema
				if (!$xmlDoc->schemaValidate('xml/ResultFile.xsd')) {
					$xmlErrors = libxml_get_errors();
					$xmlErrorMessage = $xmlErrors[0]->message;
					$this->Session->setFlash(__("Document not valid: '$xmlErrorMessage'!", true));
					return;
				}
			}
			# parse the xml file
			$testPrograms = $xmlDoc->getElementsByTagName('TESTPROGRAM');
			if ($testPrograms->length == 0) {
				$this->Session->setFlash(__('Result file does not contain any TESTPROGRAM tag!', true));
				return;
			}
			if ($testPrograms->length > 1) { //MobilePhenotyper does not produce files with more than one TESTPROGRAM tag, but maybe we should allow it anyway?
				$this->Session->setFlash(__('More than one TESTPROGRAM tag in result file!', true));
				return;
			}
			$testProgramID = 0;
			$objecttype_id = 7; //default type 'undefined'
			foreach ($testPrograms as $testProgram) {
				$testProgramID = $testProgram->getAttribute('ID');
				$objecttype_id = $testProgram->getAttribute('OBJECT_TYPE');
				if ($objecttype_id == NULL || $objecttype_id == 0) { // we are reading an old result file
					$objecttype_id = 7;
				}
			}
			$testObjects = $xmlDoc->getElementsByTagName('TEST_OBJECT');
			if ($testObjects->length == 0) { // we are reading an old result file
				$testObjects = $xmlDoc->getElementsByTagName('SAMPLE');
			}
			if ($testObjects->length == 0) {
				$this->Session->setFlash(__('File does not contain any test object!', true));
				return;
			}
			# for success/error statistics
			$resultDatasetCount = 0;
			$successCount = 0;
			$errorCount = 0;
			
			foreach ($testObjects as $testObject) {
				$testObjectID = $testObject->getAttribute('ID');
				$testObjectMultiplication = $testObject->getAttribute('MULTIPLICATION');
				$testObjectTimeStamp = $testObject->getAttribute('TIMESTAMP');
				$testObjectTimeAndDate = explode(" ", $testObjectTimeStamp);
				if (count($testObjectTimeAndDate) == 2) {
					$date = $testObjectTimeAndDate[0];
					$time = $testObjectTimeAndDate[1];
				} else {
					$testObjectTimeAndDate = explode("T", $testObjectTimeStamp); //time and date according to ISO 8601
					$date = $testObjectTimeAndDate[0];
					$time = $testObjectTimeAndDate[1];
				}
				$date = $this->_convert_date($date);
				//$time = $this->_convert_time($time); // has to be implemented, but that seems not to be very urgent - MySQL can handle several time formats
				
				$parameters = $testObject->getElementsByTagName('PARAMETER');
				foreach ($parameters as $parameter) {
					$parameterID = $parameter->getAttribute('ID');
					$parameterChildren = $parameter->childNodes;
					foreach ($parameterChildren as $parameterChild) {
						if ($parameterChild->nodeType != 3 && $parameterChild->nodeName == 'ATTRIBUTE') {
							$result = $this->parseAttribute($testObjectID, $parameterChild, $date, $time, $parameterID, $objecttype_id, $testProgramID);
							$resultDatasetCount += $result["dataSetCount"];
							$successCount += $result["successCount"];
							$errorCount += $result["errorCount"];
						} else if ($parameterChild->nodeType != 3 && $parameterChild->nodeName == 'VALUE_GROUP') {
							$attributes = $parameterChild->getElementsByTagName('ATTRIBUTE');
							foreach ($attributes as $attribute) {
								$result = $this->parseAttribute($testObjectID, $attribute, $date, $time, $parameterID, $objecttype_id, $testProgramID);
								$resultDatasetCount += $result["dataSetCount"];
								$successCount += $result["successCount"];
								$errorCount += $result["errorCount"];
							}
						}
					}
				}
			}
			$this->Session->setFlash("Parsed '$resultDatasetCount' data sets; success (saved): '$successCount' errors: '$errorCount'");
		}
	}
	
	function parseAttribute($object_id, $attribute, $date, $time, $entity_id, $objecttype_id, $program_id) {
		$value_id = $attribute->getAttribute('ID');
		$attributeChildren = $attribute->childNodes;
		$result = array("dataSetCount" => 0, "successCount" => 0, "errorCount" => 0);
		foreach ($attributeChildren as $attributeChild) {
			if ($attributeChild->nodeType != 3 && $attributeChild->nodeName == 'VALUE') {
				$result["dataSetCount"] ++;
				$number = $attributeChild->nodeValue;
				$this->Phenotype->begin();
				$person = $this->Session->read('Auth.Person');
				$person_id = $person['id'];
				if($this->_save_phenotype(compact('program_id', 'object_id', 'objecttype_id', 'date', 'time', 'entity_id', 'value_id', 'number', 'person_id'))) {
					$this->Phenotype->commit();
					$result["successCount"] ++;
				} else {
					$this->Phenotype->rollback();
					$result["errorCount"] ++;
				}
			}
		}
		return $result;
	}
	

	function _save_phenotype($tuples) {
        # save the phenotyping info
        $this->Phenotype->create();
        $phenotype = $this->Phenotype->save(array(
            'Phenotype' => $tuples # 'program_id', 'object_id', 'objecttype_id', 'date', 'time', 'entity_id', 'value_id', 'number', 'person_id'
        ));
        if (empty($phenotype)) {
			$this->Session->setFlash('Could not save phenotyping data!');
            $this->Phenotype->rollback();
            $this->error_msg = 'Failed to create Phenotype!';
            return false;
        }
        else {
            $phenotype['Phenotype']['id'] = $this->Phenotype->getLastInsertID();
        }

        return $phenotype;
    }
 

    /**
     * Converts date according to the chosen date format to yyyy-mm-dd format.
     */
    function _convert_date($date) {
		if ($this->data['Phenotypes']['dateFormat'] == 'dd/mm/yyyy') {
			list($day, $month, $year) = preg_split('/[^0-9]/', $date);
		} else if ($this->data['Phenotypes']['dateFormat'] == 'mm/dd/yyyy') {
			list($month, $day, $year) = preg_split('/[^0-9]/', $date);
		} else if ($this->data['Phenotypes']['dateFormat'] == 'dd.mm.yyyy' || $this->data['Phenotypes']['dateFormat'] == 'dd.mm.yy') {
			list($day, $month, $year) = preg_split('.[^0-9].', $date);
		} else if ($this->data['Phenotypes']['dateFormat'] == 'yyyy-mm-dd') {
			list($year, $month, $day) = preg_split('.[^0-9].', $date);
		} else {
			// maybe implement an automated parsing here
			return $date;
		}
		
        return "$year-$month-$day";
    }
	
	function _convert_time($time) {
		//TODO: implement
	}
}
?>
