<?php

namespace WP_AUX\Entities;

use WP_AUX\Entities\PageTemplate\LayoutEntity;
use WP_AUX\Entities\PageTemplate\HeaderEntity;
use WP_AUX\Entities\PageTemplate\SidebarEntity;
use WP_AUX\Services\AuxFramework\PageFieldGroupsService;

class PageTemplateEntity {
  protected ?int $postID = null;
  protected ?string $postType = null;

  public HeaderEntity $header;
  public LayoutEntity $layout;
  public SidebarEntity $sidebar;

  /* @var string|callable|object|null */
  protected $content;

  protected array $settings = [];

  public function __construct()
  {
    $this->layout = new LayoutEntity($this);
    $this->header = new HeaderEntity($this);
    $this->sidebar = new SidebarEntity($this);
  }

  public function getPostID(): ?int
  {
    return $this->postID;
  }

  public function getPostType(): ?string
  {
    return $this->postType;
  }

  public function setContent($content): self
  {
    $this->content = $content;

    return $this;
  }

  public function getSettings(): array
  {
    return $this->settings;
  }

  public function getSetting(string $key): mixed
  {
    return $this->settings[$key] ?? null;
  }

  /**
   * Render the page content
   *
   * If the content is a closure or callable, it will be called.
   * If the content is null, the_content() will be called.
   * If the content is not a closure or null, it will be echoed.
   *
   * @since 1.0.0
   */
  public function renderContent(): void
  {
    if (is_callable($this->content) && $this->content instanceof \Closure) {
      call_user_func($this->content);
    } elseif (is_null($this->content)) {
      the_content();
    } else {
      echo $this->content;
    }
  }

  /**
   * Set up the page template entity based on the request
   * @since 1.0.0
   */
  public function setFromRequest(bool $manuallyConfigure = false): self
  {
    if ($this->postID = get_the_ID()) {
      $this->postType = get_post()->post_type;
    }

    if (!$manuallyConfigure) {
      $this->settings = PageFieldGroupsService::getSettingsFromRequest();

      $this->header->setFromRequest();
      $this->layout->setFromRequest();
      $this->sidebar->setFromRequest();
    }

    return $this;
  }

  /**
   * Get the requested page template entity
   *
   * If the entity has not been set up yet, it will be set up.
   *
   * @since 1.0.0
   */
  public static function getRequested(bool $manuallyConfigure = false): PageTemplateEntity
  {
    static $instance;

    if (is_null($instance)) {
      $instance = new self();
      $instance->setFromRequest($manuallyConfigure);
    }

    return $instance;
  }

  /**
   * Get the absolute path of the page template part based on post type
   * @since 1.0.0
   */
  public function getRenderFile(string $templatePart): string
  {
    $tryPaths = [
      $this->getPostType() . '/' . $templatePart,
      $templatePart,
    ];

    foreach ($tryPaths as $tryPathKey => $tryPath) {
      $tryPaths[$tryPathKey] = 'template-parts/main-content/' . $tryPath . '.php';
    }

    return locate_template($tryPaths, false);
  }

  /**
   * Render a page template part based on post type
   * @since 1.0.0
   */
  public function renderTemplatePart(string $templatePart): void
  {
    $templateFile = $this->getRenderFile($templatePart);

    if ($templateFile) {
      load_template($templateFile, null);
    }
  }
}
