<?php

/**
 * file: vault_two.php
 *
 *  Major re-working of the vault idea.

 */

class FirstpassShell extends Shell {


    var $uses = array('Enquiry', 'Contact', 'Invoice', 'PurchaseOrder', 'User', 'Email', 'EmailRecipient', 'Job');

    // var $email_dir = '/var/www/cakephp/app/emails';

    function main() {

	/******************************************************
         * Config Variables
         * *****************************************************/
	$testing = 1; //Whether to actually move the emails. 1=test, 0=production
	/* Setup Connection to the IMAP server */
	$username = 'vault';
	$password = 'xjdYOsmJWc37'; /* The password for the account to be checked */


	if($testing == 1) {

	    //$username = 'karl';
	    //$password = '72seng89';
	    $ripmime_path = '/opt/local/bin/ripmime';
	    $email_dir = '/Users/karlcordes/Sites/quotenik/app/emails';
	    //$mbox = imap_open("{mail.cmctechnologies.com.au:143}INBOX", $username, $password) or die("can't connect: " . imap_last_error()
	    //);
	    //$mbox = imap_open("{192.168.0.8:143}INBOX", $username, $password) or die("can't connect: " . imap_last_error());

	    define('EML_FILE_PATH', '/Users/karlcordes/Sites/quotenik/app/vendors/shells/');

	    $filename = 'sample.eml';
	    $debug = 1;

	    // Read the file
	    if (!($content = fread(fopen(EML_FILE_PATH.$filename, 'r'), filesize(EML_FILE_PATH.$filename))))
		die('File not found ('.EML_FILE_PATH.$filename.')');

//Handle files coming from windows (\r\n vs \n):
//   Thanks to Dan Hulme (dhulme@gmail.com)
	    $content = str_replace("\r", "", $content);

// Keep a copy of the original file
	    $raw=$content;

	    $headers = imap_rfc822_parse_headers($content);

	    //print_r($headers);
 //$message = $this->getMessage($mbox, $i, $this_header);
	    $recipients = $this->getRecipients($headers, true);
	    print_r($recipients);
	    die();
	}
	else {
	    $ripmime_path = '/usr/local/bin/ripmime';
	    $email_dir = '/var/www/cakephp/app/emails';
	    $mbox = imap_open("{192.168.0.8:143/novalidate-cert}INBOX", $username, $password) or die("can't connect: " . imap_last_error());
	}


	$MC = imap_check($mbox);
	$number_of_messages = $MC->Nmsgs;

	echo "Number of messages to Process ".$number_of_messages."\n";


	if($number_of_messages == 0) {
	    exit(0);
	}


	/* Find the strings we want to look for in the subjects. Build arrays
	 * using the string as the keys, IDs as the value
	*/


	$enquiries = $this->Enquiry->find('all', array('recursive'=>0,
		'fields' => array('Enquiry.title', 'Enquiry.id')));

	$invoices = $this->Invoice->find('all', array('recursive'=>0, '
	    fields'=>array('Invoice.id', 'Invoice.title')));

	$purchaseOrders = $this->PurchaseOrder->find('all',
		array('recursive'=>0,
		'fields'=>array('PurchaseOrder.id', 'PurchaseOrder.title')));

	$users = $this->User->find('all', array('recursive'=>0,
		'fields'=>array('User.id', 'User.email')));

	$jobs = $this->Job->find('all', array('recursive'=>0, 'fields'=>array('Job.id', 'Job.title')));

	$enquiryMap = $this->makeMap($enquiries,'Enquiry', 'title');
	$invoiceMap = $this->makeMap($invoices, 'Invoice', 'title');
	$poMap = $this->makeMap($purchaseOrders, 'PurchaseOrder', 'title');
	$userMap = $this->makeMap($users, 'User', 'email');
	$jobMap = $this->makeMap($jobs, 'Job', 'title');


	$store = array();
	$discard = array();



	/**
	 * Loop through the messages.
	 *
	 * Procedure:
	 *
	 * 1. Check to see if the recipients (CC, or to), or Sender is in the $userMap.
	 *  1a. If one of these is true, we need to capture this email. Else, delete it.
	 *
	 * 2. This email is either to/from/CC a user in the system.
	 *	We need to associate it with the right PO/Invoice/Enquiries etc.
	 *	Check the subject for patterns that match Identifiers.
	 *
	 */
	//for($i=$number_of_messages; $i > 0; $i--) {
	while($number_of_messages > 0) {
	    if(!imap_ping($mbox)) {
		echo "Connection to Mailserver dropped. Attempting to reconnect\n";
		$mbox = imap_open("{mail.cmctechnologies.com.au:143}INBOX", $username, $password) or die("can't connect: " . imap_last_error());
	    }


	    $this_header = imap_headerinfo($mbox, $i);

	    $this_uid = imap_uid($mbox, $i);


	    $unix_time = $this_header->udate;	//Used for filing attachments into month-year folders.
	    //MM-YYYY used For lack of a better option really.

	    //$message = $this->getMessage($mbox, $i, $this_header);
	    $recipients = $this->getRecipients($this_header, true);



	    // continue;
	    //die();
	    $saveThis = false; //Set to true, if To,From,CC is a Known User.
	    $fromKnownUser = false;


	    foreach($recipients['to'] as $email) {
		$saveThis = $this->userExists($email, $userMap);
	    }
	    foreach($recipients['from'] as $email) {
		$saveThis = $this->userExists($email, $userMap);
		$fromKnownUser = $saveThis;
	    }

	    foreach($recipients['cc'] as $email) {
		$saveThis = $this->userExists($email, $userMap);
	    }


	    //print_r($recipients);

	    if(!isset($this_header->subject)) { //Emails without a subject are not welcome. Skip it.
		$discard[] = $this_uid;
		continue;
	    }

	    $subjDecoded = imap_mime_header_decode($this_header->subject);

	    $foundIdent = false;


	    foreach($subjDecoded as $sub) {

		$found_enquiries = $this->checkValidIdentifier($sub->text, $enquiryMap, 'enquiry');
		$foundIdent = $this->foundIdentifier($found_enquiries);

		$found_invoices = $this->checkValidIdentifier($sub->text, $invoiceMap, 'invoice');
		$foundIdent = $this->foundIdentifier($found_invoices);


		$found_pos = $this->checkValidIdentifier($sub->text, $poMap, 'purchaseorder');
		$foundIdent = $this->foundIdentifier($found_pos);


		$found_jobs = $this->checkValidIdentifier($sub->text, $jobMap, 'job');
		$foundIdent = $this->foundIdentifier($found_jobs);

		//echo "["$sub->.$sub->text;
	    }


	    //We're going to save this Email.
	    //Lets grab the attachments (if any) then create the appropiate Objects.


	    if($fromKnownUser == true || $saveThis == true || $foundIdent == true) {
		$store[] = $this_uid;
		echo "email $i will be saved: Subject: ".$subjDecoded[0]->text."\n";
	    }
	    else {
		$discard[] = $this_uid;
		echo "email {$i} will not be saved. Subject: ".$subjDecoded[0]->text."\n";
	    }
	    //  print_r($recipients);
	    //  echo "----------------------\n";


	    $MC = imap_check($mbox);
	    $number_of_messages = $MC->Nmsgs;
	    echo "Number of messages to Process is now ".$number_of_messages."\n";


	}


	reset($discard);
	reset($store);

	$numberToStore = count($store);
	$numberToDiscard= count($discard);


	if($numberToStore > 0) {
	    echo "Got $numberToStore messages to store\n";
	    $storeSet = implode(",", $store);
	    //imap_mail_move($mbox, $storeSet, 'INBOX/Stored', 1);
	}

	if($numberToDiscard > 0) {
	    echo "Going to discard $numberToDiscard messages\n";
	    $discardSet = implode(",",$discard);
	    //imap_mail_move($mbox, $discardSet, 'INBOX/Discarded', 1);
	}





	imap_expunge($mbox);

	imap_close($mbox);
    }



    /**
     * Make a 'HashMap' (array) in the format.
     * $newMap[$key] = $obj[$modelName]['id'];
     *
     * @param array $objects
     * @param string $modelName
     * @param string $keyName
     * @return array
     */
    function makeMap($objects,$modelName, $keyName) {
	$newMap = array();
	foreach ($objects as $obj) {

	    $key = $obj[$modelName][$keyName];
	    if($modelName == 'User') {
		strtolower($key);
	    }

	    $newMap[$key] = $obj[$modelName]['id'];

	}
	return $newMap;
    }


    /**
     *
     * @param <type> $recipient
     * @param <type> $emailMap
     * @return <type>
     */
    function userExists($recipient, &$emailMap) {
	if(isset($emailMap[$recipient])) {
	    //echo "$recipient is a user in the system. Will be saved\n";
	    return true;
	}
	else {
	    return false;
	    //echo "$recipient is not a user in the system.\n";
	}
    }


    /**
     *
     * @param <type> $subject
     * @param <type> $list
     * @param <type> $type
     */
    function checkValidIdentifier($subject, &$list, $type) {

	$returnArray = array();

	if($type == 'enquiry') {
	    preg_match("/CMC\d+([NVQWSOT]|ACT|NT)E\d+-\d+/", $subject, $output);
	}
	else if ($type == 'invoice') {
	    preg_match("/CMCIN\d+/", $subject, $output);
	}
	else if ($type == 'purchaseorder') {
	    preg_match("/CMCPO\d+/", $subject, $output);
	}
	else if($type == 'job') {
	    preg_match("/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\d+(N|V|W|S|T|NT|ACT)J\d+/", $subject, $output);
	}

	foreach($output as $match) {
	    if(isset($list[$match])) { //check if it actually exists.
		$returnArray[] = $list[$match];
	    }
	}

	return $returnArray;

    }

    /**
     *
     * @param <type> $found_identifier
     * @return <type>
     */
    function foundIdentifier(&$found_identifier) {
	if(count($found_identifier) > 0) {
	    return true;
	}
	else {
	    return;
	}
    }




    function getMessage($mbox, $msgnumber, $headers) {

	//$subject = $headers->subject;
	//$subject = iconv_mime_decode($subject, 0, "ISO-8859-1//IGNORE");
	// $subject = mb_convert_encoding($subject, "ISO-8859-1");
	// $subject = mb_convert_encoding($subject, "UTF-8");
	//$subject = mb_decode_mimeheader($subject);

	$date = $headers->date;

	$message['subject'] = $subject;
	$message['date'] = $date;

	return $message;

    }

    /**
     * get Recipients from the headers of an email
     *
     */
    function getRecipients($headers) {

	$recipients['to'] = array();
	$recipients['from'] = array();
	$recipients['cc'] = array();

	if(isset($headers->to)) {
	    $recipients['to'] = $this->buildEmailArray($headers->to);
	}
	if(isset($headers->cc)) {
	    $recipients['cc'] = $this->buildEmailArray($headers->cc);
	}
	if(isset($headers->from)) {
	    $recipients['from'] = $this->buildEmailArray($headers->from);
	}

	return $recipients;
    }

    /**
     * Build an array containing email addresses from the header object
     * passed to it.
     *
     * @param Object $recipientObj
     * @return Array
     */
    function buildEmailArray($recipientObj) {
	$recipientList = array();
	if(count($recipientObj) > 0) {
	    foreach($recipientObj as $id=> $object) {
		$recipientList[] =  strtolower($object->mailbox."@".$object->host);
	    }
	    return $recipientList;
	}
    }




    /*
    * Fetches the body and attachments from a MIME encoded email. Uses ripmime to do the decoding
    *
    */

    function fetchBodyAttachments($mailbox, $msg_number, $email_dir, $relative_path, $ripmime_path) {

	$uuid = String::uuid();
	$email_file = $email_dir.'/'.$uuid.'.eml';
	imap_savebody($mailbox, $email_file, $msg_number);
	$command = "$ripmime_path -i $email_file -d $email_dir/$relative_path --prefix --paranoid -v --verbose-contenttype --recursion-max 30";

	$output = array();
	exec($command, $output, $status);

	/* Check the $output array and find the filenames of the attachments */

	if($status == 0) {
	    $attachments = array();

	    $biggestHTML_num = 999;  //Determine the likely HTML body of this email. Guessing, but hopefully reasonably correctly.
	    $biggestHTML_size = 0;
	    $biggestPlain_num = 999; //I dont think we'll get legit emails with >999 attachments.
	    $biggestPlain_size =0;

	    for($i=0, $j=0; $i< count($output); $i++, $j++) {
		$words = explode(' ', $output[$i]);
		$type = explode('=', $words[1]);
		$name = explode('=', $words[2]);

		/*echo "OUTPUT\n";
		print_r($output);
		echo count($output)."\n";

		echo "TYPE\n";
		print_r($type);

		echo count($type)."\n";
		*/
		if(count($type) != 2) {
		    //echo "Didnt find a proper type. Skipping it.";
		    continue;
		}

		if(count($name) != 2) {
		    //echo "Didnt find a proper name. Skipping it";
		    continue;
		}

		$oldNamePath = $email_dir.'/'.$relative_path.'/'.$name[1];
		$newNamePath = $email_dir.'/'.$relative_path.'/'.$uuid.'-'.$name[1];
		$newName = $relative_path.'/'.$uuid.'-'.$name[1];
		rename($oldNamePath, $newNamePath);
		$size = filesize($newNamePath);
		$attachments[$j]['type'] = $type[1];


		$attachments[$j]['name'] = $newName;
		$attachments[$j]['filename'] = $name[1];
		$attachments[$j]['size'] = $size;
		$attachments[$j]['is_message_body'] = 0;
		echo "in message number $msg_number: found attachment ".$attachments[$j]['name'].' '.$attachments[$j]['type']."\n";


		/** Record the array ID and size of the largest HTML & plain attachments **/
		if($attachments[$j]['type'] == 'text/html') {
		    if($size > $biggestHTML_size) {
			$biggestHTML_num = $j;
			$biggestHTML_size = $size;
		    }
		}
		else if($attachments[$j]['type'] == 'text/plain') {
		    if($size > $biggestPlain_size) {
			$biggestPlain_num = $j;
			$biggestPlain_size = $size;
		    }
		}
	    }
	    if($biggestHTML_num != 999) { //We found an HTML attachment.
		$attachments[$biggestHTML_num]['is_message_body'] = 1;
	    }
	    else if($biggestPlain_num != 999) {
		$attachments[$biggestPlain_num]['is_message_body'] = 1;
	    }

	    unlink($email_file);
	    return $attachments;
	}
	else {
	    unlink($email_file);
	    return 1;
	}
    }


    /**
     * Passed the configured $email_dir and the unix time of this message.
     *
     * 1. Checks to see if the /emails/MM-YYYY/ directory exists.
     * 2a. If not, creates it and returns the full path to this directory.
     * 2b. If exists, returns the path to this directory.
     *
     * @param <type> $email_dir
     * @param <type> $unix_time
     */
    function getAttachmentDirectory($email_dir, $unix_time) {

	$month_year = date('m-Y', $unix_time);
	$path = $email_dir."/".$month_year;

	if(!file_exists($path)) { //Directory doesn't exist Lets make it!
	    if(mkdir($path)) {
		return $month_year;
	    }
	    else {
		die("Unable to make directory $email_dir/$month_year");
	    }
	}
	else {
	    return $month_year;
	}

    }


    /**
     * The attachments have been decoded and written to disk by ripmime.
     *
     * 1. Generate a uuid for this email
     * 2. Is there a month-year folder this this current month? If not, make one.
     * 3. Move the attachments to the correct month-year Folder. Prefix their new names with uuid.
     * 4.
     *
     * @param <type> $attachments

     function moveAttachments($attachments, $email_dir, $unix_time) {

     $month_year = date('m-Y');


     $uuid = String::uuid();




     foreach($attachments as $attachment) {
     echo $email_dir.'/'.$attachment['name']."\n";
     }
     die();

     }*/


}


?>