<?php
App::uses('SeoAppModel', 'Seo.Model');

/**
 * Class ModulesController
 * Handle the operations with the modules.
 *
 * @property Module Module The model.
 */
class ModulesController extends AppBackendController {

	function beforeFilter() {
		parent::beforeFilter();
		$this->Auth->actionMap['insert'] = 'read';
	}

	function afterForm() {

		// Get all available modules
		$modules = $this->Module->find('all', [
			'fields' => [ 'Module.use_table', 'Module.name', 'Module.id' ],
			'order'  => [ 'Module.use_table' ] ]);

		// Format array and exclude current module if editing
		$availableModules = [];
		foreach ($modules as $module) {
			if (!empty($this->request->data['Module']['id']) && $module['Module']['id'] == $this->request->data['Module']['id'])
				continue;
			$availableModules[$module['Module']['use_table']] = __(ucwords(str_replace('_', ' ', Inflector::underscore($module['Module']['name']))));
		}
		$this->set('modules', $availableModules);

		// On save
		if (isset($this->request->data['Module']['created']) && empty($this->Module->id)) {
			$module = ClassRegistry::init($this->request->data['Module']['name']);

			// Throw error if too many data
			if ($module->size() > 8 * 1024 * 1024) {
				$this->backtrack(__('Editing module of this size is not considered stable, please contact technical support'), 'danger');
			}

			// Name
			$this->request->data['Module']['name'] = preg_replace('~(.)([A-Z])~', '$1 $2', $this->request->data['Module']['name']);

			// Sort
			if ($module->order) {
				$this->request->data['Module']['sort_by'] = lastFromDot(key($module->order));
			}

			// Soft deletable
			$this->request->data['Module']['soft_deletable'] = (bool) $module->schema('is_deleted');

			// Activity state
			$this->request->data['Module']['activity_state'] = (bool) $module->schema('is_active');

			// Requires approval
			$this->request->data['Module']['requires_approval'] = (bool) $module->schema('approval_status');

			// Categories
			$this->request->data['Module']['has_categories'] = (bool) $module->schema('category_id');

			// Fields
			foreach ($module->schema() as $fieldname => $params)
				if (!strpos($fieldname, '__') && !in_array($fieldname, $this->Module->reserved['Fields'])) {
					$field['old'] = $fieldname;
					$field['name'] = Inflector::humanize($fieldname);
					switch ($params['type']) {

						case 'string':
							$field['type'] = 'varchar';
							$field['options']['length'] = $params['length'];
							$field['options']['polyglot'] = !empty($params['polyglot']);
							break;

						case 'text':
							$field['type'] = 'text';
							$field['options']['polyglot'] = !empty($params['polyglot']);
							$field['options']['richtext'] = !in_array('plain', (array) $params['params']);
							break;

						case 'boolean':
							$field['type'] = 'tinyint';
							$field['options']['checked'] = (bool) $params['default'];
							break;

						case 'integer':
						case 'biginteger':
							if (preg_match('/^cms_[a-z_]*_id$/', $field['old'])) {
								$field['type'] = 'module';
								$field['name'] = ucfirst(Inflector::underscore($field['name']));
								$field['module_name'] = str_replace(' ', '_', Inflector::tableize($field['name']));
								$field['options']['bigint'] = true;
								$field['options']['required'] = $params['null'] ? 0 : 1;
							} else {
								$field['type'] = 'int';
								$field['options']['bigint'] = $params['length'] > 11;
							}
							break;

						case 'date':
						case 'datetime':
							$field['type'] = 'datetime';
							$field['options']['justdate'] = $params['type'] == 'date';
							break;

						case 'enum':
							$field['type'] = 'enum';
							$field['options']['list'] = implode("\n", $params['enum']);
							break;
					}

					$this->request->data['Module']['Fields'][] = $field;
				}

			// Uploads
			foreach ([ 'hasOne', 'hasMany' ] as $type) {
				foreach ($module->$type as $association => $params)
					if ($params['className'] == 'Upload') {
						if ($association == 'MetaImage')
							continue;
						$this->request->data['Module']['Fields'][] = [
							'name'    => Inflector::humanize($association),
							'type'    => 'file',
							'options' => [
								'comment'    => $params['comment'],
								'extensions' => implode("\n", $params['extensions']),
								'multiple'   => $type == 'hasMany' ]
						];
					}
			}
		}

		// Load validation
		$this->__loadValidationVars();

		// Shortcuts
		$this->addShortcut('ctrl space', 'if($("a[href=#FieldTab]").parent().is(".active")) ModuleManager.addField()');
	}

	/** @inheritdoc */
	public function beforeIndex() {

		// Make sure the ACL is the latest.
		$this->Module->refreshAcl();
	}

	/**
	 * Action: Handle deleting old and adding new group.
	 */
	public function group() {

		// Delete
		if (!empty($this->request->data['delete'])) {
			$id = $this->request->data['delete'];

			// Switch group to null
			$modules = $this->Module->find('all', [
				'recursive'  => -1,
				'fields'     => [
					'id' ],
				'conditions' => [
					'module_group_id' => $id ]
			]);

			// Get the list to update
			$list = [];
			foreach ($modules as $module) {
				$list[] = [
					'id'              => $module['Module']['id'],
					'module_group_id' => null
				];
			}

			// Disconnect modules
			if (!empty($list)) {
				$this->Module->data = [];
				$this->Module->saveAll($list);
			}

			// Remove the group
			$this->Module->ModuleGroup->delete($id);

			// Edit or add
		} else if (!empty($this->request->data['name'])) {

			// Get the data
			$id = $this->request->data['id'];
			$name = $this->request->data['name'];
			$data = compact('id', 'name');

			// Set the proper ordering
			if (empty($id)) {
				$biggest = $this->Module->ModuleGroup->find('first', [
					'recursive' => -1,
					'fields'    => [
						'ordering' ],
					'order'     => 'ordering DESC'
				]);
				$data['ordering'] = @reset(reset($biggest)) + 1;
			}

			// Save
			$this->Module->ModuleGroup->save($data);
		}

		// Return
		echo json_encode([ 'success' => true ]);
		exit;
	}

	/**
	 * Action: Handle the reordering.
	 */
	public function reorder() {
		$save = [ 'groups' => [], 'modules' => [] ];
		$data = $this->request->data['reordering'];

		// Get the data
		foreach ($data as $group) {

			// Add to save list
			if ($group['id']) {
				$save['groups'][] = [
					'id'       => $group['id'],
					'ordering' => $group['ordering']
				];
			}

			// Append the modules
			if (!empty($group['modules'])) {
				foreach ($group['modules'] as $module) {
					$save['modules'][] = [
						'id'              => $module['id'],
						'ordering'        => $module['ordering'],
						'module_group_id' => $module['module_group_id'] ? $module['module_group_id'] : null
					];
				}
			}
		}

		// Save
		$this->Module->saveAll($save['modules']);
		$this->Module->ModuleGroup->saveAll($save['groups']);

		// Return
		echo json_encode([ 'success' => true ]);
		exit;
	}

	# ~ Load the validations for the module	 - - - - - - - - - - - - - - - - - - - #
	protected function __loadValidationVars() {
		$this->ValidationRule = ClassRegistry::init('ValidationRule');
		$validationRules = $this->ValidationRule->find('list', [
			'fields' => [ 'id', 'name' ]
		]);
		$this->set(compact('validationRules'));

		# Load existing validation rules
		if (!empty($this->request->data['Module']['id'])) {
			$fieldsValidations = $this->Module->getFieldsValidations($this->request->data['Module']['id']);
			foreach ($this->request->data['Module']['Fields'] as $index => $field) {
				if (@isset($fieldsValidations[$field['old']])) {
					$this->request->data['Module']['Fields'][$index] = array_merge($this->request->data['Module']['Fields'][$index], $fieldsValidations[$field['old']]);
					$this->request->data['Module']['Fields'][$index]['required'] = $fieldsValidations[$field['old']]['ModuleFields']['required'];
				}
			}
		}
	}

	/**
	 * Action: Get additional validation params.
	 */
	public function validation_params() {
		$this->layout = false;

		// Limit to AJAX calls
		if (!$this->request->is('ajax') || empty($this->request->data)) {
			$this->notFound();
		}

		$ruleId = $this->request->data['rule_id'];
		$this->ValidationRule = ClassRegistry::init('ValidationRule');
		$validationRule = $this->ValidationRule->find('first', $ruleId);
		$validationRule['ValidationRule']['additional_params'] = unserialize($validationRule['ValidationRule']['additional_params']);
		$this->set($this->request->data);
		$this->set(compact('validationRule'));
	}

}

