<?php

/**
 * @package     Joomla.Site
 * @subpackage  com_formea
 *
 * @copyright   Copyright (C) 2010-2025 Feseur Sdn Bhd. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @version     1.3.0
 */

namespace Joomla\Component\Formea\Site\Libraries;

defined('_JEXEC') or die;

use Exception;
use Feseur\Library\FsrHelper;
use Feseur\Library\FsrOptionTextVal;
use Feseur\Library\FsrResponse;
use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\CMS\Language\Text;
use Joomla\Component\Formea\Site\Helper\FormeaGeneralHelper;
use Joomla\Database\DatabaseDriver;
use Joomla\Filesystem\Path;
use Joomla\Registry\Registry;
use ReflectionObject;
use ReflectionProperty;
use stdClass;

class FormeaEltype
{

  /**
   * @var Registry
   * @since 1.0.0
   */
  public $params;

  /**
   * Directory to the element plugin ends with slash
   * @var string
   * @since 1.0.0
   */
  public $dirPath;

  /**
   * @var int
   * @since 1.0.0
   */
  public $element_id;

  /**
   * @var int
   * @since 1.0.0
   */
  public $form_id = 0;

  /**
   * @var int
   * @since 1.0.0
   */
  public $form_id_unique = 0;

  /**
   * @var string
   * @since 1.0.0
   */
  public $element_alias;

  /**
   * @var int
   * @since 1.0.0
   */
  public $id = 0;

  /**
   * @var string
   * @since 1.0.0
   */
  public $name;

  /**
   * @var string
   * @since 1.0.0
   */
  public $title;

  /**
   * @var string
   * @since 1.0.0
   */
  public $version;

  /**
   * @var string
   * @since 1.0.0
   */
  public $description;

  /**
   * @var string
   * @since 1.0.0
   */
  public $state;

  /**
   * @var stdClass
   * @since 1.0.0
   */
  public $config;

  protected $uniqid;

  /**
   * @var array
   * @since 1.0.0
   */
  public $element_details = [];

  /**
   * @var array
   * @since 1.0.0
   */
  public $element_values = [];

  /**
   * @var string
   * @since 1.0.0
   */
  protected $langTag;

  /**
   * @var string
   * @since 1.0.0
   */
  protected $langTagUnderscore;

  /**
   * @var FormeaTheme
   * @since 1.0.0
   */
  protected $themeClass;

  public $elementConfig;

  /**
   * @var int
   * @since 1.0.0
   */
  public $value_type = -1;

  protected $elType = null;

  public $element_title;

  /**
   * Input group setting
   * @var array
   * @since 1.0.3
   */
  public $igSetting;

  protected $isGroup = false;
  protected $group_id = -1;
  protected $group_type = -1;
  protected $setIndex = 0;

  /**
   * @var FormeaValidation[] | null
   * @since 1.0.3
   */
  public $validationClasses = null;

  /**
   * @var Registry | null
   * @since 1.0.5
   */
  public $form_element_settings = null;

  /**
   * @var string[]
   * @since 1.0.6
   */
  public $element_css_class = [];

  public function __construct($config = [])
  {
    $params = [];
    if (isset($config['igSetting'])) {
      $this->igSetting = $config['igSetting'];
    } else {
      $this->igSetting = [
        'bare' => false
      ];
    }
    if (isset($config['themeClass'])) {
      $this->themeClass = $config['themeClass'];
    }
    if (isset($config['params'])) {
      $params = $config['params'];
    }
    if (isset($config['element_id'])) {
      $this->element_id = $config['element_id'];
    } else {
      $this->element_id = rand(999, 9999);
    }
    if (isset($config['element_alias'])) {
      $this->element_alias = $config['element_alias'];
    }
    if (isset($config['element_title'])) {
      $this->element_title = $config['element_title'];
    }
    if (isset($config['id'])) {
      $this->id = $config['id'];
    }
    if (isset($config['name'])) {
      $this->name = $config['name'];
    }
    if (isset($config['title'])) {
      $this->title = $config['title'];
    }
    if (isset($config['form_id'])) {
      $this->form_id = $config['form_id'];
    } else {
      $this->form_id = rand(999, 9999);
    }
    if (isset($config['formUniqueString'])) {
      $this->form_id_unique = $config['formUniqueString'];
    } else {
      $this->form_id_unique = rand(999, 9999);
    }

    if (isset($config['isGroup'])) {
      $this->isGroup = $config['isGroup'];
    } else {
      $this->isGroup = false;
    }
    if (isset($config['group_id'])) {
      $this->group_id = $config['group_id'];
    }
    if (isset($config['group_type'])) {
      $this->group_type = $config['group_type'];
    }

    if (isset($config['setIndex'])) {
      $this->setIndex = $config['setIndex'];
    }

    if (isset($config['validationClasses'])) {
      $this->validationClasses = $config['validationClasses'];
    } else {
      $this->validationClasses = [];
    }

    if (isset($config['element_css_class'])) {
      $this->element_css_class = $config['element_css_class'];
    } else {
      $this->element_css_class = [];
    }

    if ($params instanceof Registry) {
      $this->params = $params;
    } else {
      $this->params = new Registry($params);
    }

    if (isset($config['element_details'])) {
      $this->element_details = $config['element_details'];
    }
    if (isset($config['element_values'])) {
      $this->element_values = $config['element_values'];
    }

    if (isset($config['form_element_settings'])) {
      $this->form_element_settings = $config['form_element_settings'];
    }

    $this->dirPath           = JPATH_ROOT . '/components/com_formea/plugins/element/';
    $app                     = Factory::getApplication();
    $lang                    = $app->getLanguage();
    $this->langTag           = $lang->getTag();
    $this->langTagUnderscore = str_replace('-', '_', $this->langTag);
    $this->elementConfig     = null;
    if (!empty($this->name)) {
      $langPath = JPATH_ROOT . '/components/com_formea/plugins/element/' . $this->name;
      if (is_dir(Path::clean($langPath . '/language/' . $this->langTag))) {
        $lang->load($this->name, $langPath, $this->langTag);
      }
      if (is_file(Path::clean($langPath . '/element.json'))) {
        $this->elementConfig = json_decode(file_get_contents($langPath . '/element.json'));
      }
    }
    $this->getElementType();
  }

  public function getElementType()
  {
    if (empty($this->elType)) {
      $ret     = null;
      $handler = -1; // 0-id,1 -name
      if ($this->id > 0) {
        $handler = 0;
      } elseif (!empty($this->name)) {
        $handler = 1;
      }
      if ($handler > -1) {
        $container = Factory::getContainer();
        /** @var DatabaseDriver $db */
        $db    = $container->get('DatabaseDriver');
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from($db->quoteName('#__formea_eltypes'));
        if ($handler > 0) {
          $query->where($db->quoteName('name') . ' = ' . $db->quote($this->name));
        } else {
          $query->where($db->quoteName('id') . ' = ' . $db->quote($this->id));
        }

        $db->setQuery($query);
        $elementType = $db->loadObject();
        if (!empty($elementType)) {
          $fields = $this->getAvailableFields();
          //get element config
          $conf                = (object) [];
          $filePath            = $this->dirPath . $elementType->name . '/element.json';
          $elementType->config = null;
          if (is_file(Path::clean($filePath))) {
            $conf          = file_get_contents($filePath);
            $conf          = json_decode($conf);
            $elementConfig = ['params' => []];
            if (!isset($conf->elementConfig)) {
              $conf->elementConfig = (object) $elementConfig;
            }
            if (!isset($conf->elementConfig->params)) {
              $conf->elementConfig->params = [];
            }
            //get the root xml
            $filePathXml = $this->dirPath . $elementType->name . '/' . $elementType->name . '.xml';
            if (!is_file(Path::clean($filePathXml))) {
              die;
            }
            $root = simplexml_load_file($filePathXml);
            if (isset($root->elementConfig)) {

              $configField = $root->elementConfig->children()->asXML();
              $xmlFields   = null;
              if ($configField) {
                $configField      = simplexml_load_string($configField, "SimpleXMLElement", LIBXML_NOCDATA);
                $configFieldArray = FsrHelper::xmlToArray($configField, [
                  'attributePrefix' => '',
                  'textContent'     => 'text',
                ]);
                $xmlFields        = FormeaGeneralHelper::searchByKeyRecursive($configFieldArray, 'field');
              }

              if (!empty($xmlFields)) {
                $totalXmlFields = count($xmlFields);
                $paramResult    = [];
                for ($j = 0; $j < $totalXmlFields; $j++) {

                  $field         = $xmlFields[$j];
                  $option        = [];
                  $selectedValue = '';
                  $defaultValue  = '';
                  foreach ($field as $keyAttr => $child) {
                    $key = str_replace('@', '', $keyAttr);
                    if (!is_array($child)) {
                      $param[$key] = Text::_($child);
                      if ($key === 'name') {
                        $selectedValue = $this->params->get($child, '');
                      }
                    } else {
                      if ($key === 'option') {
                        $totalChild = count($child);
                        for ($k = 0; $k < $totalChild; $k++) {
                          $option[$k] = (object) [
                            'text' => Text::_($child[$k]['text']),
                            'val'  => $child[$k]['value']
                          ];
                        }
                      }
                    }
                  }
                  $param['option']         = $option;
                  $param['selected_value'] = $selectedValue;
                  if (empty($selectedValue)) {
                    if (isset($param['default'])) {
                      $param['selected_value'] = $param['default'];
                    }
                  }
                  $paramResult[] = (object) $param;
                }
                $conf->elementConfig->params = $paramResult;
              }
            }

            $elementType->config = $conf;
          }
        }
        $ret = $elementType;
        if (!empty($fields)) {
          $totalFields = count($fields);
          for ($i = 0; $i < $totalFields; $i++) {
            if (isset($ret->{$fields[$i]})) {
              if ($fields[$i] === 'title' || $fields[$i] === 'description') {
                $this->{$fields[$i]} = Text::_($ret->{$fields[$i]});
              } else {
                $this->{$fields[$i]} = $ret->{$fields[$i]};
              }
            }
          }
        }
      }
      $this->elType = $ret;
    }


    return $this->elType;
  }

  public function getLabel($label = 'label', $class = [], $preview = false)
  {
    $labelOpening  = '<label for="' . $this->formatElementId() . '" class="' . implode(' ', $class) . '">';
    $labelClosing  = '</label>';
    $htmlStructure = [
      'labelOpening' => $labelOpening,
      'body'         => $label,
      'labelClosing' => $labelClosing
    ];
    /** @var FormeaValidation[] $validationClasses */
    $validationClasses = $this->validationClasses;
    if (!empty($validationClasses)) {
      $validationClasses      = array_values($validationClasses);
      $totalValidationClasses = count($validationClasses);
      for ($i = 0; $i < $totalValidationClasses; $i++) {
        $htmlStructure = $validationClasses[$i]->beforeGeneratingLabel($htmlStructure);
      }
    }

    return implode('', $htmlStructure);
  }

  /**
   * @param             $class
   * @param             $inputAttributes
   * @param             $langTagUnderscore
   * @param             $preview
   * @param   Registry  $labelSetting
   *
   * @return string
   *
   * @since 1.0.0
   */
  public function getInput($class = [], $inputAttributes = [], $langTagUnderscore = '', $preview = false, $labelSetting = null)
  {
    $themeClass = $this->getThemeClass();
    if (empty($langTagUnderscore)) {
      $langTagUnderscore = $this->langTagUnderscore;
    }
    $classAttr = [];
    if (empty($class)) {
      $classAttr[] = $themeClass->getInputClass();
    } else {
      $classAttr = array_merge($classAttr, $class);
    }
    $input     = '<input class="' . implode(' ', $classAttr) . '" ';
    $inputType = 'text';
    if (!empty($this->params)) {
      $inputType = $this->params->get('input_type', 'text');
    }
    $input .= 'type="' . $inputType . '"';
    if (!$preview) {
      $input .= 'name="' . $this->formatElementName() . '"';
    }
    if (isset($inputAttributes['placeholder'])) {
      $input .= 'placeholder="' . $inputAttributes['placeholder'] . '" ';
    }
    if (isset($inputAttributes['value'])) {
      $input .= 'value="' . htmlspecialchars($inputAttributes['value'], ENT_QUOTES) . '" ';
    }
    $input .= 'id="' . $this->formatElementId() . '" />';


    return $input;
  }

  public function getInputGroup($class = [], $inputAttributes = [], $langTagUnderscore = '', $preview = false, $labelSetting = null)
  {
    $themeClass = $this->getThemeClass();
    if (empty($langTag)) {
      $langTag = $this->langTag;
    }
    $langTagUnderscore  = str_replace('-', '_', $langTag);
    $columnClass        = ['fm_element_' . $this->form_id . '_' . $this->element_id];
    $labelText          = '';
    $labelClass         = $themeClass->getLabelElClass();
    $inputWrapper       = '';
    $inputWrapperCloser = '';

    $labelPosition   = 'TOP';
    $helperTextAlign = 'LEFT';
    $showLabel       = true;
    $error_msg       = [];
    $hasError        = false;

    // var_dump($labelSetting);die;

    if (!empty($labelSetting)) {
      $labelPosition     = strtoupper($labelSetting->get($langTagUnderscore . '.setting.position', 'TOP'));
      $labelSettingAlign = strtoupper($labelSetting->get($langTagUnderscore . '.setting.align', 'LEFT'));
      $showLabel         = filter_var($labelSetting->get($langTagUnderscore . '.setting.show_label', 'true'), FILTER_VALIDATE_BOOLEAN);
      if ($showLabel) {
        if ($labelPosition !== 'TOP') {
          $labelColumn           = (int) $labelSetting->get($langTagUnderscore . '.setting.label_column', 12);
          $columnClass[]         = $themeClass->getRowClass();
          $labelClass            = array_merge($themeClass->getLabelInlineElClass(), $labelClass);
          $labelClass[]          = $themeClass->getColumnClass($labelColumn);
          $wrapperSize           = $themeClass->getColumnAutoClass();
          $wrapperCalculatedSize = 12 - $labelColumn;
          if ($wrapperCalculatedSize > 0) {
            $wrapperSize = $themeClass->getColumnClass($wrapperCalculatedSize);
          }
          $inputWrapper       = '<div class="' . $wrapperSize . '">';
          $inputWrapperCloser = '</div>';
        }
        $labelClass[] = $themeClass->getTextAlignClass($labelSettingAlign);
      }
    }

    if ($labelPosition === 'TOP') {
      //$columnClass[] = $themeClass->getBlockClass();
    }

    if (isset($columnAttributes['class'])) {
      $columnClass[] = $columnAttributes['class'];
    }

    $html            = '<div class="' . implode(' ', $columnClass) . '">';
    $inputClass      = [];
    $inputAttributes = null;
    if (!empty($this->element_details)) {
      if (isset($this->element_details[$langTagUnderscore])) {
        $labelText = $this->element_details[$langTagUnderscore]['caption'];
        if (isset($this->element_details[$langTagUnderscore]['placeholder'])) {
          $inputAttributes['placeholder'] = $this->element_details[$langTagUnderscore]['placeholder'];
        }
        if (isset($this->element_details[$langTagUnderscore]['description'])) {
          $inputAttributes['description'] = $this->element_details[$langTagUnderscore]['description'];
        }
      }
    }
    if (!empty($this->element_values)) {
      if (isset($this->element_values[$langTagUnderscore])) {
        if (isset($this->element_values[$langTagUnderscore]['defval'])) {
          $inputAttributes['value'] = $this->element_values[$langTagUnderscore]['defval'];
        }
      }
    }

    if (!empty($submittedData) && isset($submittedData->elements)) {
      if (is_array($submittedData->elements)) {
        $totalElements = count($submittedData->elements);
        for ($i = 0; $i < $totalElements; $i++) {
          if ($submittedData->elements[$i]->element_id === $this->element_id) {
            if ($submittedData->elements[$i]->validation_error) {
              $hasError = false;

              $totalResults = count($submittedData->elements[$i]->validation_result->result);
              for ($j = 0; $j < $totalResults; $j++) {
                if (!empty($submittedData->elements[$i]->validation_result->result[$j]->result->result->msg)) {
                  $hasError    = true;
                  $error_msg[] = $submittedData->elements[$i]->validation_result->result[$j]->result->result->msg;
                }
              }
              if ($hasError) {
                $inputClass[] = $themeClass->getErrorClass();
              }
            } else {
              $inputClass[] = $themeClass->getNoErrorClass();
            }
            $inputAttributes['value'] = $submittedData->elements[$i]->submitted_value;
            break;
          }
        }
      }
    }


    if ($labelPosition !== 'RIGHT') {
      if (!$preview && $showLabel) {
        $html .= $this->getLabel($labelText, $labelClass, $preview);
      }
    }


    $elementAttributeClass = new FormeaElementAttribute(['element_id' => $this->element_id]);

    if (!empty($elementAttributeClass)) {
      $elementAttributes = $elementAttributeClass->getAttributes();
      if (!empty($elementAttributes->class)) {
        $inputClass[] = $elementAttributes->class;
      }
      foreach ($elementAttributes as $attr => $val) {
        if ($attr !== 'class') {
          $inputAttributes[$attr] = $val;
        }
      }
    }

    $html .= $inputWrapper;
    $html .= $this->getInput($inputClass, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);
    $html .= $this->getErrorMsgFeedback($error_msg, $hasError);
    if (isset($inputAttributes['description']) && !$preview) {
      $html .= $this->getHelperText($inputAttributes['description'], $langTagUnderscore, $inputAttributes, $labelSetting);
    }
    $html .= $inputWrapperCloser;
    if ($labelPosition === 'RIGHT') {
      if (!$preview && $showLabel) {
        $html .= $this->getLabel($labelText, $labelClass, $preview);
      }
    }
    $html .= '</div>';

    return $html;
  }


  public function getHelperText($description, $langTagUnderscore, $inputAttributes = [], $labelSetting = null)
  {
    $themeClass = $this->getThemeClass();
    $html       = '';
    if (!empty($description)) {
      $helper_align = 'LEFT';
      $classes      = [$themeClass->getHelperTextContainerClass()];
      if (isset($inputAttributes['form_text_class'])) {
        $classes[] = $inputAttributes['form_text_class'];
      }
      if (!empty($labelSetting)) {
        $helper_align = strtoupper($labelSetting->get($langTagUnderscore . '.helper_align', 'LEFT'));
      }
      $classes[] = $themeClass->getTextAlignClass($helper_align);
      $html      = '<div class="' . implode(' ', $classes) . '">' . $description . '</div>';
    }

    return $html;
  }

  public function getErrorMsgFeedback($error_msg = [], $isError = false)
  {
    $themeClass = $this->getThemeClass();
    $class      = ['fm_feedback_el'];
    $class[]    = $themeClass->getFeedbackContainerClass($isError);
    $html       = '';
    $html       .= '<div class="' . implode(' ', $class) . '">' . implode('<br/>', $error_msg) . '</div>';

    return $html;
  }

  public function getOptionLists($langTagUnderscore = '', $defaultValue = '')
  {
    if (empty($langTagUnderscore)) {
      $langTagUnderscore = $this->langTagUnderscore;
    }
    $html = '';
    if (!empty($this->element_values)) {
      if (isset($this->element_values[$langTagUnderscore])) {
        if (isset($this->element_values[$langTagUnderscore]['option_lists'])) {
          /** @var FsrOptionTextVal[] $optionLists */
          $optionLists = $this->element_values[$langTagUnderscore]['option_lists'];
          if (is_array($optionLists)) {
            $totalOptionLists = count($optionLists);
            for ($i = 0; $i < $totalOptionLists; $i++) {
              $html .= '<option ';
              if ($optionLists[$i]->selected) {
                $html .= 'selected="selected" ';
              }
              $html .= 'value="' . htmlspecialchars($optionLists[$i]->val, ENT_QUOTES) . '">';
              $html .= $optionLists[$i]->text;
              $html .= '</option>';
            }
          }
        }
      }
    }

    return $html;
  }

  /**
   * @param             $preview
   * @param             $langTag
   * @param             $columnAttributes
   * @param   Registry  $labelSetting
   *
   * @return string
   *
   * @since version
   */
  public function renderField($preview = false, $langTag = '', $columnAttributes = [], $inputAttributes = [], $labelSetting = null)
  {

    $themeClass = $this->getThemeClass();
    if (empty($langTag)) {
      $langTag = $this->langTag;
    }
    $langTagUnderscore  = str_replace('-', '_', $langTag);
    $columnClass        = ['fm_element_' . $this->form_id . '_' . $this->element_id];
    $columnClass        = array_merge($this->element_css_class, $columnClass);
    $labelText          = '';
    $labelClass         = $themeClass->getLabelElClass();
    $inputWrapper       = '';
    $inputWrapperCloser = '';

    $labelPosition   = 'TOP';
    $helperTextAlign = 'LEFT';
    $showLabel       = true;

    $submittedData = $this->getSubmittedElementData();
    $hasError      = $submittedData->hasError;
    $error_msg     = $submittedData->error_msg;
    // var_dump($labelSetting);die;

    if (!empty($labelSetting)) {
      $labelPosition     = strtoupper($labelSetting->get($langTagUnderscore . '.setting.position', 'TOP'));
      $labelSettingAlign = strtoupper($labelSetting->get($langTagUnderscore . '.setting.align', 'LEFT'));
      $showLabel         = filter_var($labelSetting->get($langTagUnderscore . '.setting.show_label', 'true'), FILTER_VALIDATE_BOOLEAN);
      if ($showLabel) {
        if ($labelPosition !== 'TOP' && $labelPosition !== 'BOTTOM') {
          $labelColumn           = (int) $labelSetting->get($langTagUnderscore . '.setting.label_column', 12);
          $columnClass[]         = $themeClass->getRowClass();
          $labelClass            = array_merge($themeClass->getLabelInlineElClass(), $labelClass);
          $labelClass[]          = $themeClass->getColumnClass($labelColumn);
          $wrapperSize           = $themeClass->getColumnAutoClass();
          $wrapperCalculatedSize = 12 - $labelColumn;
          if ($wrapperCalculatedSize > 0) {
            $wrapperSize = $themeClass->getColumnClass($wrapperCalculatedSize);
          }
          $inputWrapper       = '<div class="' . $wrapperSize . '">';
          $inputWrapperCloser = '</div>';
        }
        $labelClass[] = $themeClass->getTextAlignClass($labelSettingAlign);
      }
    }

    if ($hasError) {
      $columnClass[] = 'has-error';
    }


    if ($labelPosition === 'TOP') {
      $columnClass[] = $themeClass->getFormGroupClass();
    }

    if (isset($columnAttributes['class'])) {
      $columnClass[] = $columnAttributes['class'];
    }

    if (!empty($this->form_element_settings)) {
      if (!empty($this->form_element_settings->get('containerClass'))) {
        $columnClass[] = $this->form_element_settings->get('containerClass');
      }
    }

    $html       = '<div class="' . implode(' ', $columnClass) . '">';
    $inputClass = [];

    if (!empty($this->element_details)) {
      if (isset($this->element_details[$langTagUnderscore])) {
        $labelText = $this->element_details[$langTagUnderscore]['caption'];
        if (isset($this->element_details[$langTagUnderscore]['placeholder'])) {
          $inputAttributes['placeholder'] = $this->element_details[$langTagUnderscore]['placeholder'];
        }
        if (isset($this->element_details[$langTagUnderscore]['description'])) {
          $inputAttributes['description'] = $this->element_details[$langTagUnderscore]['description'];
        }
      }
    }
    if (!empty($this->element_values)) {
      if (isset($this->element_values[$langTagUnderscore])) {
        if (isset($this->element_values[$langTagUnderscore]['defval'])) {
          $inputAttributes['value'] = $this->element_values[$langTagUnderscore]['defval'];
        }
      }
    }

    if ($submittedData->hasSubmittedData) {
      $inputAttributes['value'] = $submittedData->submitted_value;
      if (!empty($submittedData->error_css_class)) {
        $inputClass[] = $submittedData->error_css_class;
      } else {
        $inputClass[] = $themeClass->getNoErrorClass();
      }
    }


    if ($labelPosition == 'TOP') {
      if (!$preview && $showLabel) {
        $html .= $this->getLabel($labelText, $labelClass, $preview);
      }
    }


    $elementAttributeClass = new FormeaElementAttribute(['element_id' => $this->element_id]);

    if (!empty($elementAttributeClass)) {
      $elementAttributes = $elementAttributeClass->getAttributes();
      if (!empty($elementAttributes->class)) {
        $inputClass[] = $elementAttributes->class;
      }
      foreach ($elementAttributes as $attr => $val) {
        if ($attr !== 'class' && $attr !== 'additional_attr') {
          $inputAttributes[str_replace('_', '-', $attr)] = $val;
        }
      }
    }
    if ($labelPosition == 'LEFT') {
      if (!$preview && $showLabel) {
        $html .= $this->getLabel($labelText, $labelClass, $preview);
      }
    }
    $html .= $inputWrapper;

    $html .= $this->getInput($inputClass, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);
    if ($labelPosition == 'BOTTOM') {
      if (!$preview && $showLabel) {
        $html .= $this->getLabel($labelText, $labelClass, $preview);
      }
    }
    $html .= $this->getErrorMsgFeedback($error_msg, $hasError);
    if (isset($inputAttributes['description']) && !$preview) {
      $html .= $this->getHelperText($inputAttributes['description'], $langTagUnderscore, $inputAttributes, $labelSetting);
    }
    $html .= $inputWrapperCloser;
    if ($labelPosition === 'RIGHT') {
      if (!$preview && $showLabel) {
        $html .= $this->getLabel($labelText, $labelClass, $preview);
      }
    }
    $html .= '</div>';

    return $html;
  }


  public function getBareInput($preview = false, $langTag = '', $columnAttributes = [], $labelSetting = null)
  {
    $themeClass = $this->getThemeClass();
    if (empty($langTag)) {
      $langTag = $this->langTag;
    }
    $langTagUnderscore = str_replace('-', '_', $langTag);
    $submittedData     = $this->getSubmittedElementData();

    $hasError        = $submittedData->hasError;
    $error_msg       = $submittedData->error_msg;
    $inputClass      = [];
    $inputAttributes = null;
    if (!empty($this->element_details)) {
      if (isset($this->element_details[$langTagUnderscore])) {
        $labelText = $this->element_details[$langTagUnderscore]['caption'];
        if (isset($this->element_details[$langTagUnderscore]['placeholder'])) {
          $inputAttributes['placeholder'] = $this->element_details[$langTagUnderscore]['placeholder'];
        }
        if (isset($this->element_details[$langTagUnderscore]['description'])) {
          $inputAttributes['description'] = $this->element_details[$langTagUnderscore]['description'];
        }
      }
    }
    if (!empty($this->element_values)) {
      if (isset($this->element_values[$langTagUnderscore])) {
        if (isset($this->element_values[$langTagUnderscore]['defval'])) {
          $inputAttributes['value'] = $this->element_values[$langTagUnderscore]['defval'];
        }
      }
    }

    if ($submittedData->hasSubmittedData) {
      $inputAttributes['value'] = $submittedData->submitted_value;
      if (!empty($submittedData->error_css_class)) {
        $inputClass[] = $submittedData->error_css_class;
      } else {
        $inputClass[] = $themeClass->getNoErrorClass();
      }
    }


    $elementAttributeClass = new FormeaElementAttribute(['element_id' => $this->element_id]);

    if (!empty($elementAttributeClass)) {
      $elementAttributes = $elementAttributeClass->getAttributes();
      if (!empty($elementAttributes->class)) {
        $inputClass[] = $elementAttributes->class;
      }
      foreach ($elementAttributes as $attr => $val) {
        if ($attr !== 'class') {
          $inputAttributes[$attr] = $val;
        }
      }
    }


    return $this->getInput($inputClass, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);
  }


  public function renderInputGroup($preview, $labelSetting)
  {
    $langTag = $labelSetting->lang_code;

    return $this->getBareInput($preview, $langTag, [], $labelSetting);
  }

  public function formatElementId()
  {
    $name = 'previewElement';
    if (!empty($this->element_alias)) {
      $name = $this->element_alias;
    }
    $name .= '_' . $this->element_id;
    if ($this->isGroup) {
      $name .= '_' . $this->group_id . '_' . $this->setIndex;
    }
    $name .= '_' . $this->form_id . '_' . $this->form_id_unique;

    return 'formea_' . $name;
  }

  public function formatElementName()
  {
    $nameStr = ['formea'];
    $name    = '[previewElement]';
    if (!empty($this->element_alias)) {
      $name = '[' . $this->element_alias . ']';
    }
    if ($this->isGroup) {
      $nameStr[] = '[group_' . $this->form_id_unique . ']';
      $nameStr[] = '[' . $this->group_id . '][' . $this->setIndex . ']';
    }
    $nameStr[] = $name;

    return implode('', $nameStr);
  }


  public function getAvailableFields()
  {
    $public = (new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);
    $ret    = [];
    if (!empty($public)) {
      $totalPublic = count($public);
      for ($i = 0; $i < $totalPublic; $i++) {
        $ret[] = $public[$i]->getName();
      }
    }

    return $ret;
  }

  public function getLabelSettings($elementDetails = [], $preview = [], $previewBare = [])
  {
    $languages     = FormeaGeneralHelper::getLanguages(true);
    $langData      = FormeaGeneralHelper::prepareLangData();
    $totalLangData = count($langData);
    $ret           = [];
    for ($i = 0; $i < $totalLangData; $i++) {
      if (isset($languages[$langData[$i]])) {
        $ret[] = FormeaGeneralHelper::getBlankLabelSetting($langData[$i], $languages[$langData[$i]]->title, $elementDetails, $preview, $previewBare);
      }
    }

    return $ret;
  }

  /**
   * @param   FormeaSubmissionElement  $element
   *
   * @return mixed
   *
   * @since 1.0.5
   */
  public function beforeValidatingInput($element)
  {
    return $element;
  }

  /**
   * The element before storing in DB right after validation process
   *
   * @param $element
   *
   * @return mixed
   *
   * @since 1.0.5
   */
  public function afterValidatingInput($element)
  {
    return $element;
  }

  public function afterStoringInDb($formObject, $submission_id, $element)
  {
    return $element;
  }

  public function preProcessSubmittedValue($submitted_value)
  {
    return $submitted_value;
  }

  /**
   * @param   mixed                    $submitted_value
   * @param   FormeaSubmissionElement  $element
   * @param   FormeaValidation[]       $validations
   *
   * @return FsrResponse
   *
   * @since 1.0.0
   */
  public function validateInput($submitted_value, $element, $validations = [])
  {
    $retObject        = new FsrResponse();
    $totalValidations = count($validations);
    $result           = [];
    $submitted_value  = $this->preProcessSubmittedValue($submitted_value);
    if ($totalValidations > 0) {
      for ($i = 0; $i < $totalValidations; $i++) {
        $validatorPath = JPATH_ROOT . '/components/com_formea/plugins/validation/' . $validations[$i]['validation_type'] . '/';
        $class         = $validations[$i]['validation_type'];
        if (is_file(Path::clean($validatorPath . $class . '.php'))) {
          require_once $validatorPath . $class . '.php';
          $config = [
            'submitted_value' => $submitted_value,
            'params'          => $validations[$i]['params'],
            'validation'      => $validations[$i],
            'value_type'      => 0
          ];
          /** @var FormeaValidation $validationClass */
          $validationClass = new $class($config);
          // var_dump($validationClass);die;
          $result[] = (object) ['validation_plugin' => $class, 'result' => $validationClass->validate()];
        } else {
          $retObject->setMsg(Text::sprintf('COM_FORMEA_VALIDATION_PLUGIN_S_NOT_FOUND', $validations[$i]['validation_type']));
        }
      }
    }
    $retObject->setResult($result);
    $retObject->setSuccess(true);

    return $retObject;
  }

  public function getImageDetails($absoluteUrl = false)
  {
    $ret            = new stdClass();
    $ret->image     = '';
    $ret->imageSafe = '';
    $ret->imageType = '';
    if (!empty($this->elementConfig)) {
      if (isset($this->elementConfig->imageDetails)) {
        $imageDetails = $this->elementConfig->imageDetails;
        if (isset($imageDetails->image) && !empty($imageDetails->image)) {
          if ($imageDetails->imageType == 1) {
            if (is_file(Path::clean(JPATH_ROOT . '/' . $imageDetails->image))) {
              $imageDetails->image = file_get_contents(JPATH_ROOT . '/' . $imageDetails->image);
            }
          }
        }
        $ret = $imageDetails;
      }
    }

    return $ret;
  }

  public function getPreviewSettings()
  {

    $ret = [];
    if (empty($this->previewSettings)) {
      if (isset($this->elementConfig->previewSettings)) {
        $ret = (array) $this->elementConfig->previewSettings;
      }
    }

    return $ret;
  }

  /**
   *
   * @return FormeaTheme
   *
   * @since 1.0.0
   */
  public function getThemeClass()
  {
    if (empty($this->themeClass)) {
      $this->themeClass = new FormeaTheme();
    }

    return $this->themeClass;
  }

  /**
   * Before element type being deleted
   * @return true
   *
   * @since 1.0.6
   */
  public function onDeleteElType()
  {
    return true;
  }

  /**
   * Method to delete Element type plugin (eltype)
   * @return FsrResponse
   *
   * @since 1.0.0
   */
  public function deleteEltype()
  {
    $retObject = new FsrResponse();
    try {
      if ((int) $this->id < 1) {
        throw new Exception(Text::_('COM_FORMEA_NO_ELEMENT_SELECTED'));
      }

      $container = Factory::getContainer();
      /** @var DatabaseDriver $db */
      $db    = $container->get('DatabaseDriver');
      $query = $db->getQuery(true);

      //check if element is in used
      $query->select(['a.title', 'b.title AS element_title']);
      $query->from($db->quoteName('#__formea_eltypes', 'a'))->innerJoin(
        $db->quoteName('#__formea_elements', 'b') . ' ON ' . $db->quoteName('a.name') . ' = ' .
          $db->quoteName('b.type')
      );
      $query->where($db->quoteName('a.id') . ' = ' . $db->quote($this->id));
      $db->setQuery($query);
      $usedInFormLists = $db->loadObjectList();
      $eltypeObject    = $this->getElementType();
      if (empty($eltypeObject)) {
        throw new Exception(Text::_('COM_FORMEA_ELTYPE_NOT_FOUND'));
      }

      if (!empty($usedInFormLists)) {
        $eltype_title    = '';
        $elementLists    = [];
        $totalUsedInForm = count($usedInFormLists);
        for ($i = 0; $i < $totalUsedInForm; $i++) {
          $eltype_title   = $usedInFormLists[$i]->title;
          $elementLists[] = $usedInFormLists[$i]->element_title;
        }
        $msg = Text::sprintf('COM_FORMEA_FAILED_TO_DELETE_ELTYPE_S', $eltype_title, implode(', ', $elementLists));
        throw new Exception($msg);
      }

      // delete all custom keys for user 1001.
      $conditions = array(
        $db->quoteName('id') . ' = ' . $this->id
      );

      $query->clear();
      $query->delete($db->quoteName('#__formea_eltypes'));
      $query->where($conditions);
      $db->setQuery($query);
      $db->execute();


      if (is_dir(Path::clean($this->dirPath . $eltypeObject->name))) {
        $elName    = $eltypeObject->name;
        $className = 'Formea' . $elName;
        require_once $this->dirPath . $elName . '/' . $className . '.php';
        /** @var FormeaEltype $elClass */
        $elClass = new $className();
        $done    = $elClass->onDeleteElType();
        Folder::delete($this->dirPath . $eltypeObject->name);
      }

      if (is_dir(Path::clean(JPATH_ROOT . '/media/com_formea/css/element/' . $eltypeObject->name))) {
        Folder::delete(JPATH_ROOT . '/media/com_formea/css/element/' . $eltypeObject->name);
      }
      if (is_dir(Path::clean(JPATH_ROOT . '/media/com_formea/js/element/' . $eltypeObject->name))) {
        Folder::delete(JPATH_ROOT . '/media/com_formea/js/element/' . $eltypeObject->name);
      }
      if (is_dir(Path::clean(JPATH_ROOT . '/media/com_formea/img/element/' . $eltypeObject->name))) {
        Folder::delete(JPATH_ROOT . '/media/com_formea/img/element/' . $eltypeObject->name);
      }


      $retObject->setSuccess(true);
      $retObject->setResult((object) [
        'deleted_eltype' => $eltypeObject
      ]);
    } catch (Exception $e) {
      $retObject->setSuccess(false);
      $retObject->setMsg($e->getMessage());
    }

    return $retObject;
  }

  public function getSubmittedElementData()
  {
    $submittedData    = null;
    $hasError         = false;
    $error_msg        = [];
    $submittedValue   = '';
    $error_css_class  = '';
    $themeClass       = $this->getThemeClass();
    $hasSubmittedData = false;
    if (!empty($this->form_id) && $this->form_id > 0) {
      $session       = Factory::getApplication()->getSession();
      $submittedData = $session->get('FORMEA_FORM_SUBMISSION_' . $this->form_id);
    }
    $foundElement = null;
    if (!empty($submittedData) && isset($submittedData->elements) && $submittedData->hasError) {
      if (!is_array($submittedData->elements)) {
        $submittedData->elements = [];
      }
      $_elements = [];
      if ($this->isGroup) {
        $_elements = $this->getElementByGroup($submittedData->elements, $this->group_id, $this->setIndex, $this->element_id);
      } else {
        $_elements = $this->getElementById($submittedData->elements, $this->element_id);
        //   var_dump($_elements);die;
      }

      if (!empty($_elements)) {
        $_elements = array_values($_elements);
        if (isset($_elements[0])) {
          $foundElement = $_elements[0];
        }
      }

      if (!empty($foundElement)) {
        $hasSubmittedData = true;
        if ($foundElement->validation_error) {
          $hasError     = false;
          $totalResults = count($foundElement->validation_result->result);
          for ($j = 0; $j < $totalResults; $j++) {
            if ($foundElement->validation_result->result[$j]->result->result->hasError) {
              $hasError = true;
            }
            if (!empty($foundElement->validation_result->result[$j]->result->result->msg)) {
              $error_msg[] = $foundElement->validation_result->result[$j]->result->result->msg;
            }
          }
          if ($hasError) {
            $error_css_class = $themeClass->getErrorClass();
          }
        } else {
          $error_css_class = $themeClass->getNoErrorClass();
        }
        $submittedValue = $foundElement->submitted_value;
      }
    }

    return (object) [
      'submitted_value'  => $submittedValue,
      'error_css_class'  => $error_css_class,
      'error_msg'        => $error_msg,
      'hasError'         => $hasError,
      'hasSubmittedData' => $hasSubmittedData,
      'submittedData'    => $submittedData
    ];
  }

  /**
   * @param $elements
   * @param $targetGroupId
   * @param $targetName
   *
   * @return array
   *
   * @since version
   */
  private function getElementByGroup($elements, $targetGroupId, $setIndex, $element_id)
  {
    $filteredObjects = array_filter($elements, function ($object) use ($targetGroupId, $setIndex, $element_id) {
      return $object->group_id === $targetGroupId && $object->setIndex === $setIndex && $object->element_id === $element_id;
    });

    return $filteredObjects;
  }

  /**
   *
   * @return array
   *
   * @since 1.0.0
   */
  public function getErrorMsg()
  {

    $submittedData = $this->getSubmittedElementData();

    return $submittedData->error_msg;
  }

  /**
   * @param $elements
   * @param $targetGroupId
   * @param $targetName
   *
   * @return array
   *
   * @since version
   */
  private function getElementById($elements, $element_id)
  {
    $filteredObjects = array_filter($elements, function ($object) use ($element_id) {
      return $object->element_id === $element_id;
    });

    return $filteredObjects;
  }

  /**
   * Get the inline JS script to be pushed in the header
   *
   * @since 1.0.0
   */
  public function getGeneratedScript()
  {
    return '';
  }

  /**
   * Get the inline CSS to be pushed in the header
   *
   * @since 1.0.0
   */
  public function getGeneratedStyle()
  {
    return '';
  }

  /**
   * JS file list to load
   *
   * @since 1.0.0
   */
  public function getLoadableScript()
  {
    return [];
  }

  /**
   * CSS file list to load
   *
   * @since 1.0.0
   */
  public function getLoadableStyle()
  {
    return [];
  }

  /**
   * CSS file list to load
   *
   * @since 1.0.9
   */
  public function getAdminLoadableStyle()
  {
    return [];
  }

  public function set($key, $value)
  {
    $this->{$key} = $value;
  }
}
