<?php
/**
 * M17nModelTestCase TestCase
 *
 * @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
 */

//@codeCoverageIgnoreStart;
App::uses('M17nModelTestCase', 'M17n.TestSuite');
App::uses('Current', 'NetCommons.Utility');
//@codeCoverageIgnoreEnd;

/**
 * M17nModelTestCase TestCase
 *
 * @author Shohei Nakajima <nakajimashouhei@gmail.com>
 * @package NetCommons\M17n\TestSuite
 * @codeCoverageIgnore
 */
abstract class M17nBehaviorSaveTestBase extends M17nModelTestCase {

/**
 * Fixtures
 *
 * @var array
 */
	private $__fixtures = array();

/**
 * Plugin name
 *
 * @var string
 */
	public $plugin = 'm17n';

/**
 * 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 = '') {
		if (! isset($this->fixtures)) {
			$this->fixtures = array();
		}
		$this->fixtures = array_merge($this->__fixtures, $this->fixtures);
		parent::__construct($name, $data, $dataName);
	}

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

		//テストプラグインのロード
		Current::$current = Hash::insert(Current::$current, 'Block.id', '1');

		$roomId = '2';
		Current::$current = Hash::insert(Current::$current, 'Room.id', $roomId);
		$path = $roomId . '.Permission.content_publishable.value';
		Current::$permission = Hash::insert(Current::$permission, $path, true);
	}

/**
 * tearDown method
 *
 * @return void
 */
	public function tearDown() {
		Current::$current = array();
		Current::$permission = array();
		parent::tearDown();
	}

/**
 * save()のテスト
 *
 * @param int $langId 言語ID
 * @param array $data 登録データ
 * @param array $expected 期待値
 * @param array $prepare 関連するデータ作成
 * @dataProvider dataProvider
 * @return void
 */
	public function testSave($langId, $data, $expected, $prepare) {
		//テストデータセット
		foreach ($prepare as $modelName => $preDatas) {
			$model = ClassRegistry::init($modelName);
			foreach ($preDatas as $preData) {
				$model->create(false);
				$model->save($preData, ['validate' => false, 'callbacks' => false]);
			}
		}
		Current::write('Language.id', $langId);

		//テスト実施
		$this->_executeTestSave($data);

		//結果データ取得
		$actual = $this->_getActual($data);
		$actual = $this->_parseActual($actual, $expected);

		//チェック
		$this->assertEquals($actual, $expected);
	}

/**
 * テストの実行
 *
 * @param array $data テストデータ
 * @return void
 */
	protected function _executeTestSave($data) {
		$result = $this->TestModel->save($data);
		$this->assertNotEmpty($result);
	}

/**
 * $actualの取得
 *
 * @param array $data テストデータ
 * @return array
 */
	protected function _getActual($data) {
		$alias = $this->TestModel->alias;
		$actual = $this->TestModel->find('all', array(
			'recursive' => 1,
			'conditions' => array(
				$alias . '.' . $this->fieldKey => $data[$alias][$this->fieldKey]
			)
		));

		return $actual;
	}

/**
 * $actualをパースする
 *
 * @param array $actual 結果
 * @param array $expected 期待値
 * @return array
 */
	protected function _parseActual($actual, $expected) {
		$actual = Hash::remove($actual, '{n}.TrackableCreator');
		$actual = Hash::remove($actual, '{n}.TrackableUpdater');

		$indexes = array_keys($expected);
		foreach ($indexes as $i) {
			if (! Hash::get($expected, $i . '.' . $this->TestModel->alias . '.created_user')) {
				$actual = Hash::remove($actual, $i . '.' . $this->TestModel->alias . '.created_user');
			}
			if (! Hash::get($expected, $i . '.' . $this->TestModel->alias . '.created')) {
				$actual = Hash::remove($actual, $i . '.' . $this->TestModel->alias . '.created');
			}
			if (! Hash::get($expected, $i . '.' . $this->TestModel->alias . '.modified_user')) {
				$actual = Hash::remove($actual, $i . '.' . $this->TestModel->alias . '.modified_user');
			}
			if (! Hash::get($expected, $i . '.' . $this->TestModel->alias . '.modified')) {
				$actual = Hash::remove($actual, $i . '.' . $this->TestModel->alias . '.modified');
			}
		}

		return $actual;
	}

}
