<?php

/**
 * MailContent class
 * Generated on Wed, 15 Mar 2006 22:57:46 +0100 by DataObject generation tool
 *
 * @author Carlos Palma <chonwil@gmail.com>
 */
class MailContent extends BaseMailContent {

	private $mail_data = null;

	/**
	 * Cache of account
	 * @var MailAccount
	 */
	private $account;

	protected $is_searchable = true;
	

	
	function getSummaryText () {
		return $this->getBodyPlain();
	}
	
	
	/**
	 * Array of searchable columns
	 * @var array
	 */
	protected $searchable_columns = array('from', 'from_name', 'to', 'cc', 'bcc', 'subject', 'body');
	 
	protected $mail_conversation_mail_ids;
	protected $mail_conversation_mail_ids_w_permissions;

	
	function getConversationMailIds($check_permissions = false){
		if ($check_permissions) {
			if (is_null($this->mail_conversation_mail_ids_w_permissions)) {
				$this->mail_conversation_mail_ids_w_permissions = MailContents::getMailIdsFromConversation($this, true);
			}
			return $this->mail_conversation_mail_ids_w_permissions;
		} else {
			if (is_null($this->mail_conversation_mail_ids)) {
				$this->mail_conversation_mail_ids = MailContents::getMailIdsFromConversation($this);
			}
			return $this->mail_conversation_mail_ids;
		} 
	}
	 
	/**
	 * Gets the owner mail account
	 * @return MailAccount
	 */
	function getAccount() {
		if (is_null($this->account)){
			$this->account = MailAccounts::findById($this->getAccountId());
		} //if
		return $this->account;
	}
	
	/**
	 * @author Ignacio Vazquez - elpepe.uy@gmail.com
	 * @param string $subject
	 * The subject is stored in two places: object.name and mailData.subject
	 */
	function setSubject($subject) {
		$this->getMailData()->setSubject($subject);
		$this->object->setName($subject);
	}
	
	function getSubject() {
		return $this->object->getName();
	}
	
	function getFullSubject() {
		return $this->getMailData()->getSubject();
	}
	
	function getTo() {
		return $this->getMailData()->getTo();
	}
	
	function setTo($to) {
		return $this->getMailData()->setTo($to);
	}
	
	function getCc() {
		return $this->getMailData()->getCc();
	}
	
	function setCc($cc) {
		return $this->getMailData()->setCc($cc);
	}
	
	function getBcc() {
		return $this->getMailData()->getBcc();
	}
	
	function setBcc($bcc) {
		return $this->getMailData()->setBcc($bcc);
	}
	
	function getBodyHtml() {
		return $this->getMailData()->getBodyHtml();
	}
	
	function setBodyHtml($html) {
		return $this->getMailData()->setBodyHtml($html);
	}
	
	function getBodyPlain() {
		return $this->getMailData()->getBodyPlain();
	}
	
	function setBodyPlain($plain) {
		return $this->getMailData()->setBodyPlain($plain);
	}
	
	 
	/**
	 * Validate before save
	 *
	 * @access public
	 * @param array $errors
	 * @return null
	 */
	function validate(&$errors) {
		if(!$this->validatePresenceOf('uid')) {
			$errors[] = lang('uid required');
		}
		if(!$this->validatePresenceOf('account_id')) {
			$errors[] = lang('account id required');
		}
	}
	
	function save() {
		parent::save();
		$this->getMailData()->setId($this->getId());
		$this->getMailData()->save();
	}

	/**
	 * @return MailData
	 */
	function getMailData() {
		if (!$this->mail_data instanceof MailData) $this->mail_data = MailDatas::findById($this->getId());
		if (!$this->mail_data instanceof MailData) $this->mail_data = new MailData();
		return $this->mail_data;
	}
	
	function delete($delete_db_record = true) {
		$rows = DB::executeAll("SELECT count(`object_id`) as `c` FROM `".TABLE_PREFIX."mail_contents` WHERE `conversation_id` = " . DB::escape($this->getConversationId()));
		if (is_array($rows) && count($rows) > 0) {
			if ($rows[0]['c'] < 2) {
				// if no other emails in conversation, delete conversation
				DB::execute("DELETE FROM `".TABLE_PREFIX."mail_conversations` WHERE `id` = " . DB::escape($this->getCOnversationId()));
			}
		}
		if ($delete_db_record) {
			return parent::delete();
		} else {
			return $this->mark_as_deleted();
		}
	}
	
	function clearEverything() {
		$this->clearContentFile();
		$this->clearMailData();
		parent::clearEverything();
	}
	
	function clearMailData() {
		if ($this->getMailData() instanceof MailData) {
			$this->getMailData()->delete();
		}
	}
	
	function clearContentFile() {
		if ($this->getContentFileId() != '') {
			try {
				FileRepository::deleteFile($this->getContentFileId());
			} catch (Exception $e) {
				//Logger::log($e->getMessage());
			}
		}
	}
	
	function mark_as_deleted(){
		$this->setIsDeleted(true);
		$this->clearEverything();
		return $this->save();
	}

	function getTitle(){
		return $this->getSubject();
	}
	
	/**
	 * Returns the mail content. If it is in repository returns the file content,
	 * else tries to get the content from database (if column content exists).
	 * @access public
	 * @param void
	 * @return string
	 */
	function getContent() {
		if (FileRepository::isInRepository($this->getContentFileId())) {
			return FileRepository::getFileContent($this->getContentFileId());
			//return FileRepository::getFileContent($this->getContentFileId(), config_option('file_storage_adapter'));
		} else if ($this->getMailData()->columnExists('content')) {
			return $this->getMailData()->getContent();
		}
	} 
	


	/**
	 * Returns if the field is classified
	 *
	 * @access public
	 * @param void
	 * @return boolean
	 */
	function getIsClassified() {
		$wspaces = $this->getWorkspaces();
		return (is_array($wspaces) && count($wspaces) > 0);
	} // getIsClassified()
	
	
	
	/**
	 * Returns if the mail is a draft
	 *
	 * @access public
	 * @param void
	 * @return boolean
	 */
	function getIsDraft() {
		return ($this->getState() == 2);
	} // getIsDraft()
	
	
	/**
	 * Returns if the mail was sent
	 *
	 * @access public
	 * @param void
	 * @return boolean
	 */
	function getIsSent() {
		return ($this->getState() == 1 || $this->getState() == 3);
	} // getIsSent()

	// ---------------------------------------------------
	//  URLs
	// ---------------------------------------------------

	/**
	 * Return view mail URL of this mail
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getViewUrl() {
		if ($this->getState() == 2)
			return $this->getEditUrl(); // For drafts only
		else
			return get_url('mail', 'view', $this->getId());
	} // getAccountUrl
	
	/**
	 * Return edit mail URL of this mail
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getEditUrl() {
		if ($this->getState() == 2)
			return get_url('mail', 'edit_mail', $this->getId()); // For drafts only
		else
			return get_url('mail', 'view', $this->getId());
	} // getAccountUrl
	
	function getShowContentsUrl() {
		return get_url('mail', 'view', $this->getId());
	} // getAccountUrl

	/**
	 * Return delete mail URL of this mail
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getDeleteUrl() {
		return get_url('mail', 'delete', $this->getId());
	} // getDeleteUrl

	/**
	 * Return classify mail URL of this mail
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getClassifyUrl() {
		return get_url('mail', 'classify', array( 'id' => $this->getId(), 'type' => 'email'));
	} // getClassifyUrl

	/**
	 * Return unclassify mail URL of this mail
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getUnclassifyUrl() {
		return get_url('mail', 'unclassify', array( 'id' => $this->getId(), 'type' => 'email'));
	} // getClassifyUrl
	
	/**
	 * Return send mail URL
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getSendMailUrl() {
		return get_url('mail', 'add_mail');
	} // getClassifyUrl

	/**
	 * Return reply mail URL
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getReplyMailUrl() {
		return get_url('mail', 'reply_mail', array( 'id' => $this->getId(), 'type' => 'email'));
	} // getReplyMailUrl
	
	
	/**
	 * Return forward mail URL
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getForwardMailUrl() {
		return get_url('mail', 'forward_mail', array( 'id' => $this->getId(), 'type' => 'email'));
	} // getForwardMailUrl
	
	/**
	 * Return print mail URL
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getPrintUrl() {
		return get_url('mail', 'print_mail', array( 'id' => $this->getId()));
	} // getPrintUrl
	
	function getSenderName() {
		$user = Contacts::getByEmail($this->getFrom());
		if ($user instanceof Contact && $user->canSeeUser(logged_user())) {
			return $user->getObjectName();
		} else {
			$contact = Contacts::getByEmail($this->getFrom());
			if ($contact instanceof Contact && $contact->canView(logged_user())) {
				return $contact->getObjectName();
			}
		}
		return $this->getFromName();
	}
	
	function getSenderUrl() {
		$user = Contacts::getByEmail($this->getFrom());
		if ($user instanceof Contact && $user->canSeeUser(logged_user())) {
			return $user->getCardUrl();
		} else {
			$contact = Contacts::getByEmail($this->getFrom());
			if ($contact instanceof Contact && $contact->canView(logged_user())) {
				return $contact->getCardUrl();
			}
		}
		return $this->getViewUrl();
	}
	
	// ---------------------------------------------------
	//  Permissions
	// ---------------------------------------------------

	/**
	 * Returns true if $user can view this email
	 *
	 * @param Contact $user
	 * @return boolean
	 */
	function canView(Contact $user) {	
		$account = $this->getAccount();
		if ($account) {
			return ( 
				$account->getContactId() == logged_user()->getId() || 
				can_read($user, $this->getMembers(), $this->manager()->getObjectTypeId())
			);	
		}else{
			return false;
		}
	}


	/**
	 * Returns true if $user can edit this email
	 *
	 * @param Contact $user
	 * @return boolean
	 */
	function canEdit(Contact $user) {	
		$account = $this->getAccount();
		if ($account) {
			return ( 
				$account->getContactId() == logged_user()->getId() || 
				can_write($user, $this->getMembers(), $this->manager()->getObjectTypeId())
			);	
		}else{
			return false;
		}
	} 

	/**
	 * Check if specific user can add contacts to specific project
	 *
	 * @access public
	 * @param Contact $user
	 * @param Project $project
	 * @return booelean
	 */
	function canAdd(Contact $user, $context, &$notAllowedMember = '') {
		return can_add($user, $context, $this->manager()->getObjectTypeId(), $notAllowedMember);
	} // canAdd

	/**
	 * Returns true if $user can delete this email
	 *
	 * @param Contact $user
	 * @return boolean
	 */
	function canDelete(Contact $user) {
		$account = $this->getAccount();
		if ($account) {
			return ( 
				$account->getContactId() == logged_user()->getId() || 
				can_delete($user,$this->getMembers(), $this->manager()->getObjectTypeId())
			);	
		}else{
			return false;
		}
	}

	// ---------------------------------------------------
	//  ApplicationDataObject implementation
	// ---------------------------------------------------

	function getSearchableColumnContent($column_name) {
		if ($column_name == 'body') {
			return $this->getTextBody();
		} else if ($this->getMailData()->columnExists($column_name)) {
			return $this->getMailData()->getColumnValue($column_name);
		} else {
			return parent::getSearchableColumnContent($column_name);
		}
	} // getSearchableColumnContent
	
    function addToSearchableObjects($wasNew = false){
    	$columns_to_drop = array();
    	if ($wasNew)
    		$columns_to_drop = $this->getSearchableColumns();
    	else {
			foreach ($this->getSearchableColumns() as $column_name){
				if (isset($this->searchable_composite_columns[$column_name])){
					foreach ($this->searchable_composite_columns[$column_name] as $colName){
						if ($this->isColumnModified($colName)){
							$columns_to_drop[] = $column_name;
							break;
						}
					}
				} else if ($column_name == 'body') {
					$columns_to_drop[] = $column_name;
				} else if ($this->getMailData()->columnExists($column_name) && $this->getMailData()->isColumnModified($column_name)) {
					$columns_to_drop[] = $column_name;
				} else if ($this->isColumnModified($column_name)) {
					$columns_to_drop[] = $column_name;
				}
			}
    	}
    	
    	if (count($columns_to_drop) > 0){
    		SearchableObjects::dropContentByObjectColumns($this,$columns_to_drop);
    		
	        foreach($columns_to_drop as $column_name) {
	          $content = $this->getSearchableColumnContent($column_name);
	          if(trim($content) <> '') {

	            $searchable_object = new SearchableObject();
	            
	            $searchable_object->setRelObjectId($this->getObjectId());
	            $searchable_object->setColumnName($column_name);
	            $searchable_object->setContent($content);
	            $searchable_object->setContactId($this->getAccount() instanceof MailAccount ? $this->getAccount()->getContactId() : 0);
	            //$searchable_object->setProjectId(0); TODO Feng 2 setDefault Member
	            $searchable_object->save();
	          } // if
	        } // foreach
    	} // if
    	
    	if ($wasNew){
        	SearchableObjects::dropContentByObjectColumns($this,array('uid'));
        	$searchable_object = new SearchableObject();
            
            //$searchable_object->setRelObjectManager(get_class($this->manager()));
            $searchable_object->setRelObjectId($this->getObjectId());
            $searchable_object->setColumnName('uid');
            $searchable_object->setContent($this->getUniqueObjectId());

            
            $searchable_object->save();
        }
    }
	
	/**
	 * Return object name
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getObjectName() {
		return $this->getName();
	} // getObjectName

	/**
	 * Return object type name
	 *
	 * @param void
	 * @return string
	 */
	function getObjectTypeName() {
		return $this->manager()->object_type_name;

	} 

	/**
	 * Return object URl
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getObjectUrl() {
		return $this->getViewUrl();
	} // getObjectUrl


	/**
	 * Return value of 'subject' field
	 *
	 * @access public
	 * @param void
	 * @return string
	 */
	function getName() {
		return $this->getSubject();
	} // getSubject()


  function getDashboardObject(){
    	$projectId = "0";
    	$project = "";
    	if (count($this->getWorkspaces()) > 0) {
    		$type = "email";
    	} else {
    		$type = "emailunclassified";
    	}
    	$tags = project_object_tags($this);
    	
    	$deletedOn = $this->getTrashedOn() instanceof DateTimeValue ? ($this->getTrashedOn()->isToday() ? format_time($this->getTrashedOn()) : format_datetime($this->getTrashedOn(), 'M j')) : lang('n/a');
		if ($this->getTrashedById() > 0)
			$deletedBy = Contacts::findById($this->getTrashedById());
    	if (isset($deletedBy) && $deletedBy instanceof Contact) {
    		$deletedBy = $deletedBy->getObjectName();
    	} else {
    		$deletedBy = lang("n/a");
    	}
		
    	if ($this->getState() == 1 || $this->getState() == 3 || $this->getState() == 5) {
    		$createdBy = $this->getCreatedBy();
    	}
    	if (isset($createdBy) && $createdBy instanceof Contact) {
    		$createdById = $createdBy->getId();
    		$createdBy = $createdBy->getObjectName();
    	} else {
    		$createdById = 0;
    		$createdBy = $this->getFromName();
    	}
    	
  		$archivedOn = $this->getArchivedOn() instanceof DateTimeValue ? ($this->getArchivedOn()->isToday() ? format_time($this->getArchivedOn()) : format_datetime($this->getArchivedOn(), 'M j')) : lang('n/a');
  		if ($this->getArchivedById() > 0)
			$archivedBy = Contacts::findById($this->getArchivedById());
    	if (isset($archivedBy) &&  $archivedBy instanceof Contact) {
    		$archivedBy = $archivedBy->getObjectName();
    	} else {
    		$archivedBy = lang("n/a");
    	}
    	
    	$sentTimestamp = $this->getReceivedDate() instanceof DateTimeValue ? ($this->getReceivedDate()->isToday() ? format_time($this->getReceivedDate()) : format_datetime($this->getReceivedDate())) : lang('n/a');
    	
		return array(
				"id" => $this->getObjectTypeName() . $this->getId(),
				"object_id" => $this->getId(),
				"name" => $this->getObjectName() != "" ? $this->getObjectName():lang('no subject'),
				"type" => $type,
				"tags" => $tags,
				"createdBy" => $createdBy,
				"createdById" => $createdById,
				"dateCreated" => $sentTimestamp,
				"updatedBy" => $createdBy,
				"updatedById" => $createdById,
				"dateUpdated" => $sentTimestamp,
				"wsIds" => $this->getWorkspacesIdsCSV(logged_user()->getWorkspacesQuery()),
    			"url" => $this->getObjectUrl(),
				"manager" => get_class($this->manager()),
    			"deletedById" => $this->getTrashedById(),
    			"deletedBy" => $deletedBy,
    			"dateDeleted" => $deletedOn,
    			"archivedById" => $this->getArchivedById(),
    			"archivedBy" => $archivedBy,
    			"dateArchived" => $archivedOn,
				"subject" => $this->getSubject(),
				"isRead" => $this->getIsRead(logged_user()->getId())
		);
	}
	
	/**
	 * Returns a plain text version of the email
	 * @return string
	 */
	function getTextBody() {
		if ($this->getBodyHtml()) {
			return html_to_text(html_entity_decode($this->getBodyHtml(),null, "UTF-8"));
		} else {
			return $this->getBodyPlain();
		}
	}
	
	
	function getFromContact(){
		$contacts = Contacts::findAll(array(
			'conditions' => " jt.email_address = '".clean($this->getFrom())."'",
			'join' => array(
				'jt_table' => ContactEmails::instance()->getTableName(),
				'jt_field' => 'contact_id',
				'e_field' => 'object_id',
			),
		));
		
		if (is_array($contacts) && count($contacts) > 0){
			return $contacts[0];
		}
		return null;
	}
	
	function getLinkedObjects() {
		$conv_emails = MailContents::getMailsFromConversation($this);
		$objects = array();
		foreach ($conv_emails as $mail){
			if(logged_user()->isMemberOfOwnerCompany()) {
				$mail_objects = $mail->getAllLinkedObjects();
			} else {
				if (is_null($mail->linked_objects)) {
					$mail->linked_objects = LinkedObjects::getLinkedObjectsByObject($this, true);
				}
				$mail_objects = $mail->linked_objects;
			}
			if (is_array($mail_objects)){
				foreach ($mail_objects as $mo){
					$objects[] = $mo;
				}
			}
		}
		
		if ($this->isTrashed()) {
			$include_trashed = true;
		} else {
			$include_trashed = false;
		}
		
		if ($include_trashed) {
			return $objects;
		} else {
			$ret = array();
			if (is_array($objects) && count($objects)) {
				foreach ($objects as $o) {
					if (!$o instanceof ContentDataObject || !$o->isTrashed()) {
						$ret[] = $o;
					}
				}
			}
			return $ret;
		}
	}
	

	/**
	 * Return object comments, filter private comments if user is not member of owner company
	 *
	 * @param void
	 * @return array
	 */
	function getComments() {
		return Comments::getCommentsByObjectIds(implode(',',$this->getConversationMailIds(true)), 'MailContents');
	} // getComments
	
	

	/**
	 * Return tag names for this object
	 *
	 * @access public
	 * @param void
	 * @return array
	 */
	function getTagNames() {
		//Seba ver si es lo mismo ya que siempre que un mail esta en un tag los otros tambien
		//if (user_config_option('show_emails_as_conversations',true,logged_user()->getId())){
		if (user_config_option('show_emails_as_conversations')){
			return Tags::getTagNamesByObjectIds(implode(',',$this->getConversationMailIds(true)), 'MailContents');
		}else{
			return parent::getTagNames();
		}
	} // getTagNames
	
	
	
	function addToStatus($amount) {
		try {
			DB::beginWork();
			$state = -1;
			$saved = "false";
			$state = $this->getState();
			$this->setState($state + $amount);
			$this->save();
			$saved = "true";
			DB::commit();
			return true;
		} catch (Exception $e) {
			Logger::log("Could not advance email state, email skipped: ".$e->getMessage()."\nmail_id=".$this->getId()."\nstate=$state\nsaved=$saved");
			DB::rollback();
		}
		return false;
	}
	
	
	/**
	 * Override defaults. 
	 * Also adds mail to sharing table if is not categorized. 
	 * Only permissions for the account owner.  
	 * 
	 * @see ContentDataObject::addToSharingTable()
	 */
	function addToSharingTable() {	
		parent::addToSharingTable();
		$id = $this->getId();
		
		if(!$this->getAccount() instanceof MailAccount) return;
		
		$contactId = $this->getAccount()->getContactId();
		$contact = Contacts::instance()->findById($contactId);
		
		if (!$contact instanceof Contact) return;
		
		$group_id = $contact->getPermissionGroupId();
		if ($group_id) {
			$sql = "INSERT INTO ".TABLE_PREFIX."sharing_table ( object_id, group_id ) VALUES ($id,$group_id) ON DUPLICATE KEY UPDATE group_id = group_id ";
			DB::execute($sql);
		}
	}
}
