<?php

namespace PHPOnCouch;

use InvalidArgumentException,
	PHPOnCouch\Exceptions,
	PHPUnit_Framework_TestCase,
	stdClass;

require_once join(DIRECTORY_SEPARATOR, [__DIR__, '_config', 'config.php']);

/**
 * Generated by PHPUnit_SkeletonGenerator on 2016-11-01 at 01:49:47.
 * @backupGlobals disabled
 * @backupStaticAttributes disabled
 */
class CouchReplicatorTest extends PHPUnit_Framework_TestCase
{

	private $host = 'localhost';
	private $port = '5984';
	private $dbname = 'couchclienttest';

	/**
	 *
	 * @var ReflectedProperty
	 */
	private $opts;

	/**
	 *
	 * @var CouchReplicator
	 */
	private $replicator;

	/**
	 *
	 * @var \ReflectionClass
	 */
	private $reflectedClass;

	/**
	 *
	 * @var PHPOnCouch\CouchClient
	 */
	private $client;

	/**
	 *
	 * @var PHPOnCouch\CouchClient
	 */
	private $aclient;
	
	
	/**
	 *
	 * @var PHPOnCouch\CouchClient
	 */
	private $targetClient;
	/**
	 * Sets up the fixture, for example, opens a network connection.
	 * This method is called before a test is executed.
	 */
	protected function setUp()
	{
		$this->reflectedClass = new \ReflectionClass(CouchReplicator::class);
		$config = \config::getInstance();
		$this->port = $config->getPort();
		$this->host = $config->getHost();
		$this->aUrl = $config->getUrl($this->host, $this->port, $config->getFirstAdmin());
		$this->couch_server = 'http://' . $this->host . ':' . $this->port . '/';
		$this->opts = $this->reflectedClass->getProperty('opts');
		$this->opts->setAccessible(true);

		$this->aclient = new CouchClient($this->aUrl, $this->dbname);
		$this->targetClient = new CouchClient($this->aUrl,'replicationarget');
		$this->setupClient($this->aclient);
		$this->setupClient($this->targetClient);
		
		
		$this->replicator = new CouchReplicator($this->aclient);
	}
	
	protected function setupClient(CouchClient $client){
		try {
			$client->deleteDatabase();
		} catch (\Exception $e) {
			
		}
		$client->createDatabase();
	}
	
	protected function dropDB(CouchClient $client){
		try {
			$client->deleteDatabase();
		} catch (Exceptions\CouchNotFoundException $e) {
			
		}
	}

	/**
	 * Tears down the fixture, for example, closes a network connection.
	 * This method is called after a test is executed.
	 */
	protected function tearDown()
	{
		$this->dropDB($this->targetClient);
		$this->targetClient = null;
		
		$this->dropDB($this->aclient);
		$this->aclient = null;
	}

	/**
	 * @covers PHPOnCouch\CouchReplicator::__construct
	 */
	public function testCouchReplicatorConstructor()
	{
		$prop = $this->reflectedClass->getProperty('client');
		$prop->setAccessible(true);

		$replicator = new CouchReplicator($this->aclient);
		$this->assertEquals($prop->getValue($replicator), $this->aclient);
	}

	private function simulateReplication(CouchReplicator $repl)
	{
		try {
			$repl->to("asdlkasldkasd");
		} catch (\Exception $ex) {
			
		}
	}

	public function testCreateTarget()
	{
		//Should return itself
		$this->assertEquals($this->replicator, $this->replicator->create_target());
		//Should be set to true
		$this->assertTrue($this->opts->getValue($this->replicator)['create_target']);

		$this->simulateReplication($this->replicator);

		//Should reset values
		$this->assertEmpty($this->opts->getValue($this->replicator));
	}

	public function testContinuous()
	{
		//Should return itself
		$this->assertEquals($this->replicator, $this->replicator->continuous());
		//Should be set to true
		$this->assertTrue($this->opts->getValue($this->replicator)['continuous']);

		$this->simulateReplication($this->replicator);

		//Should reset values
		$this->assertEmpty($this->opts->getValue($this->replicator));
	}

	public function testCancel()
	{
		//Should return itself
		$this->assertEquals($this->replicator, $this->replicator->cancel());
		//Should be set to true
		$this->assertTrue($this->opts->getValue($this->replicator)['cancel']);

		$this->simulateReplication($this->replicator);

		//Should reset values
		$this->assertEmpty($this->opts->getValue($this->replicator));
	}

	public function testDocIds()
	{
		$ids = ['val1', 'val2'];
		//Should return itself
		$this->assertEquals($this->replicator, $this->replicator->doc_ids($ids));
		//Should be set to true
		$this->assertEquals($this->opts->getValue($this->replicator)['doc_ids'], $ids);

		$this->simulateReplication($this->replicator);

		//Should reset values
		$this->assertEmpty($this->opts->getValue($this->replicator));
	}

	public function testFilter()
	{
		$name = 'just_a_name';
		//Should return itself
		$this->assertEquals($this->replicator, $this->replicator->filter($name));
		//Should be set to true
		$this->assertEquals($this->opts->getValue($this->replicator)['filter'], $name);

		$this->simulateReplication($this->replicator);

		//Should reset values
		$this->assertEmpty($this->opts->getValue($this->replicator));
	}

	public function testQueryParams()
	{
		$params = ['name' => 'val'];
		//Should return itself
		$this->assertEquals($this->replicator, $this->replicator->query_params($params));
		//Should be set to true
		$this->assertEquals($this->opts->getValue($this->replicator)['query_params'], $params);

		$this->simulateReplication($this->replicator);

		//Should reset values
		$this->assertEmpty($this->opts->getValue($this->replicator));
	}
	
	public function testTo()
	{
		$docToSync = (object)['_id'=>'replicate_me'];
		$this->aclient->storeDoc($docToSync);
		
		
		//Should have no docs
		$this->assertEquals(0,$this->targetClient->getAllDocs()->total_rows);
		$this->assertEquals(1,$this->aclient->getAllDocs()->total_rows);
		
		$this->replicator->doc_ids([$docToSync->_id])->to($this->targetClient->getDatabaseUri());
		
		//Should have doc
		$this->assertEquals(1,$this->targetClient->getAllDocs()->total_rows);
	}
	
	public function testFrom()
	{
		$docToSync = (object)['_id'=>'replicate_me'];
		$this->targetClient->storeDoc($docToSync);
		
		
		//Should have no docs
		$this->assertEquals(1,$this->targetClient->getAllDocs()->total_rows);
		$this->assertEquals(0,$this->aclient->getAllDocs()->total_rows);
		
		$this->replicator->doc_ids([$docToSync->_id])->from($this->targetClient->getDatabaseUri());
		
		//Should have doc
		$this->assertEquals(1,$this->targetClient->getAllDocs()->total_rows);
	}

}
