<?php
/**
 * NetCommonsCakeTestCase
 *
 * @author Noriko Arai <arai@nii.ac.jp>
 * @author Shohei Nakajima <nakajimashouhei@gmail.com>
 * @link http://www.netcommons.org NetCommons Project
 * @license http://www.netcommons.org/license.txt NetCommons License
 * @copyright Copyright 2014, NetCommons Project
 */

CakeLog::drop('stdout');
CakeLog::drop('stderr');

App::uses('Current', 'NetCommons.Utility');
App::uses('CurrentFrame', 'NetCommons.Utility');
App::uses('CurrentPage', 'NetCommons.Utility');
App::uses('CurrentSystem', 'NetCommons.Utility');
App::uses('NetCommonsTestSuite', 'NetCommons.TestSuite');
App::uses('SiteSettingUtil', 'SiteManager.Utility');
App::uses('OriginalKeyBehavior', 'NetCommons.Model/Behavior');
App::uses('TestAuthGeneral', 'AuthGeneral.TestSuite');
App::uses('AuthComponent', 'Controller/Component');

/**
 * NetCommonsCakeTestCase class
 *
 * @package NetCommons\NetCommons\TestSuite
 * @SuppressWarnings(PHPMD.NumberOfChildren)
 * @codeCoverageIgnore
 */
abstract class NetCommonsCakeTestCase extends CakeTestCase {

/**
 * Plugin name
 *
 * @var string
 */
	public $plugin;

/**
 * Model name
 *
 * @var array
 */
	protected $_modelName;

/**
 * Method name
 *
 * @var array
 */
	protected $_methodName;

/**
 * Fixture merge
 *
 * @var array
 */
	protected $_isFixtureMerged = true;

/**
 * Fixtures
 *
 * @var array
 */
	protected $_defaultFixtures = array(
		'plugin.blocks.block',
		'plugin.blocks.block_role_permission',
		'plugin.blocks.block_setting',
		'plugin.blocks.blocks_language',
		'plugin.boxes.box',
		'plugin.boxes.boxes_page_container',
		'plugin.data_types.data_type',
		'plugin.data_types.data_type_choice',
		'plugin.files.upload_file',
		'plugin.files.upload_files_content',
		'plugin.frames.frame',
		'plugin.frames.frame_public_language',
		'plugin.frames.frames_language',
		'plugin.m17n.language',
		'plugin.mails.mail_queue',
		'plugin.mails.mail_queue_user',
		'plugin.mails.mail_setting',
		'plugin.pages.page',
		'plugin.pages.page_container',
		'plugin.plugin_manager.plugin',
		//'plugin.plugin_manager.plugins_role',
		//'plugin.roles.default_role_permission',
		'plugin.roles.role',
		'plugin.rooms.roles_room',
		'plugin.rooms.roles_rooms_user',
		'plugin.rooms.room',
		'plugin.rooms.rooms_language',
		//'plugin.rooms.room_role',
		//'plugin.rooms.room_role_permission',
		'plugin.rooms.space',
		'plugin.site_manager.site_setting',
		'plugin.topics.topic',
		'plugin.topics.topic_readable',
		'plugin.topics.topic_user_status',
		'plugin.user_attributes.user_attribute',
		'plugin.user_attributes.user_attribute_choice',
		'plugin.user_attributes.user_attribute_setting',
		'plugin.user_roles.user_attributes_role',
		'plugin.users.user',
		'plugin.users.users_language',
	);

/**
 * Fixtures load
 *
 * @param string $name The name parameter on PHPUnit_Framework_TestCase::__construct()
 * @param array  $data The data parameter on PHPUnit_Framework_TestCase::__construct()
 * @param string $dataName The dataName parameter on PHPUnit_Framework_TestCase::__construct()
 * @return void
 */
	public function __construct($name = null, array $data = array(), $dataName = '') {
		parent::__construct($name, $data, $dataName);
		if ($this->_isFixtureMerged && isset($this->fixtures)) {
			$this->fixtures = array_merge($this->_defaultFixtures, $this->fixtures);
		}
		if ($this->plugin) {
			NetCommonsTestSuite::$plugin = $this->plugin;
		}
		Configure::write('Config.language', 'ja');
	}

/**
 * setUp method
 *
 * @return void
 */
	public function setUp() {
		$this->_clear();

		parent::setUp();

		Configure::write('NetCommons.installed', true);
		Configure::write('Config.language', 'ja');

		if ($this->_modelName) {
			$model = $this->_modelName;
			$this->$model = ClassRegistry::init(Inflector::camelize($this->plugin) . '.' . $model);
		}
	}

/**
 * tearDown method
 *
 * @return void
 */
	protected function _clear() {
		if ($this->_modelName) {
			$model = $this->_modelName;
			unset($this->$model);
		}

		Configure::write('NetCommons.installed', false);
		Configure::write('Config.language', null);
		SiteSettingUtil::reset();

		foreach (['CurrentFrame', 'CurrentPage', 'CurrentSystem'] as $utility) {
			$reflectionClass = new ReflectionClass($utility);
			$property = $reflectionClass->getProperty('__memoryCache');
			$property->setAccessible(true);
			$property->setValue($utility, []);
		}

		Current::$current = array();
		Current::$permission = array();

		OriginalKeyBehavior::$isUnitRandomKey = false;

		//throwが実行されるとログイン情報が残っているため、初期化する
		$reflectionClass = new ReflectionClass('AuthComponent');
		$property = $reflectionClass->getProperty('_user');
		$property->setAccessible(true);
		$property->setValue([]);
	}

/**
 * tearDown method
 *
 * @return void
 */
	public function tearDown() {
		parent::tearDown();
	}

/**
 * privateおよびprotectedメソッドのテスト
 *
 * @param Instance $instance インスタンス
 * @param string $mockMethod Mockのメソッド
 * @param array $params Mockのメソッドのパラメータ
 * @return void
 */
	protected function _testReflectionMethod($instance, $mockMethod, $params = array()) {
		$method = new ReflectionMethod($instance, $mockMethod);
		$method->setAccessible(true);
		$result = $method->invokeArgs($instance, $params);
		return $result;
	}

/**
 * Load TestPlugin
 *
 * @param CakeTestCase $test CakeTestCase
 * @param string $plugin Plugin name
 * @param string $testPlugin Test plugin name
 * @return void
 */
	public static function loadTestPlugin(CakeTestCase $test, $plugin, $testPlugin) {
		$pluginPath = CakePlugin::path(Inflector::camelize($plugin));
		if (empty($pluginPath) || ! file_exists($pluginPath)) {
			$test->markTestAsSkipped(sprintf('Could not find %s in plugin paths', $pluginPath));
			return;
		}

		App::build(array(
			'Plugin' => array($pluginPath . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
		));
		App::uses('CakePlugin', 'Core');
		CakePlugin::load($testPlugin, ['routes' => true, 'ignoreMissing' => true]);
	}

/**
 * Assert Date time
 *
 * @param string $result Result data
 * @param string $message メッセージ
 * @return void
 */
	public function assertDatetime($result, $message = null) {
		$pattern = '/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/';
		$this->assertRegExp($pattern, $result, $message);
	}

}
