<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

namespace Crypt\GPG\Tests;

use Crypt\GPG\Exceptions;
use Crypt\GPG\UserId;

/**
 * User id class tests for Crypt_GPG.
 *
 * @category  Encryption
 * @package   Crypt_GPG
 * @author    Michael Gauthier <mike@silverorange.com>
 * @copyright 2008-2010 silverorange
 * @license   https://www.gnu.org/copyleft/lesser.html LGPL License 2.1
 * @link      https://github.com/pear/Crypt_GPG
 */
class UserIdTest extends TestCase
{
    /**
     * @group construct
     */
    public function testConstructFromString()
    {
        $expectedUserId = new UserId([
            'name'    => 'Example User',
            'comment' => 'This is a test comment',
            'email'   => 'test@example.com',
        ]);

        $string = 'Example User (This is a test comment) <test@example.com>';
        $userId = new UserId($string);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group construct
     */
    public function testConstructFromUserId()
    {
        $expectedUserId = new UserId([
            'name'    => 'Example User',
            'comment' => 'This is a test comment',
            'email'   => 'test@example.com',
            'revoked' => true,
            'valid'   => false,
        ]);

        $userId = new UserId($expectedUserId);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group construct
     */
    public function testConstructFromArray()
    {
        $userId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'This is a test comment',
                'email'   => 'test@example.com',
                'revoked' => true,
                'valid'   => false,
            ]
        );

        $this->assertEquals('Example User', $userId->getName());
        $this->assertEquals('This is a test comment', $userId->getComment());
        $this->assertEquals('test@example.com', $userId->getEmail());

        $this->assertTrue($userId->isRevoked());
        $this->assertFalse($userId->isValid());
    }

    /**
     * @group parse
     */
    public function testParseFull()
    {
        $expectedUserId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'This is a test comment',
                'email'   => 'test@example.com',
            ]
        );

        $string = 'Example User (This is a test comment) <test@example.com>';
        $userId = UserId::parse($string);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group parse
     */
    public function testParseNameOnly()
    {
        $expectedUserId = new UserId(['name' => 'Example User']);

        $string = 'Example User';
        $userId = UserId::parse($string);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group parse
     */
    public function testParseNameComment()
    {
        $expectedUserId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'This is a test comment',
            ]
        );

        $string = 'Example User (This is a test comment)';
        $userId = UserId::parse($string);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group parse
     */
    public function testParseNameEmail()
    {
        $expectedUserId = new UserId(
            [
                'name'  => 'Example User',
                'email' => 'test@example.com',
            ]
        );

        $string = 'Example User <test@example.com>';
        $userId = UserId::parse($string);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group parse
     */
    public function testParseEmailOnly()
    {
        $expectedUserId = new UserId(
            [
                'name'  => '',
                'email' => 'test@example.com',
            ]
        );

        $string = '<test@example.com>';
        $userId = UserId::parse($string);

        $this->assertEquals($expectedUserId, $userId);

        $string = 'test@example.com';
        $userId = UserId::parse($string);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group to-string
     */
    public function testToStringFull()
    {
        $expected = 'Example User (This is a test comment) <test@example.com>';

        $userId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'This is a test comment',
                'email'   => 'test@example.com',
            ]
        );

        $this->assertEquals($expected, strval($userId));
    }

    /**
     * @group to-string
     */
    public function testToStringNameOnly()
    {
        $expected = 'Example User';

        $userId = new UserId(['name' => 'Example User']);

        $this->assertEquals($expected, strval($userId));
    }

    /**
     * @group to-string
     */
    public function testToStringNameComment()
    {
        $expected = 'Example User (This is a test comment)';

        $userId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'This is a test comment',
            ]
        );

        $this->assertEquals($expected, strval($userId));
    }

    /**
     * @group to-string
     */
    public function testToStringNameEmail()
    {
        $expected = 'Example User <test@example.com>';

        $userId = new UserId(
            [
                'name'  => 'Example User',
                'email' => 'test@example.com',
            ]
        );

        $this->assertEquals($expected, strval($userId));
    }

    /**
     * @group accessors
     */
    public function testGetName()
    {
        $userId = new UserId(
            [
                'name' => 'Example User',
            ]
        );

        $this->assertEquals('Example User', $userId->getName());
    }

    /**
     * @group accessors
     */
    public function testGetComment()
    {
        $userId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'This is a test comment',
            ]
        );

        $this->assertEquals('This is a test comment', $userId->getComment());
    }

    /**
     * @group accessors
     */
    public function testGetEmail()
    {
        $userId = new UserId(
            [
                'name'  => 'Example User',
                'email' => 'test@example.com',
            ]
        );

        $this->assertEquals('test@example.com', $userId->getEmail());
    }

    /**
     * @group accessors
     */
    public function testIsRevoked()
    {
        $userId = new UserId(
            [
                'name'    => 'Example User',
                'revoked' => true,
            ]
        );

        $this->assertTrue($userId->isRevoked());

        $userId = new UserId(
            [
                'name'    => 'Example User',
                'revoked' => false,
            ]
        );

        $this->assertFalse($userId->isRevoked());
    }

    /**
     * @group accessors
     */
    public function testIsValid()
    {
        $userId = new UserId(
            [
                'name'  => 'Example User',
                'valid' => true,
            ]
        );

        $this->assertTrue($userId->isValid());

        $userId = new UserId(
            [
                'name'  => 'Example User',
                'valid' => false,
            ]
        );

        $this->assertFalse($userId->isValid());
    }

    /**
     * @group mutators
     */
    public function testSetName()
    {
        $expectedUserId = new UserId(['name' => 'Second Name']);
        $userId         = new UserId(['name' => 'First Name']);

        $userId->setName('Second Name');

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group mutators
     */
    public function testSetComment()
    {
        $expectedUserId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'Second comment text',
            ]
        );

        $userId = new UserId(
            [
                'name'    => 'Example User',
                'comment' => 'First comment text',
            ]
        );

        $userId->setComment('Second comment text');

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group mutators
     */
    public function testSetEmail()
    {
        $expectedUserId = new UserId(
            [
                'name'  => 'Example User',
                'email' => 'second@example.com',
            ]
        );

        $userId = new UserId(
            [
                'name'  => 'Example User',
                'email' => 'first@example.com',
            ]
        );

        $userId->setEmail('second@example.com');

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group mutators
     */
    public function testSetRevoked()
    {
        $expectedUserId = new UserId(
            [
                'name'    => 'Example User',
                'revoked' => true,
            ]
        );

        $userId = new UserId(
            [
                'name'    => 'Example User',
                'revoked' => false,
            ]
        );

        $userId->setRevoked(true);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group mutators
     */
    public function testSetValid()
    {
        $expectedUserId = new UserId(
            [
                'name'  => 'Example User',
                'valid' => true,
            ]
        );

        $userId = new UserId(
            [
                'name'  => 'Example User',
                'valid' => false,
            ]
        );

        $userId->setValid(true);

        $this->assertEquals($expectedUserId, $userId);
    }

    /**
     * @group fluent
     */
    public function testFluentInterface()
    {
        $userId         = new UserId();
        $returnedUserId = $userId->setName('Alice');

        $this->assertEquals(
            $userId,
            $returnedUserId,
            'Failed asserting fluent interface works for setName() method.'
        );

        $userId         = new UserId();
        $returnedUserId = $userId->setComment('encryption is fun');

        $this->assertEquals(
            $userId,
            $returnedUserId,
            'Failed asserting fluent interface works for setComment() method.'
        );

        $userId         = new UserId();
        $returnedUserId = $userId->setEmail('test@example.com');

        $this->assertEquals(
            $userId,
            $returnedUserId,
            'Failed asserting fluent interface works for setEmail() method.'
        );

        $userId         = new UserId();
        $returnedUserId = $userId->setRevoked(true);

        $this->assertEquals(
            $userId,
            $returnedUserId,
            'Failed asserting fluent interface works for setRevoked() method.'
        );

        $userId         = new UserId();
        $returnedUserId = $userId->setValid(true);

        $this->assertEquals(
            $userId,
            $returnedUserId,
            'Failed asserting fluent interface works for setValid() method.'
        );
    }
}
