<?php

abstract class Controller
{
    protected $registry;
    protected $id;
    protected $layout;
    protected $template;
    protected $children = array();
    protected $childrenData = array();
    protected $data = array();
    protected $output;
    protected $db;

    public function __construct($registry)
    {
        $this->registry = $registry;
        $this->db = $registry->get('db');
    }

    public function __get($key)
    {
        return $this->registry->get($key);
    }

    public function __set($key, $value)
    {
        $this->registry->set($key, $value);
    }

    protected function forward($route, $args = array())
    {
        return new Action($route, $args);
    }

    protected function redirect($url, $status = 302)
    {
        header('Status: ' . $status);
        header('Location: ' . str_replace(array('&amp;', "\n", "\r"), array('&', '', ''), $url));
        exit();
    }

    protected function getChildData($child, $args = array(), $json = false)
    {
        $action = new Action($child, $args);

        if (file_exists($action->getFile())) {
            require_once($action->getFile());

            $class = $action->getClass();

            $controller = new $class($this->registry);

            $controller->{$action->getMethod()}($action->getArgs());

            if (!$json) {
                return $controller->data;
            } else {
                return json_encode($controller->data);
            }
        }
    }

    protected function getChild($child, $args = array())
    {
        $action = new Action($child, $args);

        if (file_exists($action->getFile())) {
            require_once($action->getFile());

            $class = $action->getClass();

            $controller = new $class($this->registry);

            $controller->{$action->getMethod()}($action->getArgs());

            return $controller->output;
        } else {

            /*Função para deletar da oc_extension o modulo caso não ache o arquivo dele nas pastas
            caso o arquivo com erro não faça parte dos tipos listados no array a baixo ele exibira a mensagem
            padrão do opencart - by Dionis Mendanha*/

            $arrayType = array('module', 'payment', 'shipping', 'total');
            $file = explode('/', $child);

            $ignoremodule = array('descontoacrescimokit');/* Módulos que não possuem controler */

            if (!in_array($file[1], $ignoremodule)) {
                if (in_array($file[0], $arrayType)) {
                    $this->db->query("DELETE FROM `" . DB_PREFIX . "extension` WHERE code='" . $file[1] . "'");
                } else {
                    trigger_error('Error: Could not load controller ' . $child . '!');
                    exit();
                }
            }
        }
    }

    protected function hasAction($child, $args = array())
    {
        $action = new Action($child, $args);

        if (file_exists($action->getFile())) {
            require_once($action->getFile());

            $class = $action->getClass();

            $controller = new $class($this->registry);

            if (method_exists($controller, $action->getMethod())) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    protected function render($templateRoute = null)
    {
        foreach ($this->children as $child) {
            $this->data[basename($child)] = $this->getChild($child);
        }

        foreach ($this->childrenData as $child => $data) {
            $this->data[basename($child)] = $this->getChildData($child, $data);
        }

        $templateController = new TemplateController($this->registry);

        if ((isset($templateRoute)) && ($templateRoute != null)) {
            $this->template = $templateController->getTemplateRoute($templateRoute);
        }

        // variavel pra ser usada em qualquer tela
        $this->data['ambiente_teste'] = (defined('AMBIENTE_TESTE') && AMBIENTE_TESTE);

        $this->output = $templateController->loadOutPut($this->template, $this->data);
        return $this->output;
    }
}
