<?php

/**
 * Ahead WebSoft Technologies Pvt Ltd.
 * @copyright  Copyright 2006-2026 Ahead WebSoft Technologies Pvt Ltd.
 * @license    https://www.socialengine.com/policies
 */

class Core_Form_Custom_Fields extends Engine_Form
{

	protected $_item;
	protected $_processedValues = array();
	protected $_topLevelId;
	protected $_topLevelValue;
	protected $_packageId;
	protected $_resourceType;
	protected $_isCreation = false;

	// Add custom element paths?
	public function __construct($options = null)
	{
		Engine_FOrm::enableForm($this);
		self::enableForm($this);

		parent::__construct($options);
	}

	public static function enableForm(Zend_Form $form)
	{
		$form->addPrefixPath('Fields_Form_Element', APPLICATION_PATH . '/application/modules/Fields/Form/Element', 'element');
	}

	/* General */

	public function getItem()
	{
		return $this->_item;
	}

	//WE ARE JUST CHANGING IN THIS FUNCTION
	public function setItem($item)
	{
		$this->_item = $item;
		return $this;
	}

	public function setTopLevelId($id)
	{
		$this->_topLevelId = $id;
		return $this;
	}

	public function getPackagelId()
	{
		return $this->_packageId;
	}

	public function setPackageId($id)
	{
		$this->_packageId = $id;
		return $this;
	}

	public function getResourceType()
	{
		return $this->_resourceType;
	}

	public function setResourceType($id)
	{
		$this->_resourceType = $id;
		return $this;
	}

	public function getTopLevelId()
	{
		return $this->_topLevelId;
	}

	public function setTopLevelValue($val)
	{
		$this->_topLevelValue = $val;
		return $this;
	}

	public function getTopLevelValue()
	{
		return $this->_topLevelValue;
	}

	public function setIsCreation($flag = true)
	{
		$this->_isCreation = (bool) $flag;
		return $this;
	}

	public function setProcessedValues($values)
	{
		$this->_processedValues = $values;
		$this->_setFieldValues($values);
		return $this;
	}

	public function getProcessedValues()
	{
		return $this->_processedValues;
	}

	public function getFieldMeta()
	{
		return Engine_Api::_()->fields()->getFieldsMeta($this->getItem());
	}

	public function getFieldStructure()
	{
		// Let's allow fallback for no profile type (for now at least)
		if (!$this->_topLevelId || !$this->_topLevelValue) {
			$this->_topLevelId = null;
			$this->_topLevelValue = null;
		}
		return Engine_Api::_()->fields()->getFieldsStructureFull($this->getItem(), $this->_topLevelId, $this->_topLevelValue);
	}

	// Main

	public function generate()
	{
		$struct = $this->getFieldStructure();

		$orderIndex = 0;
		$isEnableCheck = 0;
		if ($this->_packageId != null) {
			$package = Engine_Api::_()->getItem($this->_resourceType, $this->_packageId);
			$fieldsEnable = json_decode($package->custom_fields_params, true);

			$params = json_decode($package->params, true);
			$enableCheck = $params['custom_fields'];
			$isEnableCheck = 1;
		}
		foreach ($struct as $fskey => $map) {
			$field = $map->getChild();

			// Ignore fields not searchable (even though getFieldsStructureSearch should have skipped it already)
			if (!$this->_isCreation && !$field->search) {
				continue;
			}

			// Skip fields hidden on signup
			//       if (isset($field->show) && !$field->show && $this->_isCreation) {
			//         continue;
			//       }
			if ($isEnableCheck && !engine_in_array($fskey, $fieldsEnable) && $fskey != '0_0_1' && $enableCheck == 2)
				continue;

			// Add field and load options if necessary
			try {
				$params = $field->getElementParams($this->getItem());
			} catch (Exception $e) {
				continue;
			}
			$key = $map->getKey();

			// If value set in processed values, set in element
			if (!empty($this->_processedValues[$field->field_id])) {
				$params['options']['value'] = $this->_processedValues[$field->field_id];
			}

			if (!@is_array($params['options']['attribs'])) {
				$params['options']['attribs'] = array();
			}

			if ($params['type'] != 'Heading') {
				if (isset($params['options']['icon']) && $params['options']['icon'])
					$params['options']['label'] = '<i class="' . $params['options']['icon'] . '"></i>' . Zend_Registry::get('Zend_Translate')->_($params['options']['label']);
			}

			// Heading
			if ($params['type'] == 'Heading') {
				$params['options']['value'] = Zend_Registry::get('Zend_Translate')->_($params['options']['label']);
				unset($params['options']['label']);
			}

			// Order
			// @todo this might cause problems, however it will prevent multiple orders causing elements to not show up
			$params['options']['order'] = $orderIndex++;

			$inflectedType = Engine_Api::_()->fields()->inflectFieldType($params['type']);
			unset($params['options']['alias']);
			unset($params['options']['publish']);
			$this->addElement($inflectedType, $key, $params['options']);
			if ($params['type'] != 'Heading') {
				$this->getElement($key)->getDecorator('label')
					->setOption('escape', false);
				$this->getElement($key)->addDecorator('FormErrors');
				$this->getElement($key)->getDecorator('FormErrors')->setEscape(false);
			}

			$element = $this->getElement($key);

			if (method_exists($element, 'setFieldMeta')) {
				$element->setFieldMeta($field);
			}

			// Set attributes for hiding/showing fields using javscript
			$classes = 'field_container field_' . $map->child_id . ' option_' . $map->option_id . ' parent_' . $map->field_id;
			$element->setAttrib('class', $classes);
			$element->setAttrib('readonly', '');
			$element->setAttrib('onfocus', "this.removeAttribute('readonly')");
			//
			if ($field->canHaveDependents()) {
				$element->setAttrib('onchange', 'changeFields(this)');
			}

			// Set custom error message
			if ($field->error) {
				$element->addErrorMessage($field->error);
			}

			if ($field->isHeading()) {
				$element->removeDecorator('Label')
					->removeDecorator('HtmlTag')
					->getDecorator('HtmlTag2')->setOption('class', 'form-wrapper-heading');
			}
		}

		$this->addElement('Button', 'submit', array(
			'label' => 'Save',
			'type' => 'submit',
			'order' => 10000,
		));
	}

	public function saveValues()
	{
		// An id must be set to save data (duh)
		if (is_null($this->getItem())) {
			throw new Exception("Cannot save data when no identity has been specified");
		}

		// Iterate over values
		$values = Engine_Api::_()->fields()->getFieldsValues($this->getItem());
		//remove class fields
		foreach ($values as $iteVal)
			$iteVal->delete();

		$fVals = $_POST;

		if ($this->_elementsBelongTo) {
			if (isset($fVals[$this->_elementsBelongTo])) {
				$fVals = $fVals[$this->_elementsBelongTo];
			}
		}
		foreach ($fVals as $key => $value) {
			$parts = explode('_', $key);
			if ((engine_count($parts) != 3 || !intval($parts[0]) || !intval($parts[1]) || !intval($parts[2])  || $key == 'MAX_FILE_SIZE'))
				continue;
			list($parent_id, $option_id, $field_id) = $parts;

			// Whoops no headings
			if ($this->getElement($key) instanceof Engine_Form_Element_Heading) {
				continue;
			}
			// Array mode
			if ($this->getElement($key) && (is_array($value) || $this->getElement($key)->isArray())) {

				// Lookup
				$valueRows = $values->getRowsMatching(array(
					'field_id' => $field_id,
					'item_id' => $this->getItem()->getIdentity()
				));

				// Delete all
				foreach ($valueRows as $valueRow) {
					$valueRow->delete();
				}

				// Insert all
				$indexIndex = 0;
				if (is_array($value) || !empty($value)) {
					if (is_array($value) && array_key_exists('month', $value)) {
						$value = $value['year'] . '-' . $value['month'] . '-' . $value['day'];
					}
					foreach ((array) $value as $singleValue) {
						$valueRow = $values->createRow();
						$valueRow->field_id = $field_id;
						$valueRow->item_id = $this->getItem()->getIdentity();
						$valueRow->index = $indexIndex++;
						$valueRow->value = $singleValue;
						$valueRow->save();
					}
				}
			}

			// Scalar mode
			else {
				// Lookup
				$valueRow = $values->getRowMatching(array(
					'field_id' => $field_id,
					'item_id' => $this->getItem()->getIdentity(),
					'index' => 0
				));

				// Remove value row if empty
				if (empty($value)) {
					if ($valueRow) {
						$valueRow->delete();
					}
					continue;
				}

				// Create if missing
				$isNew = false;
				if (!$valueRow) {
					$isNew = true;
					$valueRow = $values->createRow();
					$valueRow->field_id = $field_id;
					$valueRow->item_id = $this->getItem()->getIdentity();
				}

				$valueRow->value = htmlspecialchars($value);
				try {
					$valueRow->save();
				} catch (Exception $e) {
					//silence
				}
			}
		}

		// Update search table
		Engine_Api::_()->getApi('core', 'fields')->updateSearch($this->getItem(), $values);

		// Fire on save hook
		Engine_Hooks_Dispatcher::getInstance()->callEvent('onFieldsValuesSave', array(
			'item' => $this->getItem(),
			'values' => $values
		));

		// Regenerate form
		$this->generate();
	}

	protected function _setFieldValues($values)
	{
		// Iterate over elements and apply the values
		foreach ($this->getElements() as $key => $element) {
			if (engine_count(explode('_', $key)) == 3) {
				list($parent_id, $option_id, $field_id) = explode('_', $key);
				if (isset($values[$field_id])) {
					$element->setValue($values[$field_id]);
				}
			}
		}
	}

	/* These are hacks to existing form methods */

	public function init()
	{
		$this->generate();
	}

	public function isValid($data)
	{
		if (!is_array($data)) {
			require_once 'Zend/Form/Exception.php';
			throw new Zend_Form_Exception(__CLASS__ . '::' . __METHOD__ . ' expects an array');
		}
		$translator = $this->getTranslator();
		$valid = true;

		if ($this->isArray()) {
			$data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
		}
		$front = Zend_Controller_Front::getInstance();
		$module = !empty($_POST['moduleName'])  ? $_POST['moduleName']  : $front->getRequest()->getModuleName();
		//sesapi calling
		if (!empty($_POST['module']))
			$module = $_POST["module"];
		// Changing this part
		$structure = $this->getFieldStructure();
		$selected = array();
		$arrayId = array();
		if (!empty($this->_topLevelId))
			$selected[$this->_topLevelId] = $this->_topLevelValue;
		if (isset($_POST['category_id']) && $_POST['category_id'] != 0) {
			$category_map_id_data = Engine_Api::_()->getDbtable('categories', $module)->getMapId($_POST['category_id']);
			if ($category_map_id_data != 0) {
				$category_map_id = $category_map_id_data;
				array_push($arrayId, $category_map_id);
			}
		}
		if (isset($_POST['subcat_id']) && $_POST['subcat_id'] != 0) {
			$subcategory_map_id_data = Engine_Api::_()->getDbtable('categories', $module)->getSubCatMapId($_POST['subcat_id']);
			if ($subcategory_map_id_data != 0) {
				$subcategory_map_id = $subcategory_map_id_data;
				array_push($arrayId, $subcategory_map_id);
			}
		}
		if (isset($_POST['subsubcat_id']) && $_POST['subsubcat_id'] != 0) {
			$subsubcategory_map_id_data = Engine_Api::_()->getDbtable('categories', $module)->getSubSubCatMapId($_POST['subsubcat_id']);
			if ($subsubcategory_map_id_data != 0) {
				$subsubcategory_map_id = $subsubcategory_map_id_data;
				array_push($arrayId, $subsubcategory_map_id);
			}
		}

		foreach ($this->getElements() as $key => $element) {

			$element->setTranslator($translator);

			$parts = explode('_', $key);
			if (engine_count($parts) !== 3) {
				continue;
			}


			list($parent_id, $option_id, $field_id) = $parts;
			//if( !is_numeric($field_id) ) continue;
			$fieldObject = $structure[$key];

			// All top level fields are always shown
			if (!empty($parent_id)) {

				$parent_field_id = $parent_id;
				$option_id = $option_id;
				// Field has already been stored, or parent does not have option
				// specified, <del>or field is a heading</del>
				if (isset($selected[$field_id]) || empty($selected[$parent_field_id]) /* || !isset($data[$key]) */) {
					$element->setIgnore(true);
					continue;
				}

				// Parent option doesn't match
				if (is_scalar($selected[$parent_field_id]) && $selected[$parent_field_id] != $option_id && !engine_in_array($option_id, $arrayId)) {
					$element->setIgnore(true);
					continue;
				} else if (is_array($selected[$parent_field_id]) && !engine_in_array($option_id, $selected[$parent_field_id])) {
					$element->setIgnore(true);
					continue;
				}
			}
			// This field is being used
			if (isset($data[$key])) {
				$selected[$field_id] = $data[$key];
			}

			if ($element instanceof Engine_Form_Element_Heading) {
				$element->setIgnore(true);
			} else if (!isset($data[$key])) {
				$valid = $element->isValid(null, $data) && $valid;
			} else {
				$valid = $element->isValid($data[$key], $data) && $valid;
			}
		}

		$this->_processedValues = $selected;
		// Done changing

		foreach ($this->getSubForms() as $key => $form) {
			$form->setTranslator($translator);
			if (isset($data[$key])) {
				$valid = $form->isValid($data[$key]) && $valid;
			} else {
				$valid = $form->isValid($data) && $valid;
			}
		}

		$this->_errorsExist = !$valid;

		return $valid;
	}
}
