<?php

require_once 'Swift/Tests/SwiftUnitTestCase.php';
require_once 'Swift/Mime/Headers/MailboxHeader.php';
require_once 'Swift/Mime/HeaderEncoder.php';
require_once 'Swift/Mime/Grammar.php';

class Swift_Mime_Headers_MailboxHeaderTest
  extends Swift_Tests_SwiftUnitTestCase
{
  
  /* -- RFC 2822, 3.6.2 for all tests.
   */
  
  private $_charset = 'utf-8';
  
  public function testTypeIsMailboxHeader()
  {
    $header = $this->_getHeader('To', $this->_getEncoder('Q', true));
    $this->assertEqual(Swift_Mime_Header::TYPE_MAILBOX, $header->getFieldType());
  }
  
  public function testMailboxIsSetForAddress()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setAddresses('chris@swiftmailer.org');
    $this->assertEqual(array('chris@swiftmailer.org'),
      $header->getNameAddressStrings()
      );
  }
  
  public function testMailboxIsRenderedForNameAddress()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris Corbyn'));
    $this->assertEqual(
      array('Chris Corbyn <chris@swiftmailer.org>'), $header->getNameAddressStrings()
      );
  }
  
  public function testAddressCanBeReturnedForAddress()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setAddresses('chris@swiftmailer.org');
    $this->assertEqual(array('chris@swiftmailer.org'), $header->getAddresses());
  }
  
  public function testAddressCanBeReturnedForNameAddress()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array('chris@swiftmailer.org' => 'Chris Corbyn'));
    $this->assertEqual(array('chris@swiftmailer.org'), $header->getAddresses());
  }
  
  public function testQuotesInNameAreQuoted()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn, "DHE"'
      ));
    $this->assertEqual(
      array('"Chris Corbyn, \"DHE\"" <chris@swiftmailer.org>'),
      $header->getNameAddressStrings()
      );
  }
  
  public function testEscapeCharsInNameAreQuoted()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn, \\escaped\\'
      ));
    $this->assertEqual(
      array('"Chris Corbyn, \\\\escaped\\\\" <chris@swiftmailer.org>'),
      $header->getNameAddressStrings()
      );
  }
  
  public function testGetMailboxesReturnsNameValuePairs()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn, DHE'
      ));
    $this->assertEqual(
      array('chris@swiftmailer.org' => 'Chris Corbyn, DHE'), $header->getNameAddresses()
      );
  }
  
  public function testMultipleAddressesCanBeSetAndFetched()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setAddresses(array(
      'chris@swiftmailer.org', 'mark@swiftmailer.org'
      ));
    $this->assertEqual(
      array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
      $header->getAddresses()
      );
  }
  
  public function testMultipleAddressesAsMailboxes()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setAddresses(array(
      'chris@swiftmailer.org', 'mark@swiftmailer.org'
      ));
    $this->assertEqual(
      array('chris@swiftmailer.org'=>null, 'mark@swiftmailer.org'=>null),
      $header->getNameAddresses()
      );
  }
  
  public function testMultipleAddressesAsMailboxStrings()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setAddresses(array(
      'chris@swiftmailer.org', 'mark@swiftmailer.org'
      ));
    $this->assertEqual(
      array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
      $header->getNameAddressStrings()
      );
  }
  
  public function testMultipleNamedMailboxesReturnsMultipleAddresses()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $this->assertEqual(
      array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
      $header->getAddresses()
      );
  }
  
  public function testMultipleNamedMailboxesReturnsMultipleMailboxes()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $this->assertEqual(array(
        'chris@swiftmailer.org' => 'Chris Corbyn',
        'mark@swiftmailer.org' => 'Mark Corbyn'
        ),
      $header->getNameAddresses()
      );
  }
  
  public function testMultipleMailboxesProducesMultipleMailboxStrings()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $this->assertEqual(array(
        'Chris Corbyn <chris@swiftmailer.org>',
        'Mark Corbyn <mark@swiftmailer.org>'
        ),
      $header->getNameAddressStrings()
      );
  }
  
  public function testSetAddressesOverwritesAnyMailboxes()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $this->assertEqual(
      array('chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'),
      $header->getNameAddresses()
      );
    $this->assertEqual(
      array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
      $header->getAddresses()
      );
    
    $header->setAddresses(array('chris@swiftmailer.org', 'mark@swiftmailer.org'));
    
    $this->assertEqual(
      array('chris@swiftmailer.org' => null, 'mark@swiftmailer.org' => null),
      $header->getNameAddresses()
      );
    $this->assertEqual(
      array('chris@swiftmailer.org', 'mark@swiftmailer.org'),
      $header->getAddresses()
      );
  }
  
  public function testNameIsEncodedIfNonAscii()
  {
    $name = 'C' . pack('C', 0x8F) . 'rbyn';
    
    $encoder = $this->_getEncoder('Q');
    $this->_checking(Expectations::create()
      -> one($encoder)->encodeString($name, any(), any()) -> returns('C=8Frbyn')
      -> ignoring($encoder)
      );
    
    $header = $this->_getHeader('From', $encoder);
    $header->setNameAddresses(array('chris@swiftmailer.org'=>'Chris ' . $name));
    
    $addresses = $header->getNameAddressStrings();
    $this->assertEqual(
      'Chris =?' . $this->_charset . '?Q?C=8Frbyn?= <chris@swiftmailer.org>',
      array_shift($addresses)
      );
  }
  
  public function testEncodingLineLengthCalculations()
  {
    /* -- RFC 2047, 2.
    An 'encoded-word' may not be more than 75 characters long, including
    'charset', 'encoding', 'encoded-text', and delimiters.
    */
    
    $name = 'C' . pack('C', 0x8F) . 'rbyn';
    
    $encoder = $this->_getEncoder('Q');
    $this->_checking(Expectations::create()
      -> one($encoder)->encodeString($name, 6, 63) -> returns('C=8Frbyn')
      -> ignoring($encoder)
      );
    
    $header = $this->_getHeader('From', $encoder);
    $header->setNameAddresses(array('chris@swiftmailer.org'=>'Chris ' . $name));
    
    $header->getNameAddressStrings();
  }
  
  public function testGetValueReturnsMailboxStringValue()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn'
      ));
    $this->assertEqual(
      'Chris Corbyn <chris@swiftmailer.org>', $header->getFieldBody()
      );
  }
  
  public function testGetValueReturnsMailboxStringValueForMultipleMailboxes()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $this->assertEqual(
      'Chris Corbyn <chris@swiftmailer.org>, Mark Corbyn <mark@swiftmailer.org>',
      $header->getFieldBody()
      );
  }
  
  public function testRemoveAddressesWithSingleValue()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $header->removeAddresses('chris@swiftmailer.org');
    $this->assertEqual(array('mark@swiftmailer.org'),
      $header->getAddresses()
      );
  }
  
  public function testRemoveAddressesWithList()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $header->removeAddresses(
      array('chris@swiftmailer.org', 'mark@swiftmailer.org')
      );
    $this->assertEqual(array(), $header->getAddresses());
  }
  
  public function testSetBodyModel()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setFieldBodyModel('chris@swiftmailer.org');
    $this->assertEqual(array('chris@swiftmailer.org'=>null), $header->getNameAddresses());
  }
  
  public function testGetBodyModel()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setAddresses(array('chris@swiftmailer.org'));
    $this->assertEqual(array('chris@swiftmailer.org'=>null), $header->getFieldBodyModel());
  }
  
  public function testToString()
  {
    $header = $this->_getHeader('From', $this->_getEncoder('Q', true));
    $header->setNameAddresses(array(
      'chris@swiftmailer.org' => 'Chris Corbyn',
      'mark@swiftmailer.org' => 'Mark Corbyn'
      ));
    $this->assertEqual(
      'From: Chris Corbyn <chris@swiftmailer.org>, ' .
      'Mark Corbyn <mark@swiftmailer.org>' . "\r\n",
      $header->toString()
      );
  }
  
  // -- Private methods
  
  private function _getHeader($name, $encoder)
  {
    $header = new Swift_Mime_Headers_MailboxHeader($name, $encoder, new Swift_Mime_Grammar());
    $header->setCharset($this->_charset);
    return $header;
  }
  
  private function _getEncoder($type, $stub = false)
  {
    $encoder = $this->_mock('Swift_Mime_HeaderEncoder');
    $this->_checking(Expectations::create()
      -> ignoring($encoder)->getName() -> returns($type)
      );
    if ($stub)
    {
      $this->_checking(Expectations::create()
        -> ignoring($encoder)
        );
    }
    return $encoder;
  }
  
}