<?php

require_once(__DIR__ . '/../utilmethods.php');
require_once(__DIR__ . '/../testconsts.php');
require_once(__DIR__ . '/../../../vendor/autoload.php');

use Integrations\PhpSdk\TurnitinAPI;
use Integrations\PhpSdk\TiiClass;

/**
 * Generated by PHPUnit_SkeletonGenerator 1.2.0 on 2012-10-15 at 16:24:56.
 */
class ClassTest extends PHPUnit_Framework_TestCase
{

    protected static $sdk;
    private static $classtitle = "ClassTest Class";
    private static $classtitle_two = "ClassTest Two Class";
    private static $classtitle_update = "ClassTest Update Class";

    public static function setUpBeforeClass()
    {
        // fwrite(STDOUT, "\n" . __METHOD__ . "\n");
        self::$sdk = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, TII_SECRET, TII_APIPRODUCT, 'en');
        self::$sdk->setDebug(false);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /API Login failed/
     */
    public function testCreateSoapFault()
    {
        $api = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, 'bad', 0);
        $class = new TiiClass();
        $api->createClass($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /API Login failed/
     */
    public function testUpdateSoapFault()
    {
        $api = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, 'bad', 0);
        $class = new TiiClass();
        $api->updateClass($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /API Login failed/
     */
    public function testReadSoapFault()
    {
        $api = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, 'bad', 0);
        $class = new TiiClass();
        $api->readClass($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /API Login failed/
     */
    public function testReadsSoapFault()
    {
        $api = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, 'bad', 0);
        $class = new TiiClass();
        $api->readClasses($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /API Login failed/
     */
    public function testDeleteSoapFault()
    {
        $api = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, 'bad', 0);
        $class = new TiiClass();
        $api->deleteClass($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /API Login failed/
     */
    public function testFindSoapFault()
    {
        $api = new TurnitinAPI(TII_ACCOUNT, TII_APIBASEURL, 'bad', 0);
        $class = new TiiClass();
        $api->findClasses($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /Returned 0 of 2 classes/
     */
    public function testReadClassesError()
    {
        $class = new TiiClass();
        $class->setClassIds(array(0,0));
        self::$sdk->readClasses($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessageRegExp /You must include a Class Title/
     */
    public function testFindClassesError()
    {
        $class = new TiiClass();
        self::$sdk->findClasses($class);
    }

    /**
     * @group smoke
     * @return array
     */
    public function testCreateClass()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class = new TiiClass();
        $class->setTitle(self::$classtitle);
        $class->setEndDate($classEndDate);

        // create the class
        $response = self::$sdk->createClass($class);
        $resultClass = $response->getClass();

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Turnitin class added.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        return array('ClassToRead'=>$resultClass,'ExpectedClass'=>$class);
    }

    /**
     * @group smoke
     * @depends testCreateClass
     */
    public function testReadClass(array $classes)
    {
        $expectedClass = $classes['ExpectedClass'];
        $classToRead = $classes['ClassToRead'];

        $response = self::$sdk->readClass($classToRead);
        $resultClass = $response->getClass();

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Class CourseSection successfully found.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        // check resulting class
        $this->assertEquals($classToRead->getClassId(), $resultClass->getClassId());
        $this->assertEquals($expectedClass->getTitle(), $resultClass->getTitle());
        $this->assertNull($resultClass->getDateFrom());
        $this->assertEquals($expectedClass->getEndDate(), $resultClass->getEndDate());

        return $classToRead;
    }

    /**
     * @group smoke
     */
    public function testReadClasses()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class1 = new TiiClass();
        $class1->setTitle(self::$classtitle);
        $class1->setEndDate($classEndDate);
        $resultClass1 = self::$sdk->createClass($class1)->getClass();

        $class2 = new TiiClass();
        $class2->setTitle(self::$classtitle_two);
        $class2->setEndDate($classEndDate);
        $resultClass2 = self::$sdk->createClass($class2)->getClass();

        $classesToRead = new TiiClass();
        $classesToRead->setClassIds(array($resultClass1->getClassId(), $resultClass2->getClassId()));

        $response = self::$sdk->readClasses($classesToRead);
        $resultClasses = $response->getClasses();

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Returned 2 of 2 classes.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        // check result classes
        $class1Found = false;
        $class2Found = false;

        for ($i = 0; $i < count($resultClasses); $i++) {
            if ($resultClasses[$i]->getClassId() == $resultClass1->getClassId()) {
                $this->assertFalse($class1Found);
                $class1Found = true;
                $this->assertEquals($class1->getTitle(), $resultClasses[$i]->getTitle());
                $this->assertEquals($class1->getDateFrom(), $resultClasses[$i]->getDateFrom());
                $this->assertEquals($class1->getEndDate(), $resultClasses[$i]->getEndDate());
            } elseif ($resultClasses[$i]->getClassId() == $resultClass2->getClassId()) {
                $this->assertFalse($class2Found);
                $class2Found = true;
                $this->assertEquals($class2->getTitle(), $resultClasses[$i]->getTitle());
                $this->assertEquals($class2->getDateFrom(), $resultClasses[$i]->getDateFrom());
                $this->assertEquals($class2->getEndDate(), $resultClasses[$i]->getEndDate());
            } else {
                $this->fail("Unexpected class found!");
            }
        }

        $this->assertTrue($class1Found && $class2Found);
    }

    /**
     * @group smoke
     */
    public function testUpdateClass()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class = new TiiClass();
        $class->setTitle(self::$classtitle);
        $class->setEndDate($classEndDate);

        // create the class
        $classToUpdate = self::$sdk->createClass($class)->getClass();

        // update the class
        $updatedStartDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('-10 days'));
        $updatedEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+2 years'));

        $classToUpdate->setTitle(self::$classtitle_update);
        $classToUpdate->setDateFrom($updatedStartDate);
        $classToUpdate->setEndDate($updatedEndDate);

        $response = self::$sdk->updateClass($classToUpdate);

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Turnitin class updated.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        // check resulting class by reading it
        $classToRead = new TiiClass();
        $classToRead->setClassId($classToUpdate->getClassId());

        $resultClass = self::$sdk->readClass($classToRead)->getClass();

        $this->assertEquals($classToUpdate->getClassId(), $resultClass->getClassId());
        $this->assertEquals($classToUpdate->getTitle(), $resultClass->getTitle());
        $this->assertNull($resultClass->getDateFrom());
        $this->assertEquals($classToUpdate->getEndDate(), $resultClass->getEndDate());
    }

    public function testupdateClassTitleOnly()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class = new TiiClass();
        $class->setTitle(self::$classtitle);
        $class->setEndDate($classEndDate);

        // create the class
        $classToUpdate = self::$sdk->createClass($class)->getClass();

        // update the class title olny
        $classToUpdate->setTitle(self::$classtitle_update);

        $response = self::$sdk->updateClass($classToUpdate);

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Turnitin class updated.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        // check resulting class by reading it
        $classToRead = new TiiClass();
        $classToRead->setClassId($classToUpdate->getClassId());

        $resultClass = self::$sdk->readClass($classToRead)->getClass();

        $this->assertEquals($classToUpdate->getClassId(), $resultClass->getClassId());
        $this->assertEquals($classToUpdate->getTitle(), $resultClass->getTitle());
        $this->assertNull($resultClass->getDateFrom());
        $this->assertEquals($classEndDate, $resultClass->getEndDate());
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage title - This field is required
     */
    public function testUpdateClassEndDateOnly()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class = new TiiClass();
        $class->setTitle(self::$classtitle);
        $class->setEndDate($classEndDate);

        // create the class
        $classToUpdate = self::$sdk->createClass($class)->getClass();

        // update the class end date only
        $updatedEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+2 years'));

        $classToUpdate->setEndDate($updatedEndDate);

        self::$sdk->updateClass($classToUpdate);
    }

    /**
     * @group smoke
     */
    public function testFindClasses()
    {
        $searchString = uniqid();
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class1 = new TiiClass();
        $class1->setTitle(self::$classtitle.$searchString);
        $class1->setEndDate($classEndDate);
        $resultClass1Id = self::$sdk->createClass($class1)->getClass()->getClassId();

        $class2 = new TiiClass();
        $class2->setTitle(self::$classtitle_two.$searchString);
        $class2->setEndDate($classEndDate);
        $resultClass2Id = self::$sdk->createClass($class2)->getClass()->getClassId();

        $classesToFind = new TiiClass();
        $classesToFind->setTitle($searchString);

        $response = self::$sdk->findClasses($classesToFind);
        $resultClasses = $response->getClass()->getClassIds();

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        // check result classes
        $class1Found = false;
        $class2Found = false;

        for ($i = 0; $i < count($resultClasses); $i++) {
            if ($resultClasses[$i] == $resultClass1Id) {
                $this->assertFalse($class1Found);
                $class1Found = true;
            } elseif ($resultClasses[$i] == $resultClass2Id) {
                $this->assertFalse($class2Found);
                $class2Found = true;
            } else {
                $this->fail("Unexpected class found!");
            }
        }
        $this->assertTrue($class1Found && $class2Found);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage title - This field is required
     */
    public function testCreateClassWithoutTitle()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class = new TiiClass();
        $class->setEndDate($classEndDate);

        // create the class
        self::$sdk->createClass($class);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testReadClassWithNegativeClassId()
    {
        $classToRead = new TiiClass();
        $classToRead->setClassId(-1);

        self::$sdk->readClass($classToRead);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testReadClassWithNullClassId()
    {
        $classToRead = new TiiClass();
        $classToRead->setClassId(null);

        self::$sdk->readClass($classToRead);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testReadClassWithStringClassId()
    {
        $classToRead = new TiiClass();
        $classToRead->setClassId("SomeString");

        self::$sdk->readClass($classToRead);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testReadClassWithSymbolClassId()
    {
        $classToRead = new TiiClass();
        $classToRead->setClassId("!\"£$%^&*()");

        self::$sdk->readClass($classToRead);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testDeleteClassWithNegativeClassId()
    {
        $classToDelete = new TiiClass();
        $classToDelete->setClassId(-1);

        self::$sdk->deleteClass($classToDelete);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testDeleteClassWithNullClassId()
    {
        $classToDelete = new TiiClass();
        $classToDelete->setClassId(null);

        self::$sdk->deleteClass($classToDelete);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testDeleteClassWithStringClassId()
    {
        $classToDelete = new TiiClass();
        $classToDelete->setClassId("SomeString");

        self::$sdk->deleteClass($classToDelete);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testDeleteClassWithSymbolClassId()
    {
        $classToDelete = new TiiClass();
        $classToDelete->setClassId("!\"£$%^&*()");

        self::$sdk->deleteClass($classToDelete);
    }

    public function testReadClassesPartialSuccess()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('+1 years'));

        $class1 = new TiiClass();
        $class1->setTitle(self::$classtitle);
        $class1->setEndDate($classEndDate);
        $resultClass1 = self::$sdk->createClass($class1)->getClass();

        $class2 = new TiiClass();
        $class2->setTitle(self::$classtitle_two);
        $class2->setEndDate($classEndDate);
        $resultClass2 = self::$sdk->createClass($class2)->getClass();

        $classesToRead = new TiiClass();
        $classesToRead->setClassIds(array($resultClass1->getClassId(), $resultClass2->getClassId(), -1));

        $response = self::$sdk->readClasses($classesToRead);
        $resultClasses = $response->getClasses();

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Returned 2 of 3 classes.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("warning", $response->getStatus());
        $this->assertEquals("partialdatastorage", $response->getStatusCode());

        // check result classes
        $class1Found = false;
        $class2Found = false;

        for ($i = 0; $i < count($resultClasses); $i++) {
            if ($resultClasses[$i]->getClassId() == $resultClass1->getClassId()) {
                $this->assertFalse($class1Found);
                $class1Found = true;
                $this->assertEquals($class1->getTitle(), $resultClasses[$i]->getTitle());
                $this->assertNull($resultClasses[$i]->getDateFrom());
                $this->assertEquals($class1->getEndDate(), $resultClasses[$i]->getEndDate());
            } elseif ($resultClasses[$i]->getClassId() == $resultClass2->getClassId()) {
                $this->assertFalse($class2Found);
                $class2Found = true;
                $this->assertEquals($class2->getTitle(), $resultClasses[$i]->getTitle());
                $this->assertNull($resultClasses[$i]->getDateFrom());
                $this->assertEquals($class2->getEndDate(), $resultClasses[$i]->getEndDate());
            } else {
                $this->fail("Unexpected class found!");
            }
        }
        $this->assertTrue($class1Found && $class2Found);
    }

    public function testReadClassesWithSingleClassId()
    {
        $class = new TiiClass();
        $class->setTitle(self::$classtitle_two);
        $resultClass = self::$sdk->createClass($class)->getClass();

        $classesToRead = new TiiClass();
        $classesToRead->setClassIds(array($resultClass->getClassId()));

        $response = self::$sdk->readClasses($classesToRead);
        $resultClasses = $response->getClasses();
        $this->assertEquals(1, count($resultClasses));
    }

    public function testFindClassesWithDateLimit()
    {
        $searchString = uniqid();
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('-5 seconds'));
        // create a class
        $tiiClass = new TiiClass();
        $tiiClass->setTitle($searchString." Test Class");
        $tiiClass->setEndDate($classEndDate);

        $classToFind = new TiiClass();
        $classToFind->setDateFrom(gmdate("Y-m-d\TH:i:s\Z"));
        $classToFind->setTitle($searchString);

        $response = self::$sdk->findClasses($classToFind);

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("No Classes were found for this account and API product.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("warning", $response->getStatus());
        $this->assertEquals("nosourcedids", $response->getStatusCode());

        $this->assertEquals(0, count($response->getClass()->getClassIds()));
    }

    /**
     * @depends testReadClass
     */
    public function testDeleteClass($classToDelete)
    {
        $response = self::$sdk->deleteClass($classToDelete);

        // check response
        $this->assertNotNull($response->getMessageId());
        $this->assertEquals("Class CourseSection successfully deleted.", $response->getDescription());
        $this->assertNotNull($response->getMessageRefId());
        $this->assertEquals("status", $response->getStatus());
        $this->assertEquals("fullsuccess", $response->getStatusCode());

        return $classToDelete;
    }

    /**
     * @depends testDeleteClass
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage Class CourseSection not found.
     */
    public function testReadDeletedClass($classToRead)
    {
        self::$sdk->readClass($classToRead);
    }

    /**
     * @expectedException Integrations\PhpSdk\TurnitinSDKException
     * @expectedExceptionMessage date_end - must be after the start date
     */
    public function testCreateClassEndDateInPast()
    {
        $classEndDate = gmdate("Y-m-d\TH:i:s\Z", strtotime('-1 years'));

        $class = new TiiClass();
        $class->setTitle(self::$classtitle);
        $class->setEndDate($classEndDate);

        // create the class
        self::$sdk->createClass($class);
    }
}
