<?php

declare(strict_types=1);

namespace app\utils;

class ParsedownExtension extends \Parsedown
{
    protected $isTocEnabled = false;

    protected $rawTocList = [];

    protected $findTocSyntaxRule = '#^<p> *\[TOC\]\s*</p>$#m';

    public function setTocEnabled($isTocEnable)
    {
        $this->isTocEnabled = $isTocEnable;

        return $this;
    }

    public function setTocSyntaxRule($findTocSyntaxRule)
    {
        $this->findTocSyntaxRule = $findTocSyntaxRule;

        return $this;
    }

    public function text($text)
    {
        $content = parent::text($text);
        
        if (!$this->isTocEnabled || empty($this->rawTocList) || !preg_match($this->findTocSyntaxRule, $content)) {
            return ["toc"=>"","content"=>$content];
        }

        $content = preg_replace($this->findTocSyntaxRule, "", $content);
        return ["toc"=>$this->buildToc(), "content"=>$content];
    }

    protected function buildToc()
    {
        $tocMarkdownContent = '';
        $topHeadLevel       = min(array_column($this->rawTocList, 'level'));

        foreach ($this->rawTocList as $id => $tocItem) {
            $tocMarkdownContent .= sprintf('%s- [%s](#%s)' . PHP_EOL, str_repeat('  ', $tocItem['level'] - $topHeadLevel), $this->line($tocItem['text']), $tocItem['id']);
        }

        return parent::text($tocMarkdownContent);
    }

    protected function blockHeader($line)
    {
        $block = parent::blockHeader($line);
        $text  = $block['element']['handler']['argument'];
        $no = 0;
        foreach ($this->rawTocList as $key => $value) {
            if ($text == $value['text']) {
                $no = $value['no'] + 1;
            }
        }
        
        $id = urlencode($this->line($text));
        
        if ($no != 0) {
            $id .= '-' . $no;
        }
        
        $block['element']['attributes'] = [
            'id' => $id,
        ];

        $this->rawTocList[] = [
            'id' => $id,
            'text'  => $text,
            'level' => str_replace('h', '', $block['element']['name']),
            'no'=> $no,
        ];

        return $block;
    }
}