<?php

namespace airmoi\FileMaker;

/**
 * Generated by PHPUnit_SkeletonGenerator on 2016-09-09 at 19:41:41.
 * @SuppressWarnings(PHPMD.Superglobals)
 * @SuppressWarnings(PHPMD.ShortVariable)
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 *
 */
class FileMakerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var FileMaker
     */
    protected $fm;

    public static function setUpBeforeClass()
    {
        parent::setUpBeforeClass();
        $fm = new FileMaker($GLOBALS['DB_FILE'], $GLOBALS['DB_HOST'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']);
        $fm->newPerformScriptCommand('sample', 'create sample data', 50)->execute();
    }
    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        if ($GLOBALS['OFFICIAL_API'] == 1) {
            $this->fm = new \FileMaker($GLOBALS['DB_FILE'], $GLOBALS['DB_HOST'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']);
        } else {
            $this->fm = new FileMaker($GLOBALS['DB_FILE'], $GLOBALS['DB_HOST'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD'], ['errorHandling' => 'exception']);
        }
        //$this->fm->newPerformScriptCommand('sample', 'cleanup db')->execute();
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::listDatabases
     */
    public function testListDatabases()
    {
        $databases = $this->fm->listDatabases();
        $this->assertTrue(is_array($databases));

        $this->assertTrue(in_array($GLOBALS['DB_FILE'], $databases, 'Database ' . $GLOBALS['DB_FILE'] . ' is missing. Test can\'t run'));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::listLayouts
     */
    public function testListLayouts()
    {
        $layouts = $this->fm->listLayouts();
        $this->assertTrue(in_array('sample', $layouts));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getLayout
     */
    public function testGetLayout()
    {
        $layout = $this->fm->getLayout('sample');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Layout::class, $layout);
        }
        
        $this->assertEquals('sample', $layout->getName(), 'Layout name missmatch (' . $layout->getName() . ')');
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::isError
     */
    public function testIsError()
    {
        if (!$GLOBALS['OFFICIAL_API']) {
            $error = new FileMakerException($this->fm, 'Test FileMaker exception');
            $record = new Object\Record(new Object\Layout($this->fm));
        } else {
            $error = new \FileMaker_Error($this->fm->_impl, 'Test FileMaker exception');
            $record = new \FileMaker_Record(new \FileMaker_Layout($this->fm));
        }

        $this->assertTrue($this->fm->isError($error));
        $this->assertFalse($this->fm->isError($record));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getMinServerVersion
     */
    public function testGetMinServerVersion()
    {
        // Remove the following lines when you implement this test.
        $this->assertStringMatchesFormat('%d.%d.%d.%d', $this->fm->getMinServerVersion());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::setProperty
     */
    public function testSetProperty()
    {
        $this->fm->setProperty('logLevel', FileMaker::LOG_INFO);

        //Test valid property
        $this->assertEquals(FileMaker::LOG_INFO, $this->fm->getProperty('logLevel'));

        //Test invalid property (should return an error)
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->setExpectedException(FileMakerException::class);
            $this->fm->setProperty('fakeProperty', FileMaker::LOG_INFO);
        }
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getProperty
     */
    public function testGetProperty()
    {
        $this->assertEquals('en', $this->fm->getProperty('locale'));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getProperties
     */
    public function testGetProperties()
    {
        $this->assertArrayHasKey('locale', $this->fm->getProperties());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::setLogger
     * @todo   Implement testSetLogger().
     */
    public function testSetLogger()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
            'This test has not been implemented yet.'
        );
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newAddCommand
     */
    public function testNewAddCommand()
    {
        $command = $this->fm->newAddCommand('sample', ['text_field' => 'Test 1']);
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\Add::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_Add::class, $command);
        }
        
        $command->setField('date_field', date('m/d/Y'));

        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $record = $result->getFirstRecord();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Record::class, $record);
        } else {
            $this->assertInstanceOf(\FileMaker_Record::class, $record);
        }
        
        $this->assertEquals('Test 1', $record->getField('text_field'));
        
        return ['recid' => $record->getRecordId(), 'tableCount' => $result->getTableRecordCount()];
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newEditCommand
     * @depends testNewAddCommand
     */
    public function testNewEditCommand($datas)
    {
        $command = $this->fm->newEditCommand('sample', $datas['recid'], ['text_field' => 'Test 2']);
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\Edit::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_Edit::class, $command);
        }
        
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $record = $result->getFirstRecord();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Record::class, $record);
        } else {
            $this->assertInstanceOf(\FileMaker_Record::class, $record);
        }
        
        $this->assertEquals('Test 2', $record->getField('text_field'));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newDuplicateCommand
     * @depends testNewAddCommand
     */
    public function testNewDuplicateCommand($datas)
    {
        $command = $this->fm->newDuplicateCommand('sample', $datas['recid']);
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\Duplicate::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_Duplicate::class, $command);
        }
        
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $record = $result->getFirstRecord();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Record::class, $record);
        } else {
            $this->assertInstanceOf(\FileMaker_Record::class, $record);
        }
        
        $this->assertEquals('Test 2', $record->getField('text_field'));
        $this->assertNotEquals($datas['recid'], $record->getRecordId());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newEditCommand
     * @depends testNewAddCommand
     */
    public function testRelatedRecordCommand($datas)
    {

        $record = $this->fm->getRecordById('sample', $datas['recid']);
        $count = sizeof($record->getRelatedSet('related_sample'));
        $related = $record->newRelatedRecord('related_sample');

        $related->setField('text_field', "This is a new related record");

        $related->commit();

        $relatedSet = $record->getRelatedSet('related_sample');
        $this->assertEquals($count+1, sizeof($relatedSet));

        $relatedRecord = array_pop($relatedSet);

        $relatedRecord->setField('text_field', "This is an updated related record");
        $relatedRecord->commit();

        $relatedSet = $record->getRelatedSet('related_sample');
        $updatedRecord = array_pop($relatedSet);
        $this->assertEquals("This is an updated related record", $updatedRecord->getField('text_field'));

        $deleted = $updatedRecord->delete();
        $record = $deleted->getFirstRecord();
        $relatedSet = $record->getRelatedSet('related_sample');
        $this->assertEquals($count, sizeof($relatedSet));
    }
    /**
     * @covers \airmoi\FileMaker\FileMaker::newDeleteCommand
     * @depends testNewAddCommand
     */
    public function testNewDeleteCommand($datas)
    {
        $command = $this->fm->newDeleteCommand('sample', $datas['recid']);
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\Delete::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_Delete::class, $command);
        }
        
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $this->assertEquals($datas['tableCount'], (int)$result->getTableRecordCount());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::listScripts
     */
    public function testListScripts()
    {
        $scripts = $this->fm->listScripts();
        $this->assertTrue(in_array('cleanup db', $scripts));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newPerformScriptCommand
     * @depends testNewAddCommand
     */
    public function testNewPerformScriptCommand()
    {
        $command = $this->fm->newPerformScriptCommand('sample', 'cleanup db');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\PerformScript::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_PerformScript::class, $command);
        }
        
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $this->assertEquals(0, (int)$result->getFoundSetCount());
        
        
        $command = $this->fm->newPerformScriptCommand('sample', 'create sample data', 50);
        if (!$GLOBALS['OFFICIAL_API']) {
            $command->setRange(5, 25);
            $result = $command->execute();
            $this->assertInstanceOf(Object\Result::class, $result);
            $this->assertEquals(50, (int)$result->getFoundSetCount());
            $this->assertEquals(25, (int)$result->getFetchCount());

            $this->assertRegExp(
                '#(http:\/\/|https:\/\/)?[^:\/]*(:\d{2})?\/fmi\/xml\/fmresultset\.xml\?-db=[^\&]*\&-lay=[^\&]*\&-script=[^\&]*\&-script.param=[^\&]*\&-findany#',
                $this->fm->lastRequestedUrl
            );
        } else {
            $result = $command->execute();
        }
    }

    /**
     * @covers FileMaker::newFindAnyCommand
     */
    public function testNewFindAnyCommand()
    {
        $command =$this->fm->newFindAnyCommand('sample');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\FindAny::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_FindAny::class, $command);
        }
        
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $this->assertEquals(1, $result->getFoundSetCount());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newFindCommand
     */
    public function testNewFindCommand()
    {
        $command = $this->fm->newFindCommand('sample');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\Find::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_Find::class, $command);
        }
        
        $command->addFindCriterion('id', FileMaker::FIND_GT . '25');
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $this->assertEquals(25, $result->getFoundSetCount());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::newCompoundFindCommand
     *
     * @SuppressWarnings(PHPMD.Superglobals)
     */
    public function testNewCompoundFindCommand()
    {
        $command = $this->fm->newCompoundFindCommand('sample');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\CompoundFind::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_CompoundFind::class, $command);
        }
        
        $request1 = $this->fm->newFindRequest('sample');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\FindRequest::class, $request1);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_FindRequest::class, $request1);
        }
        
        $request1->addFindCriterion('id', "1...10");
        $command->add(1, $request1);

        $request2 = $this->fm->newFindRequest('sample');
        //$this->assertInstanceOf(\airmoi\FileMaker\Command\FindRequest::class, $request2);
        
        $request2->addFindCriterion('id', "40...50");
        $command->add(2, $request2);

        $request3 = $this->fm->newFindRequest('sample');
        //$this->assertInstanceOf(\airmoi\FileMaker\Command\FindRequest::class, $request3);
        
        $request3->addFindCriterion('id', "45");
        $request3->setOmit(true);
        $command->add(3, $request3);

        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $this->assertEquals(20, $result->getFoundSetCount());

        /*  */
    }

    /**
     * Test pull request #9 : omit on first request is missing
     * @covers \airmoi\FileMaker\FileMaker::newCompoundFindCommand
     */
    public function testNewCompoundFindCommandFirstOmitMissing()
    {
        $command = $this->fm->newCompoundFindCommand('sample');
        $request1 = $this->fm->newFindRequest('sample');

        $request1->addFindCriterion('id', "1");
        $request1->setOmit(true);

        $command->add(1, $request1);

        $result = $command->execute();

        $this->assertEquals(49, $result->getFoundSetCount());
    }
    
    /**
     * @covers \airmoi\FileMaker\FileMaker::newFindAllCommand
     * @SuppressWarnings(PHPMD.Superglobals)
     */
    public function testNewFindAllCommand()
    {
        $command =$this->fm->newFindAllCommand('sample');
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Command\FindAll::class, $command);
        } else {
            $this->assertInstanceOf(\FileMaker_Command_FindAll::class, $command);
        }
        
        $result = $command->execute();
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Result::class, $result);
        } else {
            $this->assertInstanceOf(\FileMaker_Result::class, $result);
        }
        
        $this->assertEquals(50, $result->getFoundSetCount());
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::createRecord
     * @SuppressWarnings(PHPMD.Superglobals)
     */
    public function testCreateRecord()
    {
        $record = $this->fm->createRecord('sample', [ 'text_field' => __METHOD__]);
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Record::class, $record);
        } else {
            $this->assertInstanceOf(\FileMaker_Record::class, $record);
        }
        
        $result = $record->commit();

        $this->assertTrue($result);
        return $record->getRecordId();
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getRecordById
     * @depends testCreateRecord
     */
    public function testGetRecordById($recId)
    {
        $record = $this->fm->getRecordById('sample', $recId);
        if (!$GLOBALS['OFFICIAL_API']) {
            $this->assertInstanceOf(Object\Record::class, $record);
        } else {
            $this->assertInstanceOf(\FileMaker_Record::class, $record);
        }
        
        
        $this->assertStringEndsWith('testCreateRecord', $record->getField('text_field'));
        $this->fm->newDeleteCommand('sample', $record->getRecordId())->execute();
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getContainerData
     */
    public function testGetContainerData()
    {
        $record = $this->fm->newFindAnyCommand('sample')->execute()->getFirstRecord();

        $datas = $this->fm->getContainerData($record->getField('container_field'));
        $this->assertEquals(18556, strlen($datas));
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::getContainerDataURL
     */
    public function testGetContainerDataURL()
    {
        $record = $this->fm->newFindAnyCommand('sample')->execute()->getFirstRecord();

        $url = $this->fm->getContainerDataURL($record->getField('container_field'));
        $this->assertStringEndsWith('/fmi/xml/cnt/fms.png?-db=filemaker-test&-lay=sample&-recid='.$record->getRecordId().'&-field=container_field(1)', $url);
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::__set
     */
    public function testMagicSet()
    {
        
        if ($GLOBALS['OFFICIAL_API']) {
            return true;
        }
        $this->fm->logLevel = 5;
        $this->assertEquals(5, $this->fm->getProperty('logLevel'));
        try {
            $this->fm->fakeVar = "Hello World";
        } catch (FileMakerException $e) {
            $this->assertTrue(FileMaker::isError($e));
        }
    }

    /**
     * @covers \airmoi\FileMaker\FileMaker::toOutputCharset
     * @todo   Implement testToOutputCharset().
     */
    public function testToOutputCharset()
    {
        // Remove the following lines when you implement this test.
        $this->markTestIncomplete(
            'This test has not been implemented yet.'
        );
    }
}
