<?php

require_once 'Swift/Tests/SwiftUnitTestCase.php';

class Swift_Plugins_DecoratorPluginTest extends Swift_Tests_SwiftUnitTestCase
{
  public function testMessageBodyReceivesReplacements()
  {
    $message = $this->_createMessage(
      $this->_createHeaders(),
      array('zip@button.tld' => 'Zipathon'),
      array('chris.corbyn@swiftmailer.org' => 'Chris'),
      'Subject',
      'Hello {name}, you are customer #{id}'
      );
    $this->_checking(Expectations::create()
      -> one($message)->setBody('Hello Zip, you are customer #456')
      -> ignoring($message)
      );
    
    $plugin = $this->_createPlugin(
      array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'))
      );
    
    $evt = $this->_createSendEvent($message);
    
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
  }
  
  public function testReplacementsCanBeAppliedToSameMessageMultipleTimes()
  {
    $message = $this->_createMessage(
      $this->_createHeaders(),
      array('zip@button.tld' => 'Zipathon', 'foo@bar.tld' => 'Foo'),
      array('chris.corbyn@swiftmailer.org' => 'Chris'),
      'Subject',
      'Hello {name}, you are customer #{id}'
      );
    $this->_checking(Expectations::create()
      -> one($message)->setBody('Hello Zip, you are customer #456')
      -> one($message)->setBody('Hello {name}, you are customer #{id}')
      -> one($message)->setBody('Hello Foo, you are customer #123')
      -> ignoring($message)
      );
    
    $plugin = $this->_createPlugin(
      array(
        'foo@bar.tld' => array('{name}' => 'Foo', '{id}' => '123'),
        'zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456')
        )
      );
    
    $evt = $this->_createSendEvent($message);
    
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
  }
  
  public function testReplacementsCanBeMadeInHeaders()
  {
    $headers = $this->_createHeaders(array(
      $returnPathHeader = $this->_createHeader('Return-Path', 'foo-{id}@swiftmailer.org'),
      $toHeader = $this->_createHeader('Subject', 'A message for {name}!')
    ));

    $message = $this->_createMessage(
      $headers,
      array('zip@button.tld' => 'Zipathon'),
      array('chris.corbyn@swiftmailer.org' => 'Chris'),
      'A message for {name}!',
      'Hello {name}, you are customer #{id}'
      );
    $this->_checking(Expectations::create()
      -> one($message)->setBody('Hello Zip, you are customer #456')
      -> one($toHeader)->setFieldBodyModel('A message for Zip!')
      -> one($returnPathHeader)->setFieldBodyModel('foo-456@swiftmailer.org')
      -> ignoring($message)
      -> ignoring($toHeader)
      -> ignoring($returnPathHeader)
      );
    
    $plugin = $this->_createPlugin(
      array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'))
      );
    
    $evt = $this->_createSendEvent($message);
    
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
  }
  
  public function testReplacementsAreMadeOnSubparts()
  {
    $part1 = $this->_createPart('text/plain', 'Your name is {name}?', '1@x');
    $part2 = $this->_createPart('text/html', 'Your <em>name</em> is {name}?', '2@x');
    $message = $this->_createMessage(
      $this->_createHeaders(),
      array('zip@button.tld' => 'Zipathon'),
      array('chris.corbyn@swiftmailer.org' => 'Chris'),
      'A message for {name}!',
      'Subject'
      );
    $this->_checking(Expectations::create()
      -> ignoring($message)->getChildren() -> returns(array($part1, $part2))
      -> one($part1)->setBody('Your name is Zip?')
      -> one($part2)->setBody('Your <em>name</em> is Zip?')
      -> ignoring($part1)
      -> ignoring($part2)
      -> ignoring($message)
      );
    
    $plugin = $this->_createPlugin(
      array('zip@button.tld' => array('{name}' => 'Zip', '{id}' => '456'))
      );
    
    $evt = $this->_createSendEvent($message);
    
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
  }
  
  public function testReplacementsCanBeTakenFromCustomReplacementsObject()
  {
    $message = $this->_createMessage(
      $this->_createHeaders(),
      array('foo@bar' => 'Foobar', 'zip@zap' => 'Zip zap'),
      array('chris.corbyn@swiftmailer.org' => 'Chris'),
      'Subject',
      'Something {a}'
      );
      
    $replacements = $this->_createReplacements();
    
    $this->_checking(Expectations::create()
      -> one($message)->setBody('Something b')
      -> one($message)->setBody('Something c')
      -> one($replacements)->getReplacementsFor('foo@bar') -> returns(array('{a}'=>'b'))
      -> one($replacements)->getReplacementsFor('zip@zap') -> returns(array('{a}'=>'c'))
      -> ignoring($message)
      );
    
    $plugin = $this->_createPlugin($replacements);
    
    $evt = $this->_createSendEvent($message);
    
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
    $plugin->beforeSendPerformed($evt);
    $plugin->sendPerformed($evt);
  }
  
  // -- Creation methods
  
  private function _createMessage($headers, $to = array(), $from = null, $subject = null,
    $body = null)
  {
    $message = $this->_mock('Swift_Mime_Message');
    foreach ($to as $addr => $name)
    {
      $this->_checking(Expectations::create()
        -> one($message)->getTo() -> returns(array($addr => $name))
        );
    }
    $this->_checking(Expectations::create()
      -> allowing($message)->getHeaders() -> returns($headers)
      -> ignoring($message)->getFrom() -> returns($from)
      -> ignoring($message)->getSubject() -> returns($subject)
      -> ignoring($message)->getBody() -> returns($body)
      );
    return $message;
  }
  
  private function _createPlugin($replacements)
  {
    return new Swift_Plugins_DecoratorPlugin($replacements);
  }
  
  private function _createReplacements()
  {
    return $this->_mock('Swift_Plugins_Decorator_Replacements');
  }
  
  private function _createSendEvent(Swift_Mime_Message $message)
  {
    $evt = $this->_mock('Swift_Events_SendEvent');
    $this->_checking(Expectations::create()
      -> ignoring($evt)->getMessage() -> returns($message)
      -> ignoring($evt)
      );
    return $evt;
  }
  
  private function _createPart($type, $body, $id)
  {
    $part = $this->_mock('Swift_Mime_MimeEntity');
    $this->_checking(Expectations::create()
      -> ignoring($part)->getContentType() -> returns($type)
      -> ignoring($part)->getBody() -> returns($body)
      -> ignoring($part)->getId() -> returns($id)
      );
    return $part;
  }
  
  private function _createHeaders($headers = array())
  {
    $set = $this->_mock('Swift_Mime_HeaderSet');
    
    $this->_checking(Expectations::create()
      -> allowing($set)->getAll() -> returns($headers)
      -> ignoring($set)
      );
    
    foreach ($headers as $header)
    {
      $set->set($header);
    }
    
    return $set;
  }
  
  private function _createHeader($name, $body = '')
  {
    $header = $this->_mock('Swift_Mime_Header');
    $this->_checking(Expectations::create()
      -> ignoring($header)->getFieldName() -> returns($name)
      -> ignoring($header)->getFieldBodyModel() -> returns($body)
      );
    return $header;
  }
  
}
