<?php

Goweb::loadClass('Goweb_Controller_Action');
Goweb::loadClass('Goweb_View');

/**
 * Goweb Sitemanager 5 Framework
 * @version    5.0.0
 * @category   Frontoffice
 * @package    Form
 * @subpackage Controller
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 *
 * A classe _Controller para o Front-Office disponibiliza
 * as accoes referentes a cada Modulo.
 *
*/
class Form_GenericController extends Goweb_Controller_Action {
    
    /**
     * Objecto Form_Model_Form
     *
     * @var Form_Model_Form
    */
    protected $_formModel = null;
    
    /**
     * Objecto Form_Model_Element
     *
     * @var Form_Model_Element
    */
    protected $_elementModel = null;
    
    /**
     * Objecto Goweb_Config_Ini
     *
     * @var Goweb_Config_Ini
    */
    protected $_moduleConfig = null;
    
    /**
     * Mensagem de erro
     *
     * @var string
    */
    protected $_error = null;
    
    /**
     * Mensagem de sucesso
     *
     * @var string
    */
    protected $_message = null;
    
    /**
     * Construtor da Classe
    */
    public function init() {
        $this->_moduleConfig = new Goweb_Config(Goweb_Config_Ini::load(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.ini', 'base'));
        $this->view->setViewsPath(VIEWS_PATH . DIRECTORY_SEPARATOR . 'Form');        
        $this->_formModel = Goweb::getModelInstance('Form_Model_Form', 'db');
        $this->_elementModel = Goweb::getModelInstance('Form_Model_Element', 'db');
    }
    
    /**
     * Acao executada se nenhuma outra acao for especificada
    */
    public function indexAction() {
        return $this->_forward('view');
    }
    
    /**
     * Acao para visualizar um determinado formulario
    */
    public function viewAction() {
        $id = $this->_getParam('id');
        $this->view->form = false;
        if (!$this->_validateId($id) || !$this->_formModel->find($id)) {
            return false;
        }
        $form = $this->_getForm($id);
        $form->render();
        $this->view->form_id = $id;
        $this->view->form = $form;
        $this->view->model = $this->_getFormModel($id);
        $this->view->error = $this->_error;
        $this->view->message = $this->_message;
        if ($this->_directRequest) { // significa que foi chamado directamente.
            Goweb::loadClass('Cms_Controller', APPLICATION_PATH);
            Cms_Controller::renderOutput($this->view,
                                        'view.tpl',
                                        'Form',
                                        'form-id-' . $this->_formModel->id,
                                        translate(html_entity_decode('Formul&aacute;rio: {{titulo}}', ENT_NOQUOTES, CHARSET), $this->_formModel->titulo));
            $this->_helper->viewRenderer->setRender('base');
        }
    }
    
    /**
     * Accao para visualizar um formulario em formato pop-up
    */
    public function viewPopupAction() {
        $id = $this->_getParam('id');
        if (!$this->_validateId($id) || !$this->_formModel->find($id)) {
            return false;
        }
        $form = $this->_getForm($id);
        $form->render();
        $this->view->form_id = $id;
        $this->view->model = $this->_getFormModel($id);
        $action = $form->getAction();
        $form->setAction($action . 'popup/1/');
        $this->view->form = $form;
        $this->view->error = $this->_error;
        $this->view->message = $this->_message;
    }
    
    /**
     * Accao para inserir um link de para um formulario abrir em popup
    */
    public function formPopupAction() {
        $id = $this->_getParam('id');
        if (!$this->_validateId($id) || !$this->_formModel->find($id)) {
            return false;
        }
        $this->view->form_name = $this->_formModel->titulo;
        
        $height = $this->_getParam('height');
        if (!$height || !$this->_validateId($height)) {
            $height = 400;
        }
        $this->view->height = $height;
        
        $width = $this->_getParam('width');
        if (!$width || !$this->_validateId($width)) {
            $width = 450;
        }
        $this->view->width = $width;
        
        $this->view->action = Goweb::link('/form/view_popup/id/' . $id);
        
        if ($this->_directRequest) { // significa que foi chamado directamente.
            Goweb::loadClass('Cms_Controller', APPLICATION_PATH);
            Cms_Controller::renderOutput($this->view,
                                        'link_popup.tpl',
                                        'Form',
                                        'form-id-' . $this->_formModel->id,
                                        translate('Formul&aacute;rio: {{titulo}}', $this->_formModel->titulo));
            $this->_helper->viewRenderer->setRender('base');
        } else {
            $this->_helper->viewRenderer->setRender('link_popup');
        }
    }
    
    /**
     * Acao que processa o envio de um formulario
    */
    public function submitAction() {
        $id = $this->_getParam('id');
        if (!$this->_request->isPost() || !$this->_validateId($id) || !$this->_formModel->find($id)) {
            $this->_helper->viewRenderer->setNoRender();
            return false;
        }
        
        $formTitulo          = $this->_formModel->titulo;
        $formMensagemSucesso = $this->_formModel->mensagem_sucesso;
        $formSubmitEmail     = $this->_formModel->email;
        
        $form = $this->_getForm($id);
        
        if ($this->_getParam('popup')) {
            $action = $form->getAction();
            $form->setAction($action . 'popup/1/');
        }
        
        if (!$form->validate()) {
            if (count($form->getErrorMessages()) > 1) {
                $this->_error = translate('Corrija por favor os erros no formul&aacute;rio');
            } else {
                $this->_error = translate('Corrija por favor o erro no formul&aacute;rio');
            }
        } else {
            $this->_formModel->submissoes += 1;
            $this->_formModel->save();
            
            // grava na base de dados
            $model = $this->_getFormModel($id);
            $model->form_id = $id;
            
        foreach ($form->getElementsNames() as $element) {
             if (!$model->colExists($element)) continue;
             $value = $form->{$element}->value;
             if (is_array($form->{$element}->value)) {
                    $model->{$element} = serialize($form->{$element}->value);
                } else if ($form->{$element}->type == 'file' && $value != '') {
                    // fazer o upload do ficheiro
                        $upload_path = WWW_PATH . $this->_moduleConfig->files->target;
                        if (!file_exists($upload_path)) {
                            mkdir($upload_path);
                            chmod($upload_path, 0777);
                        } elseif ((!is_readable($upload_path)) || (!is_writable($upload_path))) {
                            try {
                                chmod($upload_path, 0755);
                            } catch (Exception $e) {
                                throw new Exception("N&atilde;o foi poss&iacute;vel atribuir permiss&otilde;es a pasta '$upload_path'");
                            }
                        }
                        try {
                            if (!$form->{$element}->isReceived() && !$form->{$element}->receive()) {
                                throw new Goweb_Exception("Ocorreu um erro a gravar o ficheiro");
                            }

                        } catch (Exception $e) {
                            throw new Goweb_Exception("Ocorreu um erro a gravar o ficheiro: " . $e->getMessage() . ' (linha '. $e->getLine() . ')');
                        }
                        if (substr($upload_path, -1) != '/') $upload_path .= '/';
                        $filename = time() . '_' . $value;
                        rename($form->{$element}->getFileName(), $upload_path . $filename);
                        chmod($upload_path . $filename, 0777);
                        $model->{$element} = $filename;
                

                } else {
                    $model->{$element} = $form->{$element}->value;
                }
            }
            $model->save();

            // envia email
            if (strlen($formSubmitEmail)) {
                $config = Goweb::registry('config');
                
                Goweb::loadClass('Goweb_Mail');
                
                $mail = new Goweb_Mail();
                $customEmail = false;
                if ($this->_elementModel->colExists('email')){
                    foreach ($form->getElementsNames() as $elementId){
                        $elementId = str_replace('element_', '', $elementId);
                        if ($this->_elementModel->find($elementId)){
                            if ($this->_elementModel->email){
                                /**
                                 * Pode ter mais do que um email no mesmo formul&aacute;rio
                                 */
                                if ($customEmail){
                                    $mail->addCc($form->{'element_' . $elementId}->value);
                                } else {
                                    $mail->addTo($form->{'element_' . $elementId}->value);
                                }
                                $customEmail = true;
                            }
                        }
                    }
                }
                if ($customEmail){
                    $mail->addCc($formSubmitEmail, $config->mail->to_name);
                } else {
                    $mail->addTo($formSubmitEmail, $config->mail->to_name);
                }
                $mail->setSubject(html_entity_decode($formTitulo, ENT_NOQUOTES, CHARSET));

                $this->view->config = Goweb::registry('config');
                $this->view->url_base = $this->view->baseUrl;
                $this->view->form = $form;
                $this->view->model = $model->getRow();
                $mail->setBodyHtml($this->view->render('email.tpl'));
                
                try {                    
                    $mail->send();
                } catch (Exception $e) {
                    // nao faz nada
                }
            }
            $this->_message = $formMensagemSucesso;
            
            $this->view->message = $this->_message;
            
            if ($this->_getParam('popup') == '1') {
                $this->view->link = Goweb::link('/form/view_success/id/' . $id);
                $this->_helper->viewRenderer->setRender('success_popup');
            } else {
                Goweb::loadClass('Cms_Controller', APPLICATION_PATH);
                Cms_Controller::renderOutput($this->view,
                                             'success.tpl',
                                             'Form',
                                             'form-success-id-' . $id,
                                             $formTitulo);
                $this->_helper->viewRenderer->setRender('base');
            }
            return true;
        }
        
        $form->render();
        $this->view->form = $form;
        $this->view->error = $this->_error;
        $this->view->message = $this->_message;
        
        if ($this->_getParam('popup') == '1') {
            $this->_helper->viewRenderer->setRender('view_popup');
        } else {
            Goweb::loadClass('Cms_Controller', APPLICATION_PATH);
            Cms_Controller::renderOutput($this->view,
                                         'view.tpl',
                                         'Form',
                                         'form-submit-id-' . $id,
                                         $formTitulo);
            $this->_helper->viewRenderer->setRender('base');
        }
    }
    
    /**
     * Resposta ao utilizador de envio bem sucedido de formulario
     * do tipo popup
    */
    public function viewSuccessAction() {
        $id = $this->_getParam('id');
        if (!$this->_validateId($id) || !$this->_formModel->find($id)) {
            return false;
        }
        
        $formTitulo          = $this->_formModel->titulo;
        $formMensagemSucesso = $this->_formModel->mensagem_sucesso;
        $this->_message = $formMensagemSucesso;
        $this->view->message = $this->_message;
        
        Goweb::loadClass('Cms_Controller', APPLICATION_PATH);
        Cms_Controller::renderOutput($this->view,
                                     'success.tpl',
                                     'Form',
                                     'form-success-id-' . $id,
                                     $formTitulo);
        $this->_helper->viewRenderer->setRender('base');
    }
    
    /**
     * Funcao auxiliar que devolve um formulario
     * 
     * @param integer
     *
     * @return Goweb_Form
    */
    protected function _getForm($formId) {
        Goweb::loadClass('Form_Barebone', dirname(__FILE__));
        $form = new Form_Barebone('form_' . $formId, '/form/submit/id/' . $formId . '/');
        $form->setup($formId);
        if ($this->_formModel->colExists('with_captcha') && $this->_formModel->find($formId) && $this->_formModel->with_captcha){
            $baseUrl = str_replace(array('/admin', '/index.php'), '', Zend_Controller_Front::getInstance()->getBaseUrl());
            goweb::loadClass('Goweb_Form_Element_Captcha');
            $captcha = new Goweb_Form_Element_Captcha('verificacao', array(
                        'label' => translate("Por favor introduza o c&oacute;digo na imagem"),
                        'captcha' => 'Image',
                        'captchaOptions' => array(
                            'captcha' => 'Image',
                            'wordLen' => 6,
                            'timeout' => 300,
                            'font' => ROOT_PATH . '/Ubuntu-Title.ttf',
                            'imgurl' => $baseUrl . '/uploads/captcha',
                            'imgDir' => WWW_PATH . '/uploads/captcha',
                            'dotNoiseLevel' => 8,  
                            'lineNoiseLevel' => 4 
                        )));
            $form->addElement($captcha);
            $form->verificacao->setAttrib('onblur','this.parentNode.parentNode.className=""');
            $form->verificacao->setAttrib('onfocus','this.parentNode.parentNode.className="form_field_active"');
        }
        
        return $form;
    }
    
    /**
     * Funcao auxiliar que devolve o model de um formulario
     *
     * @param integer
     *
     * @return Form_Model_Barebone
    */
    protected function _getFormModel($formId) {
        Goweb::loadModel('Form_Model_Barebone');
        $bareboneModel = new Form_Model_Barebone($this->_formModel->getAdapter());        
        $bareboneModel->setup($formId);
        return $bareboneModel;
    }
    
    /**
     * Acao executada se a acao chamada nao existir neste modulo
     *
     * @param string
     * @param array
    */
    public function __call($action, $arguments) {
        if('Action' == substr($action, -6)) {
            $this->_forward('view', 'form');
        } else {
            throw new Goweb_Exception("A fun&ccedil;&atilde;o n&atilde;o existe em ". get_class($this));
        }
    }
}
