<?php
  /**
   * @package     Formea.Plugin
   * @subpackage  element
   *
   * @copyright   Copyright (C) 2010-2023 Feseur Sdn Bhd. All rights reserved.
   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   * @version 1.0.2
   */
// no direct access
  defined('_JEXEC') or die();

  use Feseur\Library\FsrOptionTextVal;
  use Joomla\CMS\Component\ComponentHelper;
  use Joomla\CMS\Date\Date;
  use Joomla\CMS\Language\Multilanguage;
  use Joomla\CMS\WebAsset\WebAssetManager;
  use Joomla\Component\Formea\Site\Libraries\FormeaElementAttribute;
  use Joomla\Component\Formea\Site\Libraries\FormeaEltype;
  use Joomla\CMS\Table\Table;
  use Joomla\CMS\Plugin\PluginHelper;
  use Joomla\CMS\Factory;

  class FormeaCalendar extends FormeaEltype
  {
    protected $default_value;
    protected $raw_value;

    public function __construct($config = [])
    {
      parent::__construct($config);
      $app = Factory::getApplication();
      /** @var WebAssetManager $wa */
      $wa       = $app->getDocument()->getWebAssetManager();
      $registry = $wa->getRegistry();
      $registry->addRegistryFile('components/com_formea/plugins/element/Calendar/joomla.asset.json');
    }

    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];
      if (!empty($this->params))
      {
        $inline     = $this->params->get('layout', 'dropdown') === 'inline';
        $showBorder = filter_var((int) $this->params->get('show_border', 0), FILTER_VALIDATE_BOOLEAN);
        $fullWidth = filter_var((int) $this->params->get('calendar_full_width', 0), FILTER_VALIDATE_BOOLEAN);
        $showMonths = (int)$this->params->get('showMonths',1);
        $calendar_type = (int)$this->params->get('calendar_type',0);
        if ($inline && $showBorder)
        {
          $columnClass[] = 'formea-calendar-border';
        }
        if($inline && $showMonths == 1 && $calendar_type != 1 && $fullWidth){
          $columnClass[] = 'formea-calendar-full-width';
        }


      }
      $labelText          = '';
      $labelClass         = $themeClass->getLabelElClass();
      $inputWrapper       = '';
      $inputWrapperCloser = '';

      $labelPosition   = 'TOP';
      $helperTextAlign = 'LEFT';
      $showLabel       = true;
      // 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 = ['value' => ''];
      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 ($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;
          }
        }
      }
      $this->default_value =  $inputAttributes['value'];
      $html .= $inputWrapper;
      $html .= $this->getInput($inputClass, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);
      $html .= $inputWrapperCloser;
      if ($labelPosition === 'RIGHT')
      {
        if (!$preview && $showLabel)
        {
          $html .= $this->getLabel($labelText, $labelClass, $preview);
        }
      }
      $html .= '</div>';

      return $html;
    }


    public function getInput($class = [], $inputAttributes = [], $langTagUnderscore = '', $preview = false, $labelSetting = null)
    {
      if(!is_array($class)){
        $class = [$class];
      }
      $inline = true;
      if (!empty($this->params))
      {
        $inline = $this->params->get('layout', 'inline') == 'inline';
      }
      if ($inline)
      {
        return $this->_getInlineCalendar($class, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);
      }
      else
      {
        return $this->_getInputCalendar($class, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);
      }
    }

    protected function _getInputCalendar($class = [], $inputAttributes = [], $langTagUnderscore = '', $preview = false, $labelSetting = null)
    {
      $themeClass = $this->getThemeClass();
      if (empty($langTagUnderscore))
      {
        $langTagUnderscore = $this->langTagUnderscore;
      }
      $submittedData = $this->getSubmittedElementData();

      $default_value = '';
      if (isset($inputAttributes['value']))
      {
        $default_value = $inputAttributes['value'];
      }
      //$hasError = $submittedData->hasError;
      if ($submittedData->hasSubmittedData)
      {
        $default_value = $submittedData->submitted_value;
      }




      $default_value       = $this->_replacePlaceholder($default_value);
      $this->default_value = $default_value;

      $format = $this->params->get('dateFormat', 'Y-m-d');
      if ($format === 'custom')
      {
        $format = $this->params->get('custom_date_format', 'Y-m-d');
      }
      $format = $this->_convertFormatTokenForPhp($format);
      $mode   = $this->params->get('mode', 'single');
      if ($mode !== 'single')
      {
        $splitValue      = explode(',', $default_value);
        $totalSplitValue = count($splitValue);
        $v               = [];
        for ($i = 0; $i < $totalSplitValue; $i++)
        {
          $v[] = (new Date($splitValue[$i]))->format($format);
        }
        $default_value = implode(',', $v);
      }
      else
      {
        $default_value = (new Date($default_value))->format($format);
      }


      $error_msg = $submittedData->error_msg;
      $hasError  = $submittedData->hasError;

      $classAttr = [];
      if (!empty($submittedData->error_css_class))
      {
        $classAttr[] = $submittedData->error_css_class;
      }


      $classAttr[] = $themeClass->getInputClass();
      if (!empty($class))
      {
        if(!is_array($class)){
          $class = [$class];
        }
        $classAttr = array_merge($class,$classAttr);
      }

      $input     = '<input class="' . implode(' ', $classAttr) . '" ';
      $inputType = 'text';
      $input     .= 'type="' . $inputType . '"';
      if (!$preview)
      {
        $input .= 'name="' . $this->formatElementName() . '"';
      }
      if (isset($inputAttributes['placeholder']))
      {
        $input .= 'placeholder="' . $inputAttributes['placeholder'] . '" ';
      }
      if (isset($inputAttributes['value']))
      {
        $input .= 'value="' . $default_value . '" ';
      }

      $input .= 'id="' . $this->formatElementId() . '" />';

      $input .= $this->getErrorMsgFeedback($error_msg, $hasError);

      if (isset($inputAttributes['description']) && !$preview)
      {
        $input .= $this->getHelperText($inputAttributes['description'], $langTagUnderscore, $inputAttributes, $labelSetting);
      }

      return $input;
    }

    protected function _getInlineCalendar($class = [], $inputAttributes = [], $langTagUnderscore = '', $preview = false, $labelSetting = null)
    {
      $input = '';
      if ($preview)
      {
        $input .= '<img src="' . Joomla\CMS\Uri\Uri::root() . 'media/com_formea/img/element/Calendar/calendar-preview.jpg"';
        $input .= 'style="max-width:308px;"/>';
      }
      else
      {
        $show_input   = filter_var((int) $this->params->get('show_input', 1), FILTER_VALIDATE_BOOLEAN);
        $show_border  = filter_var((int) $this->params->get('show_border', 1), FILTER_VALIDATE_BOOLEAN);
        $border_color = $this->params->get('border_color');

        if (!$show_input)
        {
          $class[]= 'formea-hide-calendar';
        }

        $input .= $this->_getInputCalendar($class, $inputAttributes, $langTagUnderscore, $preview, $labelSetting);

      }

      return $input;
    }

    public function getGeneratedScript()
    {
      $options = [];
      $inline  = $this->params->get('layout', 'inline') == 'inline';
      /* $optionLists      = $this->_getOptionsLists();
       $totalOptionLists = count($optionLists);*/
      $mode = $this->params->get('mode', 'single');
      if ($inline)
      {
        $options['inline'] = true;
      }
      $format        = 'Y-m-d h:i K';
      $calendar_type = (int) $this->params->get('calendar_type', 0);
      if ($calendar_type == 1)
      {
        //time only
        $options['enableTime'] = true;
        $options['noCalendar'] = true;
        $format                = $this->params->get('timeFormat', 'h:i K');
        if ($format === 'custom')
        {
          $format = $this->params->get('custom_time_format', 'Y-m-d');
        }
        $options['enableSeconds'] = filter_var((int) $this->params->get('enableSeconds'), FILTER_VALIDATE_BOOLEAN);

        $options['hourIncrement']   = (int) $this->params->get('hourIncrement', 1);
        $options['minuteIncrement'] = (int) $this->params->get('minuteIncrement', 5);
        $options['time_24hr']       = filter_var((int) $this->params->get('time_24hr', 0), FILTER_VALIDATE_BOOLEAN);

      }
      elseif ($calendar_type == 2)
      {
        //both dates and time
        $options['enableTime']      = true;
        $options['enableSeconds']   = filter_var((int) $this->params->get('enableSeconds'), FILTER_VALIDATE_BOOLEAN);
        $options['hourIncrement']   = (int) $this->params->get('hourIncrement', 1);
        $options['minuteIncrement'] = (int) $this->params->get('minuteIncrement', 5);
        $options['time_24hr']       = filter_var((int) $this->params->get('time_24hr', 0), FILTER_VALIDATE_BOOLEAN);
        $dateFormat                 = $this->params->get('dateFormat', 'Y-m-d');
        if ($dateFormat === 'custom')
        {
          $dateFormat = $this->params->get('custom_date_format', 'Y-m-d');
        }
        $timeFormat = $this->params->get('timeFormat', 'h:i K');
        if ($format === 'custom')
        {
          $timeFormat = $this->params->get('custom_time_format', 'Y-m-d');
        }
        $format          = $dateFormat . ' ' . $timeFormat;
        $options['mode'] = $mode;
        $minDate         = $this->params->get('minDate');
        if (!empty($minDate))
        {
          $minDate            = $this->_replacePlaceholder($minDate);
          $options['minDate'] = $minDate;
        }
        $maxDate = $this->params->get('maxDate');
        if (!empty($maxDate))
        {
          $maxDate            = $this->_replacePlaceholder($maxDate);
          $options['maxDate'] = $maxDate;
        }
        $options['showMonths'] = (int) $this->params->get('showMonths', 1);
      }
      else
      {
        //dates only
        $options['mode'] = $mode;
        $minDate         = $this->params->get('minDate');
        if (!empty($minDate))
        {
          $minDate            = $this->_replacePlaceholder($minDate);
          $options['minDate'] = $minDate;
        }
        $maxDate = $this->params->get('maxDate');
        if (!empty($maxDate))
        {
          $maxDate            = $this->_replacePlaceholder($maxDate);
          $options['maxDate'] = $maxDate;
        }
        $options['showMonths'] = (int) $this->params->get('showMonths', 1);
        $format                = $this->params->get('dateFormat', 'Y-m-d');
        if ($format === 'custom')
        {
          $format = $this->params->get('custom_date_format', 'Y-m-d');
        }
        $options['enableTime'] = false;
      }


      if ($calendar_type != 1)
      {
        //activate mode
        if ($mode === 'single')
        {
          $options['defaultDate'] = $this->default_value;
        }
        elseif ($mode === 'range')
        {
          $dv = explode(',', $this->default_value);
          if (count($dv) == 1)
          {
            $dv[] = $dv[0];
          }
          $options['defaultDate'] = $dv;
        }
        else
        {
          $options['defaultDate'] = explode(',', (!empty($this->default_value))? $this->default_value : '');
        }


        $disable_date = (int) $this->params->get('disable_date', 0);
        if ($disable_date > 0)
        {
          if ($disable_date != 2)
          {
            //Disabling specific dates
            // or
            //Disabling all dates except listed
            $_datelists = $this->params->get('disabled_dates_list');
            if (!empty($_datelists))
            {
              $filteredDateLists = $this->_replacePlaceholder($_datelists);
              $datelists = explode(',',$filteredDateLists);
              $list = [];
              $totalDateLists = count($datelists);
              for($i = 0; $i < $totalDateLists; $i++) {
                $list[] = trim($datelists[$i]);
              }
              if(!empty($list)){
                if($disable_date == 1){
                  //Disabling specific dates
                  $options['disable'] = $list;
                }else{
                  //Disabling all dates except listed
                  $options['enable'] = $list;
                }
              }
            }
          }
          else
          {
            // Disabling a date range
            $_datelists = $this->params->get('disabled_dates_list');
            if (!empty($_datelists))
            {
              $filteredDateLists = $this->_replacePlaceholder($_datelists);
              $datelists = explode(',',$filteredDateLists);
              $list = [];
              $totalDateLists = count($datelists);
              for($i = 0; $i < $totalDateLists; $i++) {
                $trimmed = trim($datelists[$i]);
                $fromTo = explode('~',$trimmed);
                $from = trim($fromTo[0]);
                $to = $from;
                if(isset($fromTo[1])){
                  $to = trim($fromTo[1]);
                }
                $list[] = [
                  'from'=> $from,
                  'to'=> $to,
                ];
              }
              if(!empty($list)){
                $options['disable'] = $list;
              }
            }
          }
        }
      }

      $options['altFormat'] = $format;
      $options['altInput']  = true;
      $options['locale']    = ['rangeSeparator' => ' - '];
      $script = '';
      if($this->setIndex == 0){
        $script .= "document.addEventListener('DOMContentLoaded',function(){";
      }

      //$this->formatElementId()
      $script .= "flatpickr('#" . $this->formatElementId() . "', ";
      $script .= json_encode($options);
      $script .= ");";
      if($this->setIndex == 0){
        $script .= "});";
      }


      return $script;
    }

    public function getGeneratedStyle()
    {
      $css = '';
      if (!empty($this->params))
      {
        $inline     = $this->params->get('layout', 'dropdown') === 'inline';
        $showBorder = filter_var((int) $this->params->get('show_border', 0), FILTER_VALIDATE_BOOLEAN);
        if ($inline && $showBorder)
        {
          $borderStyle = $this->params->get('border_style', 'solid');
          $borderColor = $this->params->get('border_color', '#FFFFFF');
          $css         .= '.fm_element_' . $this->form_id . '_' . $this->element_id . '.formea-calendar-border .flatpickr-calendar{';
          $css         .= 'border-style:' . $borderStyle . ';';
          $css         .= 'border-color:' . $borderColor . ';';
          $css         .= '} ';
        }
      }

      return $css;
    }

    protected function _getOptionsLists()
    {
      $ret = [
        ['key' => 'minDate', 'default' => null, 'alt' => null, 'hasPlaceholder' => true],
        ['key' => 'maxDate', 'default' => null, 'alt' => null, 'hasPlaceholder' => true],
        ['key' => 'showMonths', 'default' => 1, 'alt' => null, 'hasPlaceholder' => false],
        ['key' => 'mode', 'default' => 'single', 'alt' => null, 'hasPlaceholder' => false],
      ];

      return $ret;
    }

    /**
     * @param   string  $value  a string of dates or placeholder separated by a comma
     *
     *
     * @since version
     */
    protected function _replacePlaceholder($value)
    {
      /*$format = $this->params->get('dateFormat','Y-m-d');
      if($format === 'custom'){
        $format = $this->params->get('custom_date_format','Y-m-d');
      }
      $format = $this->_convertFormatTokenForPhp($format);*/
      $format        = 'Y-m-d';
      $acceptedRange = [
        'year',
        'month',
        'week',
        'day',
      ];
      $placeholder   = [
        'TODAY' => (new Date())->format($format),
      ];
      $dates         = explode(',', $value);
      $totalDates    = count($dates);

      $ret = [];
      for ($i = 0; $i < $totalDates; $i++)
      {
        $date  = trim($dates[$i]);
        $ret[] = $date;

        if (substr($date, 0, 1) == '[')
        {
          $code     = str_replace(['[', ']'], '', $date);
          $snippets = explode('_', $code);
          if (count($snippets) >= 2)
          {
            if (in_array(strtolower($snippets[1]), $acceptedRange))
            {
              //check if x is a number
              if (is_numeric($snippets[0]))
              {
                $_format = '';
                $n       = (float) $snippets[0];
                if (isset($snippets[2]))
                {
                  $_format .= '- ';
                }
                $_format            .= $n;
                $_format            .= ' ' . strtolower($snippets[1]);
                $placeholder[$code] = (new Date($_format))->format($format);
              }
            }
          }
        }
      }

      $_value = implode(', ', $ret);

      foreach ($placeholder as $key => $val)
      {
        $_value = str_replace('[' . $key . ']', $val, $_value);
      }

      return $_value;
    }

    protected function _convertFormatTokenForPhp($jsToken)
    {
      $tokenMap = [
        'd' => 'd',
        'D' => 'D',
        'l' => 'l',
        'j' => 'j',
        'J' => 'jS',
        'w' => 'w',
        'W' => 'W',
        'F' => 'F',
        'm' => 'm',
        'n' => 'n',
        'M' => 'M',
        'U' => 'U',
        'y' => 'y',
        'Y' => 'Y',
        'Z' => 'c',
        'H' => 'H',
        'h' => 'h',
        'G' => 'G',
        'i' => 'i',
        'S' => 's',
        's' => 's',
        'K' => 'A',
      ];
      $phpToken = '';
      $jsChars  = str_split($jsToken);

      foreach ($jsChars as $char)
      {
        if (array_key_exists($char, $tokenMap))
        {
          $phpToken .= $tokenMap[$char];
        }
        else
        {
          $phpToken .= $char;
        }
      }

      return $phpToken;
    }

    public function getLoadableScript()
    {
      return [
        'com_formea.element.Calendar.pickr'
      ];
    }

    public function getLoadableStyle()
    {
      return [
        //'com_formea.element.Calendar.pickr'
        'com_formea.element.Calendar.main'
      ];
    }

  }
