<?php

namespace Mtc\Cms\Handlers;

use \Illuminate\Support\Facades\App;
use \Page;
use \Pagedata;

/**
 * Template Handler Class
 * Template Handler Class responsible for handling the templates, thier structures and their controllers
 * @author Rihards Silins
 * @copyright MTC Media Ltd
 * @version 2 14/07/2017
 * @access public
 */
class TemplateHandler
{
    /**
     * Get template structure filename based off of template filename
     * @param string $template_filename
     * @return string $structure_filename
     */
    public static function getStructureFilename($template_filename)
    {
        return str_replace('.twig', '.json', $template_filename);
    }

    /**
     * Get structure contents from the correct twig inheritance directory
     * @param string $structure_filename
     * @param Twig Loader Object $twig_loader
     * @return mixed[] $result
     */
    public static function getStructure($structure_filename, $twig_loader)
    {
        // get the most current structure file
        foreach ($twig_loader->getPaths() as $twig_path) {
            $temp_structure_filename_full_path = $twig_path.'/structures/'.$structure_filename;
            if (file_exists($temp_structure_filename_full_path)) {
                $structure_filename_full_path = $temp_structure_filename_full_path;
                break;
            }
        }

        if (empty($structure_filename_full_path)) {
            return [
                'result' => false,
                'message' => 'No structure file for this template found!',
            ];
        }

        $structure = file_get_contents($structure_filename_full_path);

        if (empty($structure)) {
            return [
                'result' => false,
                'message' => 'Structure file ('.$structure_filename_full_path.') empty or unable to be opened!',
            ];
        }

        $structure = json_decode($structure, true);

        if ($structure === false || $structure === null || ! isset($structure['pagedata'])) {
            return [
                'result' => false,
                'message' => 'Structure file ('.$structure_filename_full_path.') structure corrupt!',
            ];
        }

        return [
            'result' => true,
            'message' => 'Success!',
            'structure' => $structure,
            'structure_full_path' => $structure_filename_full_path,
        ];
    }

    /**
     * Checks if filesname is a valid template filename
     * @param string $filename
     * @return bool
     */
    public static function validTemplateFilename($filename)
    {
        return preg_match("/^[a-zA-Z0-9\._-]+$/", $filename) === 1;
    }

    /**
     * Checks if page strcture is in sync with it's template
     * @param Page $page
     * @param Twig_Loader $twig_loader
     * @return bool
     */
    public static function isStructureSaved(Page $current_page, $twig_loader)
    {
        $structure = self::getStructure(self::getStructureFilename($current_page->template), $twig_loader);
        if ($structure['result'] == false) {
            return false;
        }
        $pagedata = new Pagedata;
        $result = $pagedata->get($current_page->id, 0, 0, 0, false, true);

        // wrap it in a structure that can describe what it is
        $current_page_structure = array(
            'action' => 'add_pagedata_structure',
            'pagedata' => Pagedata::removeDefaultData($pagedata->pagedata),
        );

        return $current_page_structure == $structure['structure'];
    }

    /**
     * Retrieves the most accurate template name.
     * @param string $template_filename Template filename of which you need the name.
     * @return string Template name. If there's none set it returns given filename
     */
    public static function getTemplateName($template_filename)
    {
        $twig_loader = App::make('twig')->getLoader();

        // get the most current structure file
        foreach ($twig_loader->getPaths() as $twig_path) {
            $template_filename_full_path = $twig_path.'/pages/'.$template_filename;
            if (file_exists($template_filename_full_path)) {
                break;
            } else {
                $template_filename_full_path = null;
            }
        }

        $template_name_from_file = TemplateHandler::readFileAndMatchTemplateName($template_filename_full_path);
        if ($template_name_from_file === null) {
            $template_name = $template_filename;
        } else {
            $template_name = $template_name_from_file;
        }

        return $template_name;
    }

    /**
     * Reads template file and tries to match a template name within. Returns null if unable.
     * @param string $template_filename_full_path Template filename full path of which you need the name.
     * @return string|null Template name, if there's none set it returns null.
     */
    public static function readFileAndMatchTemplateName($template_filename_full_path)
    {
        if (is_readable($template_filename_full_path)) {
            $file_handler = fopen($template_filename_full_path, 'r');
            $first_line = fgets($file_handler);
            preg_match('/^{# Template : ([^(#})]+) #}/', $first_line, $matches);
            fclose($file_handler);
            if (! empty($matches[1])) {
                return $matches[1];
            }
        }

        return null;
    }
}
