<?php
namespace SabaiApps\Directories\Component\Form\Field;

use SabaiApps\Directories\Component\Form\Form;

/**
 * TextField provides a single-line text input field.
 * Supports max length, placeholder, masks, slugify, and auto-populate.
 */
class TextField extends AbstractField {

	/**
	 * Initializes the Text field, sets up attributes, masks, and auto-populate logic.
	 *
	 * @param string $name
	 * @param array  $data
	 * @param Form   $form
	 */
	public function formFieldInit( $name, array &$data, Form $form ) {
		if ( isset( $data['#separator'] ) ) {
			// value is an array, so it must be converted to a string
			if ( isset( $data['#default_value'] ) && is_array( $data['#default_value'] ) ) {
				$data['#default_value'] = implode( $data['#separator'], $data['#default_value'] );
			}
			if ( isset( $data['#value'] ) && is_array( $data['#value'] ) ) {
				$data['#value'] = implode( $data['#separator'], $data['#value'] );
			}
		} elseif ( isset( $data['#max_length'] )
				&& is_numeric( $data['#max_length'] )
			) {

			if ( ! empty( $data['#max_length'] ) ) {
				$data['#attributes']['maxlength'] = (int) $data['#max_length'];
			}
		} else {
			$data['#attributes']['maxlength'] = 255;
		}

		if ( ! empty( $data['#states']['slugify'] ) ) {
			$data['#slugify'] = true;
		}

		if ( ! empty( $data['#mask'] ) || ! empty( $data['#slugify'] ) ) {
			if ( ! empty( $data['#mask'] ) ) {
				if ( ! isset( $data['#class'] ) ) {
					$data['#class'] = 'drts-form-type-textfield-mask';
				} else {
					$data['#class'] .= ' drts-form-type-textfield-mask';
				}
				$data['#attributes']['data-mask'] = $data['#mask'];
				if ( ! isset( $data['#placeholder'] ) ) {
					$data['#placeholder'] = $data['#mask'];
				}
			}
			if ( ! empty( $data['#slugify'] ) ) {
				if ( isset( $data['#attributes']['class'] ) ) {
					$data['#attributes']['class'] .= ' drts-form-type-textfield-slugify';
				} else {
					$data['#attributes']['class'] = 'drts-form-type-textfield-slugify';
				}
			}

			if ( ! isset( $form->settings['#pre_render'][ __CLASS__ ] ) ) {
				$form->settings['#pre_render'][ __CLASS__ ] = array( $this, 'preRenderCallback' );
			}
		}

		if ( ! empty( $data['#add_clear'] ) ) {
			if ( isset( $data['#attributes']['class'] ) ) {
				$data['#attributes']['class'] .= ' drts-form-type-textfield-with-clear';
			} else {
				$data['#attributes']['class'] = 'drts-form-type-textfield-with-clear';
			}
		}

		// Auto populate field if configured and not in admin
		if ( isset( $data['#autopopulate'] )
			&& ! $this->_application->getPlatform()->isAdmin()
		) {
			if ( ! isset( $data['#default_value'] )
				|| ( is_string( $data['#default_value'] ) && ! strlen( $data['#default_value'] ) && ! isset( $form->settings['#entity'] ) )
			) {
				switch ( $data['#autopopulate'] ) {
					case 'email':
						$value = $this->_application->getUser()->email;
						break;
					case 'url':
						$value = $this->_application->getUser()->url;
						break;
					case 'username':
						$value = $this->_application->getUser()->username;
						break;
					case 'name':
						$value = $this->_application->getUser()->name;
						break;
					default:
						$value = null;
				}
				$data['#default_value'] = $this->_application->Filter( 'form_field_autopopulate_value', $value, array( $data['#autopopulate'] ) );
			}
		}

		if ( ! isset( $data['#attributes']['placeholder'] ) ) {
			if ( ! isset( $data['#placeholder'] ) ) {
				if ( $data['#type'] === 'url'
					|| ( isset( $data['#char_validation'] ) && $data['#char_validation'] === 'url' )
				) {
					$data['#attributes']['placeholder'] = 'https://';
				}
			} else {
				$data['#attributes']['placeholder'] = $data['#placeholder'];
			}
		}
	}

	/**
	 * Validates an email address by checking the domain's MX record.
	 *
	 * @param Form   $form
	 * @param string $value
	 * @param array  $element
	 */
	public function validateEmail( Form $form, &$value, $element ) {
		list(, $domain) = explode( '@', $value );
		if ( ! $domain || ! checkdnsrr( $domain, 'MX' ) ) {
			$form->setError( __( 'Invalid domain name.', 'directories-pro' ), $element );
		}
	}

	/**
	 * Handles value processing and validation for the Text field on submit.
	 *
	 * @param mixed $value
	 * @param array $data
	 * @param Form  $form
	 */
	public function formFieldSubmit( &$value, array &$data, Form $form ) {
		if ( ! empty( $data['#skip_validate_text'] ) ) {
			return;
		}

		if ( isset( $data['#separator'] ) ) {
			$value = explode( $data['#separator'], $value );
			foreach ( array_keys( $value ) as $key ) {
				if ( false === $validated = $this->_application->Form_Validate_text( $value[ $key ], $data, $form, false, false ) ) {
					return;
				}
				if ( ! strlen( $validated ) ) {
					unset( $value[ $key ] );
					continue;
				}
				$value[ $key ] = $validated;
			}
			if ( empty( $value ) ) {
				if ( $form->isFieldRequired( $data ) ) {
					$form->setError( isset( $data['#required_error_message'] ) ? $data['#required_error_message'] : __( 'Please fill out this field.', 'directories-pro' ), $data );
				}
			} elseif ( ! empty( $data['#max_selection'] ) ) {
				if ( count( $value ) > $data['#max_selection'] ) {
					$form->setError( sprintf( __( 'Maximum of %d items is allowed for this field.', 'directories-pro' ), $data['#max_selection'] ), $data );
				}
			}
		} elseif ( false !== $validated = $this->_application->Form_Validate_text( $value, $data, $form ) ) {
				$value = $validated;
		}
	}

	/**
	 * Renders the Text field as an input element, with optional prefix/suffix/add-clear.
	 *
	 * @param array $data
	 * @param Form  $form
	 */
	public function formFieldRender( array &$data, Form $form ) {
		$this->_render( $this->_renderInput( $data, $form ), $data, $form );
	}

	/**
	 * Returns the HTML for the input element, with optional prefix/suffix/add-clear.
	 *
	 * @param array       $data
	 * @param Form        $form
	 * @param string|null $type
	 * @return string
	 */
	protected function _renderInput( array $data, Form $form, $type = null ) {
		if ( ! isset( $type ) ) {
			$type = $data['#type'];
		}
		switch ( $type ) {
			case 'number':
				if ( isset( $data['#min_value'] ) ) {
					$data['#attributes']['min'] = $data['#min_value'];
				}
				if ( isset( $data['#max_value'] ) ) {
					$data['#attributes']['max'] = $data['#max_value'];
				}
				if ( isset( $data['#step'] ) ) {
					$data['#attributes']['step'] = $data['#step'];
				}
				$data['#attributes']['onwheel'] = 'return false;'; // prevent number changing on mousewheel scroll
				break;
			case 'password':
			case 'search':
				break;
			default:
				$type = 'text';
		}

		$input = $this->_getInput( $data, $type );

		if ( ! isset( $data['#field_prefix'] )
			&& ! isset( $data['#field_suffix'] )
			&& empty( $data['#add_clear'] )
		) {
			return $input;
		}

		$has_addon = false;
		$ret       = array();
		if ( isset( $data['#field_prefix'] ) ) {
			if ( empty( $data['#field_prefix_no_addon'] ) ) {
				$has_addon = true;
				if ( ! empty( $data['#field_prefix_btn'] ) ) {
					$ret[] = '<button type="button" class="' . DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-' . ( $data['#field_prefix_btn_class'] ?? 'secondary' ) . '">' . $data['#field_prefix'] . '</button>';
				} else {
					$ret[] = '<span class="' . DRTS_BS_PREFIX . 'input-group-text">' . $data['#field_prefix'] . '</span>';
				}
			} else {
				$ret[] = $data['#field_prefix'];
			}
		}
		$ret[] = $input;
		if ( isset( $data['#field_suffix'] ) ) {
			if ( empty( $data['#field_suffix_no_addon'] ) ) {
				$has_addon = true;
				if ( ! empty( $data['#field_suffix_btn'] ) ) {
					$ret[] = '<button type="button" class="' . DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-' . ( $data['#field_suffix_btn_class'] ?? 'secondary' ) . '">' . $data['#field_suffix'] . '</button>';
				} else {
					$ret[] = '<span class="' . DRTS_BS_PREFIX . 'input-group-text">' . $data['#field_suffix'] . '</span>';
				}
			} else {
				$ret[] = $data['#field_suffix'];
			}
		}

		if ( ! empty( $data['#add_clear'] ) ) {
			$ret[] = '<i class="drts-clear fas fa-times-circle"></i>';
		}

		return $has_addon ? '<div class="' . DRTS_BS_PREFIX . 'input-group">' . implode( PHP_EOL, $ret ) . '</div>' : implode( PHP_EOL, $ret );
	}

	/**
	 * Pre-render callback to load scripts for masks and slugify functionality.
	 *
	 * @param Form $form
	 */
	public function preRenderCallback( Form $form ) {
		$this->_application->getPlatform()
			->addJsFile( 'jquery.maskedinput.min.js', 'jquery-maskedinput', array( 'jquery' ), null, true, true )
			->addJsFile( 'latinise.min.js', 'latinise', null, null, true, true );
		$form->settings['#js_ready'][] = '
var form = $("#__FORM_ID__");
form.find(".drts-form-type-textfield-mask input[type=text]").each(function(){
    var $this = $(this);
    $this.mask($this.data("mask") + ""); 
});
form.on("change", ".drts-form-type-textfield-slugify", function(){
    var $this = $(this);
    $this.val($this.val().latinise().replace(/\W+/g, "_").toLowerCase());
    if ($this.attr("maxlength")) {
        $this.val($this.val().slice(0, $this.attr("maxlength")));
    }
});
$(DRTS).on("clonefield.sabai", function (e, data) {
    if (data.clone.hasClass("drts-form-type-textfield-mask")) {
        var input = data.clone.find("input[type=text]");
        input.mask(input.data("mask"));
    }
});';
	}
}
