<?php

require_once 'Swift/Mime/MimeEntity.php';
require_once 'Swift/Mime/MimePart.php';
require_once 'Swift/Mime/AbstractMimeEntityTest.php';
require_once 'Swift/Mime/Grammar.php';

class Swift_Mime_MimePartTest extends Swift_Mime_AbstractMimeEntityTest
{
    public function testNestingLevelIsSubpart()
    {
        $part = $this->_createMimePart($this->_createHeaderSet(),
            $this->_createEncoder(), $this->_createCache()
            );
        $this->assertEqual(
            Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE, $part->getNestingLevel()
            );
    }

    public function testCharsetIsReturnedFromHeader()
    {
        /* -- RFC 2046, 4.1.2.
        A critical parameter that may be specified in the Content-Type field
        for "text/plain" data is the character set.  This is specified with a
        "charset" parameter, as in:

     Content-type: text/plain; charset=iso-8859-1

        Unlike some other parameter values, the values of the charset
        parameter are NOT case sensitive.  The default character set, which
        must be assumed in the absence of a charset parameter, is US-ASCII.
        */

        $cType = $this->_createHeader('Content-Type', 'text/plain',
            array('charset' => 'iso-8859-1')
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $this->assertEqual('iso-8859-1', $part->getCharset());
    }

    public function testCharsetIsSetInHeader()
    {
        $cType = $this->_createHeader('Content-Type', 'text/plain',
            array('charset' => 'iso-8859-1'), false
            );
        $this->_checking(Expectations::create()
            -> one($cType)->setParameter('charset', 'utf-8')
            -> ignoring($cType)
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $part->setCharset('utf-8');
    }

    public function testCharsetIsSetInHeaderIfPassedToSetBody()
    {
        $cType = $this->_createHeader('Content-Type', 'text/plain',
            array('charset' => 'iso-8859-1'), false
            );
        $this->_checking(Expectations::create()
            -> one($cType)->setParameter('charset', 'utf-8')
            -> ignoring($cType)
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $part->setBody('', 'text/plian', 'utf-8');
    }

    public function testSettingCharsetNotifiesEncoder()
    {
        $encoder = $this->_createEncoder('quoted-printable', false);
        $this->_checking(Expectations::create()
            -> one($encoder)->charsetChanged('utf-8')
            -> ignoring($encoder)
            );
        $part = $this->_createMimePart($this->_createHeaderSet(),
            $encoder, $this->_createCache()
            );
        $part->setCharset('utf-8');
    }

    public function testSettingCharsetNotifiesHeaders()
    {
        $headers = $this->_createHeaderSet(array(), false);
        $this->_checking(Expectations::create()
            -> one($headers)->charsetChanged('utf-8')
            -> ignoring($headers)
            );
        $part = $this->_createMimePart($headers, $this->_createEncoder(),
            $this->_createCache()
            );
        $part->setCharset('utf-8');
    }

    public function testSettingCharsetNotifiesChildren()
    {
        $child = $this->_createChild(0, '', false);

        $this->_checking(Expectations::create()
            -> one($child)->charsetChanged('windows-874')
            -> ignoring($child)
            );

        $part = $this->_createMimePart($this->_createHeaderSet(),
            $this->_createEncoder(), $this->_createCache()
            );
        $part->setChildren(array($child));
        $part->setCharset('windows-874');
    }

    public function testCharsetChangeUpdatesCharset()
    {
        $cType = $this->_createHeader('Content-Type', 'text/plain',
            array('charset' => 'iso-8859-1'), false
            );
        $this->_checking(Expectations::create()
            -> one($cType)->setParameter('charset', 'utf-8')
            -> ignoring($cType)
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $part->charsetChanged('utf-8');
    }

    public function testSettingCharsetClearsCache()
    {
        $headers = $this->_createHeaderSet(array(), false);
        $this->_checking(Expectations::create()
            -> ignoring($headers)->toString() -> returns(
                "Content-Type: text/plain; charset=utf-8\r\n"
                )
            -> ignoring($headers)
            );

        $cache = $this->_createCache(false);
        $this->_checking(Expectations::create()
            -> one($cache)->clearKey(any(), 'body')
            -> ignoring($cache)
            );

        $entity = $this->_createEntity($headers, $this->_createEncoder(),
            $cache
            );

        $entity->setBody("blah\r\nblah!");
        $entity->toString();

        $entity->setCharset('iso-2022');
    }

    public function testFormatIsReturnedFromHeader()
    {
        /* -- RFC 3676.
     */

        $cType = $this->_createHeader('Content-Type', 'text/plain',
            array('format' => 'flowed')
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $this->assertEqual('flowed', $part->getFormat());
    }

    public function testFormatIsSetInHeader()
    {
        $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false);
        $this->_checking(Expectations::create()
            -> one($cType)->setParameter('format', 'fixed')
            -> ignoring($cType)
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $part->setFormat('fixed');
    }

    public function testDelSpIsReturnedFromHeader()
    {
        /* -- RFC 3676.
     */

        $cType = $this->_createHeader('Content-Type', 'text/plain',
            array('delsp' => 'no')
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $this->assertIdentical(false, $part->getDelSp());
    }

    public function testDelSpIsSetInHeader()
    {
        $cType = $this->_createHeader('Content-Type', 'text/plain', array(), false);
        $this->_checking(Expectations::create()
            -> one($cType)->setParameter('delsp', 'yes')
            -> ignoring($cType)
            );
        $part = $this->_createMimePart($this->_createHeaderSet(array(
            'Content-Type' => $cType)),
            $this->_createEncoder(), $this->_createCache()
            );
        $part->setDelSp(true);
    }

    public function testFluidInterface()
    {
        $part = $this->_createMimePart($this->_createHeaderSet(),
            $this->_createEncoder(), $this->_createCache()
            );

        $this->assertSame($part,
            $part
            ->setContentType('text/plain')
            ->setEncoder($this->_createEncoder())
            ->setId('foo@bar')
            ->setDescription('my description')
            ->setMaxLineLength(998)
            ->setBody('xx')
            ->setBoundary('xyz')
            ->setChildren(array())
            ->setCharset('utf-8')
            ->setFormat('flowed')
            ->setDelSp(true)
            );
    }

    // -- Private helpers

    //abstract
    protected function _createEntity($headers, $encoder, $cache)
    {
        return $this->_createMimePart($headers, $encoder, $cache);
    }

    protected function _createMimePart($headers, $encoder, $cache)
    {
        return new Swift_Mime_MimePart($headers, $encoder, $cache, new Swift_Mime_Grammar());
    }
}
