<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing

namespace MailPoet\Newsletter\Renderer\Blocks;

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


use MailPoet\Entities\NewsletterEntity;
use MailPoet\Newsletter\Renderer\Columns\ColumnsHelper;
use MailPoet\Newsletter\Renderer\StylesHelper;

class Renderer {
  /** @var AutomatedLatestContentBlock  */
  private $ALC;

  /** @var Button */
  private $button;

  /** @var Divider */
  private $divider;

  /** @var Footer */
  private $footer;

  /** @var Header */
  private $header;

  /** @var Image */
  private $image;

  /** @var Social */
  private $social;

  /** @var Spacer */
  private $spacer;

  /** @var Text */
  private $text;

  /** @var Placeholder */
  private $placeholder;

  /** @var Coupon */
  private $coupon;

  /** @var DynamicProductsBlock */
  private $dynamicProducts;

  public function __construct(
    AutomatedLatestContentBlock $ALC,
    Button $button,
    Divider $divider,
    Footer $footer,
    Header $header,
    Image $image,
    Social $social,
    Spacer $spacer,
    Text $text,
    Placeholder $placeholder,
    Coupon $coupon,
    DynamicProductsBlock $dynamicProducts
  ) {
    $this->ALC = $ALC;
    $this->button = $button;
    $this->divider = $divider;
    $this->footer = $footer;
    $this->header = $header;
    $this->image = $image;
    $this->social = $social;
    $this->spacer = $spacer;
    $this->text = $text;
    $this->placeholder = $placeholder;
    $this->coupon = $coupon;
    $this->dynamicProducts = $dynamicProducts;
  }

  public function render(NewsletterEntity $newsletter, $data, bool $isRtl = false) {
    if (!isset($data['blocks']) || !is_countable($data['blocks']) || !is_iterable($data['blocks'])) {
        return null;
    }
    $columnCount = count($data['blocks']);
    $columnsLayout = $data['columnLayout'] ?? null;
    $columnWidths = ColumnsHelper::columnWidth($columnCount, $columnsLayout);
    $columnContent = [];

    foreach ($data['blocks'] as $index => $columnBlocks) {
      $renderedBlockElement = $this->renderBlocksInColumn($newsletter, $columnBlocks, $columnWidths[$index], $isRtl);
      $columnContent[] = $renderedBlockElement;
    }

    return $columnContent;
  }

  private function renderBlocksInColumn(NewsletterEntity $newsletter, $block, $columnBaseWidth, bool $isRtl = false) {
    $blockContent = '';
    $_this = $this;
    array_map(function($block) use (&$blockContent, $columnBaseWidth, $newsletter, $_this, $isRtl) {
      $renderedBlockElement = $_this->createElementFromBlockType($newsletter, $block, $columnBaseWidth, $isRtl);
      if (isset($block['blocks'])) {
        $renderedBlockElement = $_this->renderBlocksInColumn($newsletter, $block, $columnBaseWidth, $isRtl);
        // nested vertical column container is rendered as an array
        if (is_array($renderedBlockElement)) {
          $renderedBlockElement = implode('', array_map(static fn($v): string => is_scalar($v) ? (string)$v : '', $renderedBlockElement));
        }
      }

      $blockContent .= $renderedBlockElement;
    }, $block['blocks']);
    return $blockContent;
  }

  public function createElementFromBlockType(NewsletterEntity $newsletter, $block, $columnBaseWidth, bool $isRtl = false) {
    if ($block['type'] === 'automatedLatestContent') {
      return $this->processAutomatedLatestContent($newsletter, $block, $columnBaseWidth, $isRtl);
    }
    if ($block['type'] === 'dynamicProducts') {
      return $this->processDynamicProducts($block, $columnBaseWidth);
    }
    $block = StylesHelper::applyTextAlignment($block);
    switch ($block['type']) {
      case 'button':
        return $this->button->render($block, $columnBaseWidth);
      case 'divider':
        return $this->divider->render($block);
      case 'footer':
        return $this->footer->render($block, $isRtl);
      case 'header':
        return $this->header->render($block, $isRtl);
      case 'image':
        return $this->image->render($block, $columnBaseWidth);
      case 'social':
        return $this->social->render($block);
      case 'spacer':
        return $this->spacer->render($block);
      case 'text':
        return $this->text->render($block, $isRtl);
      case 'placeholder':
        return $this->placeholder->render($block);
      case Coupon::TYPE:
        return $this->coupon->render($block, $columnBaseWidth);
    }
    return "<!-- Skipped unsupported block type: {$block['type']} -->";
  }

  public function processAutomatedLatestContent(NewsletterEntity $newsletter, $args, $columnBaseWidth, bool $isRtl = false) {
    $transformedPosts = [
      'blocks' => $this->ALC->render($newsletter, $args),
    ];
    $transformedPosts = StylesHelper::applyTextAlignment($transformedPosts);
    return $this->renderBlocksInColumn($newsletter, $transformedPosts, $columnBaseWidth, $isRtl);
  }

  public function processDynamicProducts($args, $columnBaseWidth) {
    $renderedProducts = $this->dynamicProducts->render($args, $columnBaseWidth);
    return $renderedProducts;
  }
}
