<?php

final class Feed
{

    const BASE_PATH = "./data/cache/";
    const POST_COUNT = 10;

    private string $type;

    public function __construct(string $type = "rss")
    {
        $this->type = $type;
        $this->loadConfig();
    }

    public function run()
    {
        $this->render();
    }

    private function loadConfig()
    {
        require_once "config.php";
    }

    private function render()
    {
        header("Content-Type: application/xml");
        $file = self::BASE_PATH . $this->type . ".xml";
        $latest = self::BASE_PATH . "latest";
        if (!is_file($file) or filemtime($file) < filemtime($latest)) {
            extract($this->populateViews(FeedManager::getLatestPosts(self::POST_COUNT)));
            ob_start();
            include "views/" . $this->type . ".phtml";
            $output = ob_get_clean();
            file_put_contents($file, $output, LOCK_EX);
        }
        include $file;
    }

    private function populateViews(array $posts): array
    {
        return $this->type === "rss" ?
            $this->populateRss($posts) :
            $this->populateAtom($posts);
    }

    private function populateRss(array $posts): array
    {
        return array_merge(
            $this->populateCommon(),
            $this->populateRssRoot(),
            $this->populateItems($posts)
        );
    }

    private function populateAtom(array $posts): array
    {
        return array_merge(
            $this->populateCommon(),
            $this->populateAtomRoot(),
            $this->populateEntries($posts)
        );
    }

    private function populateCommon(): array
    {
        return [
            "title" => BLOG_TITLE,
            "has_sub_title" => BLOG_SUB_TITLE !== "",
            "sub_title" => BLOG_SUB_TITLE,
            "author_name" => AUTHOR_NICKNAME,
            "has_author_email" => AUTHOR_EMAIL !== "",
            "author_email" => AUTHOR_EMAIL
        ];
    }

    private function populateRssRoot(): array
    {
        return [
            "last_build_date" => date("r"),
            "link" => BLOG_LINK,
            "self" => BLOG_LINK . "/rss.php"
        ];
    }

    private function populateItems(array $posts): array
    {
        $items = [];
        foreach ($posts as $post) {
            $items[] = ItemParser::parse($post, BLOG_LINK);
        }
        return ["items" => $items];
    }

    private function populateAtomRoot(): array
    {
        return [
            "url" => BLOG_LINK,
            "updated" => date("c"),
            "id" => $this->getAtomUUID(),
            "self" => BLOG_LINK . "/atom.php"
        ];
    }

    private function getAtomUUID(): string
    {
        $file = self::BASE_PATH . "uuid";
        if (!is_file($file)) {
            file_put_contents($file, UUIDGenerator::generate(), LOCK_EX);
        }
        return file_get_contents($file);
    }

    private function populateEntries(array $posts): array
    {
        $entries = [];
        foreach ($posts as $post) {
            $entries[] = EntryParser::parse($post, BLOG_LINK);
        }
        return ["entries" => $entries];
    }

}