<?php

namespace app\components;

use Yii;

use app\components\BaseField;
use app\components\Utilities;

/**
 * This class handles the following text field types:
 * - text
 * - email
 * - date
 * - time
 * - url
 * - phone
 * - file
 */

class TextField extends BaseField{
    public $form_id;    // Will be used if there is 'unique' rule to check if the value exists
    public $type;
    public $document;

    public function __construct($structure, $document, $form_id = null){
        parent::__construct($structure, $document, $form_id);
        $this->form_id = $form_id;
        $this->type = $this->structure['type'];
        $this->handleRules();
        if($this->js_script){
            Yii::$app->controller->getView()->registerJs($this->js_script);
        }
    }

    public function handleRules(){
        if(isset($this->structure['unique']) && $this->structure['unique']){
            $this->field->enableAjaxValidation = true;
            $_this = $this;
            self::$model->addRule([$this->name], function() use($_this) {
                if($_this->valueExistsInSubmissions()){   
                    self::$model->addError($_this->name, 'This value has been used before');
                }
            });
        }
        if(isset($this->structure['minlength'])){
            self::$model->addRule([$this->name], 'string', ['min' => $this->structure['minlength'], 'tooShort' => Yii::t('app', '{field} should contain at least {val} characters', ['field' => ucfirst($this->label), 'val' => $this->structure['minlength']])]);
        }
        if(isset($this->structure['maxlength'])){
            self::$model->addRule([$this->name], 'string', ['max' => $this->structure['maxlength'], 'tooLong' => Yii::t('app', '{field} should contain at most {val} characters', ['field' => ucfirst($this->label), 'val' => $this->structure['maxlength']])]);
        }
        
        if($this->type == 'email'){
            self::$model->addRule([$this->name], 'email', ['message' => Yii::t('app', '{field} should be a valid email address', ['field' => ucfirst($this->label)])]);
        }
        elseif($this->type == 'file'){
            if(isset($this->structure['maxFileSize'])){
                self::$model->addRule([$this->name], 'file', ['maxSize' => 1024 * 1024 * $this->structure['maxFileSize']]);
            }
            if(isset($this->structure['fileType'])){
                $extensions = Utilities::getExtensionsOfFileType($this->structure['fileType']);
                self::$model->addRule([$this->name], 'file', ['extensions' => $extensions]);
            }
        }
        elseif(($this->type == 'date' || $this->type == 'time') && isset($this->structure['expressionsCheckbox']) && $this->structure['expressionsCheckbox']){
            $this->field->enableAjaxValidation = true;
            $operator     = $this->structure['operator'];
            $first_value  = $this->structure['expressionsValue'];
            $second_value = $this->structure['expressionsValue-2'] ?? '';
            switch($operator){
                case 'less': {
                    if($this->type == 'date'){
                        $first_value = date('Y-m-d', strtotime($first_value . ' -1 days'));
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:Y-m-d', 'max' => $first_value, 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                    else{
                        $first_value = date('H:i', strtotime($first_value . ' -1 minutes'));
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:H:i', 'max' => $first_value, 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                }
                break;
                case 'lessEqual': {
                    if($this->type == 'date'){
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:Y-m-d', 'max' => $first_value, 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                    else{
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:H:i', 'max' => $first_value, 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                }
                break;
                case 'more': {
                    if($this->type == 'date'){
                        $first_value = date('Y-m-d', strtotime($first_value . ' +1 days'));
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:Y-m-d', 'min' => $first_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                    else{
                        $first_value = date('H:i', strtotime($first_value . ' +1 minutes'));
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:H:i', 'min' => $first_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                }
                break;
                case 'moreEqual': {
                    if($this->type == 'date'){
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:Y-m-d', 'min' => $first_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                    else{
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:H:i', 'min' => $first_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                }
                break;
                case 'equal': {
                    if($this->type == 'date'){
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:Y-m-d', 'min' => $first_value, 'max' => $first_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value]), 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                    else{
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:H:i', 'min' => $first_value, 'max' => $first_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value]), 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $first_value])]);
                    }
                }
                break;
                case 'between': {
                    if($this->type == 'date'){
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:Y-m-d', 'min' => $first_value, 'max' => $second_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value]), 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $second_value])]);
                    }
                    else{
                        self::$model->addRule([$this->name], 'date', ['format' => 'php:H:i', 'min' => $first_value, 'max' => $second_value, 'tooSmall' => Yii::t('app', '{field} must be no less than {val}', ['field' => ucfirst($this->label), 'val' => $first_value]), 'tooBig' => Yii::t('app', '{field} must be no greater than {val}', ['field' => ucfirst($this->label), 'val' => $second_value])]);
                    }
                }
                break;
            }
        }
    }

    public function valueExistsInSubmissions(){
        // Check if data is populated via post request
        // else the data is coming from processing synced-record, and the unique rule will be processed previously
        if(Yii::$app->request->isPost){
            if($this->document && Yii::$app->controller->action->id != 'verify-record'){
                if($this->document[$this->name] == Yii::$app->request->post()['DynamicModel'][$this->name]){
                    return false;
                }
            }
            $res = (new \yii\mongodb\Query())
                ->from('forms_' . $this->form_id)
                ->where([
                    $this->name => Yii::$app->request->post()['DynamicModel'][$this->name]
                ])
                ->one();
    
            return $res != null ? true : false;
        }
        return false;
    }
}