<?php

  /**
   * Base notifier helper implementation
   * 
   * @package angie.frameworks.email
   * @subpackage 
   */
  class INotifierImplementation {
  	
  	/**
  	 * Parent object instance
  	 * 
  	 * @var INotifier
  	 */
  	protected $object;
  	
  	/**
  	 * Construct notify helper implementation
  	 * 
  	 * @param INotifier $object
  	 */
  	function __construct(INotifier $object) {
  		$this->object = $object;
  	} // __construct
  	
  	/**
  	 * Notify one or more users about an even
  	 * 
  	 * @param mixed $users
  	 * @param INotifierContext $context
  	 * @param mixed $event
  	 * @param array $event_params
  	 * @param array $additional
  	 */
  	function notifyUsers($users, INotifierContext $context, $event, $event_params = null, $additional = null) {
  		if($users instanceof IUser) {
  			$to_notify = array($users);
  		} elseif(is_foreachable($users)) {
  			$to_notify = $users;
  		} // if
  		
  		if(isset($to_notify)) {
        $exclude_emails = array();
        if (!$this->object instanceof AnonymousUser) {
          $exclude_emails[] = $this->object->getEmail();
        } // if
  		  
  		  if(isset($additional['exclude']) && $additional['exclude']) {
    		  if($additional['exclude'] instanceof IUser) {
    		    $exclude_emails[] = $additional['exclude']->getEmail();
    		  } elseif(is_array($additional['exclude'])) {
    		    foreach($additional['exclude'] as $v) {
    		      if($v instanceof IUser) {
    		        $exclude_emails[] = $v->getEmail();
    		      } elseif(is_string($v) && is_valid_email($v)) {
    		        $exclude_emails[] = $v;
    		      } // if
    		    } // foreach
    		  } elseif(is_string($additional['exclude']) && is_valid_email($additional['exclude'])) {
    		    $exclude_emails[] = $additional['exclude'];
    		  } // if
  		  } // if
  			
  			if(is_string($event)) {
  				$event = new NotifierEvent($event);
  			} // if
  			
  			$smarty =& SmartyForAngie::getInstance();
  			
  			$template = $smarty->createTemplate($event->getTemplatePath());
  			$template->assign(array(
  			  'sender' => $this->object, 
  			  'context' => $context,
          'style' => array(
            'link' => Theme::getProperty('notifications.link'),
          ),
  			));
  			
  			if($event_params) {
  			  $template->assign($event_params);
  			} // if

        $default_context_view_url = $context instanceof ApplicationObject && $context instanceof IRoutingContext ? $context->getViewUrl() : null;

  			foreach($to_notify as $user) {
          if ($user && !($user instanceof IUser)) {
            if (is_valid_email($user)) {
              $user = new AnonymousUser($user, $user);
            } else {
              continue;
            } // if
          } // if

  			  if(in_array($user->getEmail(), $exclude_emails)) {
  			    continue; // Ignore people from exclude list
  			  } // if
  			  
  			  if($context instanceof IVisibility && $user instanceof User && $user->getMinVisibility() > $context->getVisibility()) {
  			    continue; // Ignore people who can't see private objects
  			  } // if

          // Get context view URL for a given user
          $context_view_url = $default_context_view_url;
          EventsManager::trigger('on_notification_context_view_url', array(&$user, &$context, &$context_view_url));
  			  
  			  $template->assign(array(
  			    'recipient' => $user, 
  			    'language' => $user->getLanguage(),
            'context_view_url' => $context_view_url,
  			  ));
  			  
  			  $content = $template->fetch();
  			  
  			  if(strpos($content, '================================================================================')) {
  			  	list($subject, $body) = explode('================================================================================', $content);
  			  	
  			  	$subject = undo_htmlspecialchars(trim($subject)); // Subject does not have to be escaped
  			  	$body = trim($body);
  			  } else {
  			  	$subject = lang('[No Subject]', null, true, $user->getLanguage());
  			  	$body = trim($content);
  			  } // if
  			  
  			  ApplicationMailer::send($user, $subject, $body, array(
  			    'sender' => $this->object, 
  			    'context' => $context,
  			    'attachments' => array_var($additional, 'attachments', null)
  			  ), array_var($additional, 'method', $user->getMailingMethod()));
  			} // foreach
  		} // if
  	} // notifyUsers
  	
  	/**
  	 * Notify subscribers
  	 * 
  	 * @param INotifierContext $context
  	 * @param string $event
  	 * @param array $event_params
  	 * @param array $additional
  	 */
  	function notifySubscribers(INotifierContext $context, $event, $event_params = null, $additional = null) {
  		if($context instanceof ISubscriptions) {
  			$this->notifyUsers($context->subscriptions()->get(), $context, $event, $event_params, $additional);
  	  } else {
  	  	throw new InvalidInstanceError('context', $context, 'ISubscriptions');
  	  } // if
  	} // notifySubscribers
  	
  	/**
  	 * Notify assignees
  	 * 
  	 * @param INotifierContext $context
  	 * @param string $event
  	 * @param array $event_params
  	 * @param array $additional
  	 */
  	function notifyAssignees(INotifierContext $context, $event, $event_params = null, $additional = null) {
  		if($context instanceof IAssignees) {
  			$this->notifyUsers($context->assignees()->getAllAssignees(), $context, $event, $event_params, $additional);
  	  } else {
  	  	throw new InvalidInstanceError('context', $context, 'IAssignees');
  	  } // if
  	} // notifyAssignees
  	
  	/**
  	 * Notify administrators
  	 * 
  	 * @param INotifierContext $context
  	 * @param NotifierEvent $event
  	 * @param mixed $event_params
  	 * @param mixed $additional
  	 */
  	function notifyAdministrators(INotifierContext $context, $event, $event_params = null, $additional = null) {
  		$this->notifyUsers(Users::findAdministrators(), $context, $event, $event_params, $additional);
  	} // notifyAdministrators
  	
  }