<?php

declare(strict_types=1);

namespace Medienreaktor\Courses\Tests\Unit\Domain\Model;

use PHPUnit\Framework\MockObject\MockObject;
use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;

/**
 * Test case
 *
 * @author Matthias Schieber <matthias.schieber@medienreaktor.de>
 */
class CourseTest extends UnitTestCase
{
    /**
     * @var \Medienreaktor\Courses\Domain\Model\Course|MockObject|AccessibleObjectInterface
     */
    protected $subject;

    protected function setUp(): void
    {
        parent::setUp();

        $this->subject = $this->getAccessibleMock(
            \Medienreaktor\Courses\Domain\Model\Course::class,
            ['dummy']
        );
    }

    protected function tearDown(): void
    {
        parent::tearDown();
    }

    /**
     * @test
     */
    public function getTitleReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getTitle()
        );
    }

    /**
     * @test
     */
    public function setTitleForStringSetsTitle(): void
    {
        $this->subject->setTitle('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('title'));
    }

    /**
     * @test
     */
    public function getCourseIdReturnsInitialValueForInt(): void
    {
        self::assertSame(
            0,
            $this->subject->getCourseId()
        );
    }

    /**
     * @test
     */
    public function setCourseIdForIntSetsCourseId(): void
    {
        $this->subject->setCourseId(12);

        self::assertEquals(12, $this->subject->_get('courseId'));
    }

    /**
     * @test
     */
    public function getShortTitleReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getShortTitle()
        );
    }

    /**
     * @test
     */
    public function setShortTitleForStringSetsShortTitle(): void
    {
        $this->subject->setShortTitle('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('shortTitle'));
    }

    /**
     * @test
     */
    public function getContentsReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getContents()
        );
    }

    /**
     * @test
     */
    public function setContentsForStringSetsContents(): void
    {
        $this->subject->setContents('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('contents'));
    }

    /**
     * @test
     */
    public function getRequirementsReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getRequirements()
        );
    }

    /**
     * @test
     */
    public function setRequirementsForStringSetsRequirements(): void
    {
        $this->subject->setRequirements('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('requirements'));
    }

    /**
     * @test
     */
    public function getLanguageReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getLanguage()
        );
    }

    /**
     * @test
     */
    public function setLanguageForStringSetsLanguage(): void
    {
        $this->subject->setLanguage('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('language'));
    }

    /**
     * @test
     */
    public function getImageUriReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getImageUri()
        );
    }

    /**
     * @test
     */
    public function setImageUriForStringSetsImageUri(): void
    {
        $this->subject->setImageUri('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('imageUri'));
    }

    /**
     * @test
     */
    public function getPriceReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getPrice()
        );
    }

    /**
     * @test
     */
    public function setPriceForStringSetsPrice(): void
    {
        $this->subject->setPrice('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('price'));
    }

    /**
     * @test
     */
    public function getCourseTypeReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getCourseType()
        );
    }

    /**
     * @test
     */
    public function setCourseTypeForStringSetsCourseType(): void
    {
        $this->subject->setCourseType('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('courseType'));
    }

    /**
     * @test
     */
    public function getGoalsReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getGoals()
        );
    }

    /**
     * @test
     */
    public function setGoalsForStringSetsGoals(): void
    {
        $this->subject->setGoals('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('goals'));
    }

    /**
     * @test
     */
    public function getPerspectivesReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getPerspectives()
        );
    }

    /**
     * @test
     */
    public function setPerspectivesForStringSetsPerspectives(): void
    {
        $this->subject->setPerspectives('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('perspectives'));
    }

    /**
     * @test
     */
    public function getDurationReturnsInitialValueForInt(): void
    {
        self::assertSame(
            0,
            $this->subject->getDuration()
        );
    }

    /**
     * @test
     */
    public function setDurationForIntSetsDuration(): void
    {
        $this->subject->setDuration(12);

        self::assertEquals(12, $this->subject->_get('duration'));
    }

    /**
     * @test
     */
    public function getAgencySupportedReturnsInitialValueForBool(): void
    {
        self::assertFalse($this->subject->getAgencySupported());
    }

    /**
     * @test
     */
    public function setAgencySupportedForBoolSetsAgencySupported(): void
    {
        $this->subject->setAgencySupported(true);

        self::assertEquals(true, $this->subject->_get('agencySupported'));
    }

    /**
     * @test
     */
    public function getIhkCertifiedReturnsInitialValueForBool(): void
    {
        self::assertFalse($this->subject->getIhkCertified());
    }

    /**
     * @test
     */
    public function setIhkCertifiedForBoolSetsIhkCertified(): void
    {
        $this->subject->setIhkCertified(true);

        self::assertEquals(true, $this->subject->_get('ihkCertified'));
    }

    /**
     * @test
     */
    public function getIndividualAppointmentsReturnsInitialValueForBool(): void
    {
        self::assertFalse($this->subject->getIndividualAppointments());
    }

    /**
     * @test
     */
    public function setIndividualAppointmentsForBoolSetsIndividualAppointments(): void
    {
        $this->subject->setIndividualAppointments(true);

        self::assertEquals(true, $this->subject->_get('individualAppointments'));
    }

    /**
     * @test
     */
    public function getTargetGroupReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getTargetGroup()
        );
    }

    /**
     * @test
     */
    public function setTargetGroupForStringSetsTargetGroup(): void
    {
        $this->subject->setTargetGroup('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('targetGroup'));
    }

    /**
     * @test
     */
    public function getHighlightReturnsInitialValueForBool(): void
    {
        self::assertFalse($this->subject->getHighlight());
    }

    /**
     * @test
     */
    public function setHighlightForBoolSetsHighlight(): void
    {
        $this->subject->setHighlight(true);

        self::assertEquals(true, $this->subject->_get('highlight'));
    }

    /**
     * @test
     */
    public function getSeoTitleReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getSeoTitle()
        );
    }

    /**
     * @test
     */
    public function setSeoTitleForStringSetsSeoTitle(): void
    {
        $this->subject->setSeoTitle('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('seoTitle'));
    }

    /**
     * @test
     */
    public function getSeoDescriptionReturnsInitialValueForString(): void
    {
        self::assertSame(
            '',
            $this->subject->getSeoDescription()
        );
    }

    /**
     * @test
     */
    public function setSeoDescriptionForStringSetsSeoDescription(): void
    {
        $this->subject->setSeoDescription('Conceived at T3CON10');

        self::assertEquals('Conceived at T3CON10', $this->subject->_get('seoDescription'));
    }

    /**
     * @test
     */
    public function getSeoImageReturnsInitialValueForFileReference(): void
    {
        self::assertEquals(
            null,
            $this->subject->getSeoImage()
        );
    }

    /**
     * @test
     */
    public function setSeoImageForFileReferenceSetsSeoImage(): void
    {
        $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference();
        $this->subject->setSeoImage($fileReferenceFixture);

        self::assertEquals($fileReferenceFixture, $this->subject->_get('seoImage'));
    }

    /**
     * @test
     */
    public function getSubjectReturnsInitialValueForSubject(): void
    {
        $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
        self::assertEquals(
            $newObjectStorage,
            $this->subject->getSubject()
        );
    }

    /**
     * @test
     */
    public function setSubjectForObjectStorageContainingSubjectSetsSubject(): void
    {
        $subject = new \Medienreaktor\Courses\Domain\Model\Subject();
        $objectStorageHoldingExactlyOneSubject = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
        $objectStorageHoldingExactlyOneSubject->attach($subject);
        $this->subject->setSubject($objectStorageHoldingExactlyOneSubject);

        self::assertEquals($objectStorageHoldingExactlyOneSubject, $this->subject->_get('subject'));
    }

    /**
     * @test
     */
    public function addSubjectToObjectStorageHoldingSubject(): void
    {
        $subject = new \Medienreaktor\Courses\Domain\Model\Subject();
        $subjectObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
            ->onlyMethods(['attach'])
            ->disableOriginalConstructor()
            ->getMock();

        $subjectObjectStorageMock->expects(self::once())->method('attach')->with(self::equalTo($subject));
        $this->subject->_set('subject', $subjectObjectStorageMock);

        $this->subject->addSubject($subject);
    }

    /**
     * @test
     */
    public function removeSubjectFromObjectStorageHoldingSubject(): void
    {
        $subject = new \Medienreaktor\Courses\Domain\Model\Subject();
        $subjectObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
            ->onlyMethods(['detach'])
            ->disableOriginalConstructor()
            ->getMock();

        $subjectObjectStorageMock->expects(self::once())->method('detach')->with(self::equalTo($subject));
        $this->subject->_set('subject', $subjectObjectStorageMock);

        $this->subject->removeSubject($subject);
    }

    /**
     * @test
     */
    public function getWorkshopReturnsInitialValueForWorkshop(): void
    {
        $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
        self::assertEquals(
            $newObjectStorage,
            $this->subject->getWorkshop()
        );
    }

    /**
     * @test
     */
    public function setWorkshopForObjectStorageContainingWorkshopSetsWorkshop(): void
    {
        $workshop = new \Medienreaktor\Courses\Domain\Model\Workshop();
        $objectStorageHoldingExactlyOneWorkshop = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
        $objectStorageHoldingExactlyOneWorkshop->attach($workshop);
        $this->subject->setWorkshop($objectStorageHoldingExactlyOneWorkshop);

        self::assertEquals($objectStorageHoldingExactlyOneWorkshop, $this->subject->_get('workshop'));
    }

    /**
     * @test
     */
    public function addWorkshopToObjectStorageHoldingWorkshop(): void
    {
        $workshop = new \Medienreaktor\Courses\Domain\Model\Workshop();
        $workshopObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
            ->onlyMethods(['attach'])
            ->disableOriginalConstructor()
            ->getMock();

        $workshopObjectStorageMock->expects(self::once())->method('attach')->with(self::equalTo($workshop));
        $this->subject->_set('workshop', $workshopObjectStorageMock);

        $this->subject->addWorkshop($workshop);
    }

    /**
     * @test
     */
    public function removeWorkshopFromObjectStorageHoldingWorkshop(): void
    {
        $workshop = new \Medienreaktor\Courses\Domain\Model\Workshop();
        $workshopObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
            ->onlyMethods(['detach'])
            ->disableOriginalConstructor()
            ->getMock();

        $workshopObjectStorageMock->expects(self::once())->method('detach')->with(self::equalTo($workshop));
        $this->subject->_set('workshop', $workshopObjectStorageMock);

        $this->subject->removeWorkshop($workshop);
    }

    /**
     * @test
     */
    public function getProfessionReturnsInitialValueForProfession(): void
    {
        $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
        self::assertEquals(
            $newObjectStorage,
            $this->subject->getProfession()
        );
    }

    /**
     * @test
     */
    public function setProfessionForObjectStorageContainingProfessionSetsProfession(): void
    {
        $profession = new \Medienreaktor\Courses\Domain\Model\Profession();
        $objectStorageHoldingExactlyOneProfession = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
        $objectStorageHoldingExactlyOneProfession->attach($profession);
        $this->subject->setProfession($objectStorageHoldingExactlyOneProfession);

        self::assertEquals($objectStorageHoldingExactlyOneProfession, $this->subject->_get('profession'));
    }

    /**
     * @test
     */
    public function addProfessionToObjectStorageHoldingProfession(): void
    {
        $profession = new \Medienreaktor\Courses\Domain\Model\Profession();
        $professionObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
            ->onlyMethods(['attach'])
            ->disableOriginalConstructor()
            ->getMock();

        $professionObjectStorageMock->expects(self::once())->method('attach')->with(self::equalTo($profession));
        $this->subject->_set('profession', $professionObjectStorageMock);

        $this->subject->addProfession($profession);
    }

    /**
     * @test
     */
    public function removeProfessionFromObjectStorageHoldingProfession(): void
    {
        $profession = new \Medienreaktor\Courses\Domain\Model\Profession();
        $professionObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
            ->onlyMethods(['detach'])
            ->disableOriginalConstructor()
            ->getMock();

        $professionObjectStorageMock->expects(self::once())->method('detach')->with(self::equalTo($profession));
        $this->subject->_set('profession', $professionObjectStorageMock);

        $this->subject->removeProfession($profession);
    }
}
