<?php

namespace MailPoet\Form\Block;

if (!defined('ABSPATH')) exit;


use MailPoet\Form\Util\FieldNameObfuscator;
use MailPoet\Models\ModelValidator;
use MailPoet\WP\Functions as WPFunctions;

/**
 * This class still covers several responsibilities and could be further refactored
 * @package MailPoet\Form\Block
 */
class BlockRendererHelper {

  /** @var FieldNameObfuscator */
  private $fieldNameObfuscator;

  /** @var WPFunctions */
  protected $wp;

  public function __construct(
    FieldNameObfuscator $fieldNameObfuscator,
    WPFunctions $wp
  ) {
    $this->fieldNameObfuscator = $fieldNameObfuscator;
    $this->wp = $wp;
  }

  public function getInputValidation(array $block, array $extraRules = [], ?int $formId = null): string {
    $rules = [];
    $blockId = $this->wp->escAttr($block['id']);

    if ($blockId === 'email') {
      $rules['required'] = true;
      $rules['minlength'] = ModelValidator::EMAIL_MIN_LENGTH;
      $rules['maxlength'] = ModelValidator::EMAIL_MAX_LENGTH;
      $rules['type-message'] = __('This value should be a valid email.', 'mailpoet');
    }

    if (($blockId === 'first_name') || ($blockId === 'last_name')) {
      $errorMessages = [
        __('Please specify a valid name.', 'mailpoet'),
        __('Addresses in names are not permitted, please add your name instead.', 'mailpoet'),
      ];
      $rules['names'] = '[' . implode(',', array_map(function (string $errorMessage): string {
        return htmlspecialchars((string)json_encode($errorMessage), ENT_QUOTES);
      }, $errorMessages)) . ']';
    }

    // Segments should be required only when form ID is not empty. That allows save form on subscription management site when any segment is not checked.
    if ($blockId === 'segments' && $formId) {
      $rules['required'] = true;
      $rules['mincheck'] = 1;
      $rules['group'] = $blockId;
      $rules['errors-container'] = '.mailpoet_error_' . $blockId . '_' . $formId;
      $rules['required-message'] = __('Please select a list.', 'mailpoet');
    }

    if (!empty($block['params']['required'])) {
      $rules['required'] = true;
      $rules['errors-container'] = '.mailpoet_error_' . $blockId . '_' . $formId;
      $rules['required-message'] = __('This field is required.', 'mailpoet');
    }

    if (!empty($block['params']['validate'])) {
      if ($block['params']['validate'] === 'phone') {
        $rules['pattern'] = "^[\d\+\-\.\(\)\/\s]*$";
        $rules['error-message'] = __('Please specify a valid phone number.', 'mailpoet');
      } else {
        $rules['type'] = $this->wp->escAttr($block['params']['validate']);
      }
    }

    if (in_array($block['type'], ['radio', 'checkbox'])) {
      $rules['group'] = 'custom_field_' . $blockId;
      $rules['errors-container'] = '.mailpoet_error_' . $blockId . ($formId ? '_' . $formId : '');
      $rules['required-message'] = __('Please select at least one option.', 'mailpoet');
    }

    if ($block['type'] === 'date') {
      $rules['group'] = 'custom_field_' . $blockId;
      $rules['errors-container'] = '.mailpoet_error_' . $blockId . ($formId ? '_' . $formId : '');
    }

    $validation = [];

    $rules = array_merge($rules, $extraRules);

    if (!empty($rules)) {
      $rules = array_unique($rules);
      foreach ($rules as $rule => $value) {
        if (is_bool($value)) {
          $value = ($value) ? 'true' : 'false';
        }
        // We need to use single quotes because we need to pass array of strings as a parameter for custom validation
        if ($rule === 'names') {
          $validation[] = 'data-parsley-' . $rule . '=\'' . $value . '\'';
        } else {
          $validation[] = 'data-parsley-' . $rule . '="' . $value . '"';
        }
      }
    }
    return join(' ', $validation);
  }

  public function renderLabel(array $block, array $formSettings): string {
    $html = '';
    $forId = '';

    if (
      isset($block['params']['hide_label'])
      && $block['params']['hide_label']
    ) {
      return $html;
    }

    $automationId = null;
    if (in_array($block['id'], ['email', 'last_name', 'first_name'], true)) {
      $automationId = 'data-automation-id="form_' . $block['id'] . '_label" ';
    }

    if (isset($formSettings['id'])) {
      $forId = 'for="form_' . $block['id'] . '_' . $formSettings['id'] . '" ';
    }

    if (
      isset($block['params']['label'])
      && strlen(trim($block['params']['label'])) > 0
    ) {
      $labelClass = 'class="mailpoet_' . $block['type'] . '_label" ';

      if (
        isset($block['params']['label_within'])
        && $block['params']['label_within']
      ) {
        $labelClass = 'class="mailpoet-screen-reader-text" ';
      }

      $html .= '<label '
        . $forId
        . $labelClass
        . $this->renderFontStyle($formSettings, $block['styles'] ?? [])
        . ($automationId ?? '')
        . '>';
      $html .= htmlspecialchars($block['params']['label']);

      if (isset($block['params']['required']) && $block['params']['required']) {
        $html .= ' <span class="mailpoet_required">*</span>';
      }

      $html .= '</label>';
    }
    return $html;
  }

  public function renderLegend(array $block, array $formSettings): string {
    $html = '';

    if (
      isset($block['params']['hide_label'])
      && $block['params']['hide_label']
    ) {
      return $html;
    }

    if (
      isset($block['params']['label'])
      && strlen(trim($block['params']['label'])) > 0
    ) {
      // Use _label suffix for backward compatibility
      $labelClass = 'class="mailpoet_' . $block['type'] . '_label" ';
      $html .= '<legend '
        . $labelClass
        . $this->renderFontStyle($formSettings, $block['styles'] ?? [])
        . '>';
      $html .= htmlspecialchars($block['params']['label']);

      if (isset($block['params']['required']) && $block['params']['required']) {
        $html .= ' <span class="mailpoet_required">*</span>';
      }

      $html .= '</legend>';
    }
    return $html;
  }

  public function renderFontStyle(array $formSettings, array $styles = []) {
    $rules = [];
    if (isset($formSettings['fontSize'])) {
      $rules[] = 'font-size: ' . trim($formSettings['fontSize']) . 'px;';
      $rules[] = 'line-height: ' . (float)trim($formSettings['fontSize']) * 1.2 . 'px";';
    }
    if (isset($styles['bold'])) {
      $rules[] = 'font-weight: bold;';
    }
    return $rules ? 'style="' . $this->wp->escAttr(implode("", $rules)) . '"' : '';
  }

  public function renderInputPlaceholder(array $block): string {
    $html = '';
    // if the label is displayed as a placeholder,
    if (
      isset($block['params']['label_within'])
      && $block['params']['label_within']
    ) {
      // display only label
      $html .= ' placeholder="';
      $html .= static::getFieldLabel($block);
      // add an asterisk if it's a required field
      if (isset($block['params']['required']) && $block['params']['required']) {
        $html .= ' *';
      }
      $html .= '" ';
    }
    return $html;
  }

  // return field name depending on block data
  public function getFieldName(array $block = []): string {
    if ((int)$block['id'] > 0) {
      return 'cf_' . $block['id'];
    } elseif (isset($block['params']['obfuscate']) && !$block['params']['obfuscate']) {
      return $block['id'];
    } else {
      return $this->fieldNameObfuscator->obfuscate($block['id']);//obfuscate field name for spambots
    }
  }

  public function getFieldLabel(array $block = []): string {
    return (isset($block['params']['label'])
            && strlen(trim($block['params']['label'])) > 0)
            ? $this->wp->escHtml(trim($block['params']['label'])) : '';
  }

  public function getFieldValue($block = []) {
    return (isset($block['params']['value'])
            && strlen(trim($block['params']['value'])) > 0)
            ? $this->wp->escAttr(trim($block['params']['value'])) : '';
  }

  public function getFieldIsRequired($block = []): bool {
    return (isset($block['params']['required'])
            && strlen(trim($block['params']['required'])) > 0)
            ? !empty($block['params']['required']) : false;
  }

  public function getInputModifiers(array $block = []): string {
    $modifiers = [];

    if (isset($block['params']['readonly']) && $block['params']['readonly']) {
      $modifiers[] = 'readonly';
    }

    if (isset($block['params']['disabled']) && $block['params']['disabled']) {
      $modifiers[] = 'disabled';
    }
    return join(' ', $modifiers);
  }
}
