<?php

namespace onespace\tools\widgets\input;

use DateTime;
use Exception;
use yii\helpers\Html;
use yii\widgets\InputWidget;

/**
 * Generates a `<input type='date'>` type input.
 * 
 * {@inheritdoc}
 * 
 * @author  Gareth Palmer <gareth@one-space.co.za>
 */

final class DateSelector extends InputWidget {

    /**
     * The mimimum date that the calendar may allow.
     * 
     * @var string  $min
     * 
     * @access  public
     */

    public string $min;

    /**
     * The maximum date that the calendar may allow.
     * 
     * @var string  $max
     * 
     * @access  public
     */

    public string $max;

    /**
     * The only valid date format allowed, for min, max and other params.
     * 
     * @var string  DATE_FORMAT
     * 
     * @access  private
     */

    private const DATE_FORMAT = "Y-m-d";


    /**
     * {@inheritdoc}
     * 
     * @access  public
     */

    public function init(): void {
        parent::init();

        if (isset($this->min)) {
            if (!$this->validateDate($this->min)) {
                throw new Exception("Invalid minimum date parsed. Should be formatted " . self::DATE_FORMAT);
            }
            $this->options['min'] = $this->min;
        }

        if (isset($this->max)) {
            if (!$this->validateDate($this->max)) {
                throw new Exception("Invalid maximum date parsed. Should be formatted " . self::DATE_FORMAT);
            }
            $this->options['max'] = $this->max;
        }
    }


    /**
     * {@inheritdoc}
     * 
     * @return  string
     * 
     * @access  public
     */

    public function run(): string {
        if ($this->hasModel()) {
            return Html::activeInput('date', $this->model, $this->attribute, $this->options);
        } else {
            return Html::input('date', $this->name, $this->value, $this->options);
        }
    }


    /**
     * Validate if a date string is valid, that is Y-m-d (eg. 2023-07-14)
     * 
     * @param   string  $testDate   The date to test.
     * 
     * @return  bool
     * 
     * @access  private
     */

    private function validateDate(string $testDate): bool {
        $date = DateTime::createFromFormat(self::DATE_FORMAT, $testDate);
        return $date !== false;
    }
}
