<?php

/**
 * Class View
 * The part that handles all the output
 */
class View
{
    /* Resolve all the deprecation errors happening in the views, since they cant be disabled by error_reporting level in 8.4.*/
    public $redirect;
    public $users;
    public $notes;
    public $user_name;
    public $user_email;
    public $user_gravatar_image_url;
    public $user_avatar_file;
    public $avatar_file_path;
    public $user_account_type;
    
    /* Messenger properties */
    public $conversations;
    public $unread_count;
    public $all_users;
    
    /* Note properties */
    public $messages;
    public $other_user;

    /* Group properties */
    public $groups;

    /* Database Manager properties */
    public $databases;
    public $database_name;
    public $current_db;
    public $tables;
    public $table_name;
    public $table_info;
    public $columns;
    public $rows;
    public $indexes;
    public $total_rows;
    public $current_page;
    public $per_page;
    public $history;
    public $user;
    public $privileges;
    public $current_user;

    /* Gallery properties */
    public $images;
    public $total_images;
    public $image;

    /**
     * Static property to track if header has been rendered
     */
    private static $header_rendered = false;

    /**
     * simply includes (=shows) the view. this is done from the controller. In the controller, you usually say
     * $this->view->render('help/index'); to show (in this example) the view index.php in the folder help.
     * Usually the Class and the method are the same like the view, but sometimes you need to show different views.
     * @param string $filename Path of the to-be-rendered view, usually folder/file(.php)
     * @param array $data Data to be used in the view
     */
    public function render($filename, $data = null)
    {
        if ($data) {
            foreach ($data as $key => $value) {
                $this->{$key} = $value;
            }
        }

        if (!self::$header_rendered) {
            self::$header_rendered = true;
            
            require Config::get('PATH_VIEW') . '_templates/header.php';
            require Config::get('PATH_VIEW') . $filename . '.php';
            require Config::get('PATH_VIEW') . '_templates/footer.php';
        } else {
            require Config::get('PATH_VIEW') . $filename . '.php';
        }
    }

    /**
     * Similar to render, but accepts an array of separate views to render between the header and footer. Use like
     * the following: $this->view->renderMulti(array('help/index', 'help/banner'));
     * @param array $filenames Array of the paths of the to-be-rendered view, usually folder/file(.php) for each
     * @param array $data Data to be used in the view
     * @return bool
     */
    public function renderMulti($filenames, $data = null)
    {
        if (!is_array($filenames)) {
            self::render($filenames, $data);
            return false;
        }

        if (!self::$header_rendered) {
            self::$header_rendered = true;
            
            if ($data) {
                foreach ($data as $key => $value) {
                    $this->{$key} = $value;
                }
            }

            require Config::get('PATH_VIEW') . '_templates/header.php';
        }

        foreach($filenames as $filename) {
            require Config::get('PATH_VIEW') . $filename . '.php';
        }

        require Config::get('PATH_VIEW') . '_templates/footer.php';
    }

    /**
     * Same like render(), but does not include header and footer
     * @param string $filename Path of the to-be-rendered view, usually folder/file(.php)
     * @param mixed $data Data to be used in the view
     */
    public function renderWithoutHeaderAndFooter($filename, $data = null)
    {
        if ($data) {
            foreach ($data as $key => $value) {
                $this->{$key} = $value;
            }
        }

        require Config::get('PATH_VIEW') . $filename . '.php';
    }

    /**
     * Renders pure JSON to the browser, useful for API construction
     * @param $data
     */
    public function renderJSON($data)
    {
        header("Content-Type: application/json");
        echo json_encode($data);
    }

    /**
     * Render a view using the database manager layout
     * @param string $filename Path of the to-be-rendered view
     * @param array $data Data to be used in the view
     */
    public function renderDbManager($filename, $data = null)
    {
        if ($data) {
            foreach ($data as $key => $value) {
                $this->{$key} = $value;
            }
        }

        require Config::get('PATH_VIEW') . '_templates/dbmanager_header.php';
        require Config::get('PATH_VIEW') . $filename . '.php';
        require Config::get('PATH_VIEW') . '_templates/dbmanager_footer.php';
    }
    
    /**
     * Reset header render flag at start of request
     */
    public static function resetHeaderRendered()
    {
        self::$header_rendered = false;
    }

    /**
     * renders the feedback messages into the view
     */
    public function renderFeedbackMessages()
    {
        // echo out the feedback messages (errors and success messages etc.),
        // they are in $_SESSION["feedback_positive"] and $_SESSION["feedback_negative"]
        require Config::get('PATH_VIEW') . '_templates/feedback.php';

        // delete these messages (as they are not needed anymore and we want to avoid to show them twice
        Session::set('feedback_positive', null);
        Session::set('feedback_negative', null);
    }

    /**
     * Checks if the passed string is the currently active controller.
     * Useful for handling the navigation's active/non-active link.
     *
     * @param string $filename
     * @param string $navigation_controller
     *
     * @return bool Shows if the controller is used or not
     */
    public static function checkForActiveController($filename, $navigation_controller)
    {
        $split_filename = explode("/", $filename);
        $active_controller = $split_filename[0];

        if ($active_controller == $navigation_controller) {
            return true;
        }

        return false;
    }

    /**
     * Checks if the passed string is the currently active controller-action (=method).
     * Useful for handling the navigation's active/non-active link.
     *
     * @param string $filename
     * @param string $navigation_action
     *
     * @return bool Shows if the action/method is used or not
     */
    public static function checkForActiveAction($filename, $navigation_action)
    {
        $split_filename = explode("/", $filename);
        $active_action = $split_filename[1];

        if ($active_action == $navigation_action) {
            return true;
        }

        return false;
    }

    /**
     * Checks if the passed string is the currently active controller and controller-action.
     * Useful for handling the navigation's active/non-active link.
     *
     * @param string $filename
     * @param string $navigation_controller_and_action
     *
     * @return bool
     */
    public static function checkForActiveControllerAndAction($filename, $navigation_controller_and_action)
    {
        $split_filename = explode("/", $filename);
        $active_controller = $split_filename[0];
        $active_action = $split_filename[1];

        $split_filename = explode("/", $navigation_controller_and_action);
        $navigation_controller = $split_filename[0];
        $navigation_action = $split_filename[1];

        if ($active_controller == $navigation_controller AND $active_action == $navigation_action) {
            return true;
        }

        return false;
    }

    /**
     * Checks if the passed array of controllers contains the currently active controller.
     * Useful for navigation items that span multiple controllers (e.g., database manager).
     *
     * @param string $filename
     * @param array $controllers Array of controller names to check
     *
     * @return bool Shows if any of the controllers is active
     */
    public static function checkForActiveControllers($filename, $controllers)
    {
        foreach ($controllers as $controller) {
            if (self::checkForActiveController($filename, $controller)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Converts characters to HTML entities
     * This is important to avoid XSS attacks, and attempts to inject malicious code in your page.
     *
     * @param  string $str The string.
     * @return string
     */
    public function encodeHTML($str)
    {
        return htmlentities($str, ENT_QUOTES, 'UTF-8');
    }
}
