<?php

namespace CCDN\Helpers;

use Exception;
use Throwable;

class Controller
{

    /**
     * Individual controller views folder path
     *
     * @var string|null
     */
    protected $viewsFolder;
    /**
     * @var string
     */
    private $rootViewsFolder = Settings::VIEWS_PATH;

    /**
     * Renders a view file as a PHP script.
     *
     * @param       $viewName
     * @param  array  $param
     *
     * @return string
     */
    public function render($viewName, array $param = [])
    {
        try {
            return $this->_renderTemplate($viewName, $param);
        } catch (Throwable $e) {
            return $e->getMessage();
        }
    }

    /**
     * Renders a view file as a PHP script.
     *
     * This method treats the view file as a PHP script and includes the file.
     * It extracts the given parameters and makes them available in the view file.
     * The method captures the output of the included view file and returns it as a string.
     *
     * This method should mainly be called by view renderer or [[renderFile()]].
     *
     * @param  string  $_file_  the view file.
     * @param  array  $_params_  the parameters (name-value pairs) that will be extracted and made available in the view file.
     *
     * @return string the rendering result
     * @throws Exception
     * @throws Throwable
     */
    private function _renderTemplate($_file_, array $_params_ = [])
    {
        if (!empty($this->viewsFolder)) {
            $this->viewsFolder = trim($this->viewsFolder, '/').'/';
        }
        $_file_ = rtrim($_file_, '.php');

        $_file_ = $this->rootViewsFolder.$this->viewsFolder.$_file_.'.php';

        $_obInitialLevel_ = ob_get_level();
        ob_start();
        ob_implicit_flush(false);
        extract($_params_, EXTR_OVERWRITE);
        try {
            require $_file_;

            return ob_get_clean();
        } catch (Exception $e) {
            while (ob_get_level() > $_obInitialLevel_) {
                if (!@ob_end_clean()) {
                    ob_clean();
                }
            }
            throw $e;
        } catch (Throwable $e) {
            while (ob_get_level() > $_obInitialLevel_) {
                if (!@ob_end_clean()) {
                    ob_clean();
                }
            }
            throw $e;
        }
    }
}
