<?php

namespace App\Services;

use HtmlSanitizer\SanitizerBuilder;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Environment\Environment;
use HtmlSanitizer\Extension\Basic\BasicExtension;
use HtmlSanitizer\Extension\Listing\ListExtension;
use HtmlSanitizer\Extension\Iframe\IframeExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\Attributes\AttributesExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;

class ContentService
{
    protected $files  = [];
    protected $config = [];

    public function __construct()
    {
        $this->loadPages(env('PAGES_PATH'));
    }

    public function loadPages($folder)
    {
        $folders = glob("$folder/*", GLOB_ONLYDIR);
        foreach ($folders as $folder) {
            //$this->files[] = $folder . "/";
            $this->loadPages($folder);
        }
        $files = array_filter(glob("$folder/*md"), 'is_file');
        foreach ($files as $file) {
            $this->files[] = $file;
        }
    }

    public function loadAllPages()
    {
        $environment = new Environment($this->config);
        $environment->addExtension(new CommonMarkCoreExtension());

        // Add the extension
        $environment->addExtension(new FrontMatterExtension());

        //Add Strikethrough rendering
        $environment->addExtension(new StrikethroughExtension());

        //add attributes to elements in markdown
        $environment->addExtension(new AttributesExtension());

        //add table rendering
        $environment->addExtension(new TableExtension());

        // Instantiate the converter engine and start converting some Markdown!
        $converter = new MarkdownConverter($environment);

        $contents = [];
        foreach ($this->files as $file) {
            //get meta and html from file
            $result = $converter->convertToHtml(file_get_contents($file));
            $meta   = [];
            if ($result instanceof RenderedContentWithFrontMatter) {
                $meta = $result->getFrontMatter();
            }

            //get raw markdown from file
            $frontMatterExtension = new FrontMatterExtension();
            $parsed               = $frontMatterExtension
                ->getFrontMatterParser()
                ->parse(file_get_contents($file));

            //never trust the front end. clean it up
            //add what sanitizer extensions we need manually
            $builder = new SanitizerBuilder();
            $builder->registerExtension(new BasicExtension());
            $builder->registerExtension(new IframeExtension());
            $builder->registerExtension(new ListExtension());
            //just add it straight because classname is already in use
            $builder->registerExtension(new \HtmlSanitizer\Extension\Table\TableExtension());

            //relative-a and relative-image
            $builder->registerExtension(
                new \HtmlSanitizer\Extension\Relative\A\AExtension()
            );
            $builder->registerExtension(
                new \HtmlSanitizer\Extension\Relative\Image\ImageExtension()
            );

            $detergent = [
                'extensions' => ['basic', 'list', 'relative-a', 'relative-image', 'iframe', 'table'],
                'tags'       => [
                    'div' => [
                        'allowed_attributes' => ['class', 'title', 'id', 'style'],
                    ],
                    'img' => [
                        'allowed_attributes' => ['src', 'alt', 'title', 'class'],
                    ],
                    'iframe' => [
                        'allowed_attributes' => ['height', 'width', 'title', 'src'],
                    ],
                ],
            ];

            $sanitizer = $builder->build($detergent);
            $scrubbed  = $sanitizer->sanitize($result->getContent());
            if (isset($meta['feature'])) {
                $featureList = explode(',', $meta['feature']);
            } else {
                $featureList = "";
            }

            $docs = '';
            if (isset($meta['files'])) {
                $fileList = explode(',', $meta['files']);
                $docs     = $meta['files'];
            } else {
                $fileList = [];
                $docs     = '';
            }

            $media = [];
            $files = [];
            if ($featureList != '') {
                foreach ($featureList as $file) {
                    $item = trim($file);
                    $ext  = pathinfo($item, PATHINFO_EXTENSION);
                    if ($item != null || $item != '') {
                        array_push($media, ['file' => $item, 'type' => trim($ext)]);
                    }
                }
            }

            if ($fileList != "") {
                foreach ($fileList as $file) {
                    $item = trim($file);
                    $ext  = pathinfo($item, PATHINFO_EXTENSION);
                    if ($item != null || $item != '') {
                        array_push($files, ['file' => $item, 'type' => trim($ext)]);
                    }
                }
            }

            //sort attributes into page object
            $page = [
                'id'           => $meta['id'],
                'uuid'         => $meta['uuid'],
                'title'        => $meta['title'],
                'feature'      => $meta['feature'],
                'files'        => $docs,
                'path'         => $meta['path'],
                'layout'       => $meta['layout'],
                'tags'         => $meta['tags'],
                'author'       => $meta['author'],
                'created'      => date('Y M D d', $meta['created']),
                'updated'      => date('Y M D d', $meta['updated']),
                'rawCreated'   => $meta['created'],
                'rawUpdated'   => $meta['updated'],
                'createdYear'  => date('Y', $meta['created']),
                'createdMonth' => date('m', $meta['created']),
                'deleted'      => $meta['deleted'],
                'menu'         => $meta['menu'],
                'featured'     => $meta['featured'],
                'published'    => $meta['published'],
                'slug'         => $meta['slug'],
                'filePath'     => $file,
                'content'      => $parsed->getContent(),
                'html'         => $scrubbed,
                'media'        => $media,
                'docs'         => $files
            ];
            //checks for duplicates
            $uuid  = $meta['uuid'];
            $found = current(
                array_filter($contents, function ($item) use ($uuid) {
                    return isset($item['uuid']) && $uuid == $item['uuid'];
                })
            );

            // if uuid is not present, add it
            if (!$found) {
                array_push($contents, $page);
            }
        }
        $collection = collect($contents);
        $sorted     = $collection->sortBy([
            ['id', 'desc'],
        ]);
        $sorted->values()->all();
        return $sorted;
    }
}