<?php
/**
 * 2014 - 2015 Watt Is It
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 * @author    PayGreen <contact@paygreen.fr>
 * @copyright 2014-2014 Watt It Is
 * @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PrestaShop SA
 */

class Paygreen extends PaymentModule
{

    const _CONFIG_PRIVATE_KEY = '_PG_CONFIG_PRIVATE_KEY';
    const _CONFIG_SHOP_TOKEN = '_PG_CONFIG_SHOP_TOKEN';
    const _CONFIG_SHOP_INPUT_METHOD = '_PG_CONFIG_SHOP_INPUT_METHOD';
    const _CONFIG_PAIEMENT_ACCEPTED = '_PG_PAIEMENT_ACCEPTED';
    const _CONFIG_PAIEMENT_REFUSED = '_PG_PAIEMENT_REFUSED';
    const _CONFIG_CANCEL_ACTION = '_PG_CANCEL_ACTION';
    const _CONFIG_VISIBLE = '_PG_VISIBLE';
    const _CONFIG_ORDER_AUTH = '_PG_ORDER_AUTH_OK';
    const _CONFIG_ORDER_TEST = '_PG_ORDER_AUTH_TEST';
    const _CONFIG_PAYMENT_REFUND = '_PG_CONFIG_PAYMENT_REFUND';
    const _CONFIG_FOOTER_DISPLAY = '_PG_CONFIG_FOOTER_DISPLAY';
    const _CONFIG_FOOTER_LOGO_COLOR = '_PG_CONFIG_FOOTER_LOGO_COLOR';
    const _CONFIG_VERIF_ADULT = '_PG_CONFIG_VERIF_ADULT';

    const ERROR_TYPE_BUYER = 1;
    const ERROR_TYPE_MERCHANT = 2;
    const ERROR_TYPE_UNKNOWN = 3;

    const RS_VALID_SIMPLE = 'valid';
    const RS_VALID_WALLET = 'wallet';
    const RS_SUBSCRIBE_REDIRECT = 'rec_redirect';
    const RS_RECURRING_APPROVED = 'rec_approved';

    public $is_preprod = 0;
    public $a_errors = null;
    public $base_url = null;

    protected $a_model_buttons = array(
        "id" => 0,
        "label" => null,
        "image" => null,
        "position" => null,
        "height" => null,
        "displayType" => null,
        "nbPayment" => 1,
        "reportPayment" => 0,
        "minAmount" => null,
        "maxAmount" => null,
        "executedAt" => 0
    );

    protected $config_form = false;
    protected $id_index = 1250;

    protected $logger;

    public function __construct()
    {
        require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'PaygreenApiClient.php');
        require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'PaygreenClient.php');

        $this->name = 'paygreen';
        $this->tab = 'payments_gateways';
        $this->version = '1.3.9';
        $this->author = 'Watt Is It';
        $this->need_instance = 1;
        $this->module_key = '0403f32afdc88566f1209530d6f6241c';

        $this->bootstrap = true;

        if (Module::isInstalled($this->name)) {
            $this->warning = $this->verifyConfiguration(true);
            $this->warning = $this->verifyConfigurationNotImportant();
        }

        parent::__construct();

        $this->displayName = $this->l('PayGreen');
        $this->description = $this->l('Frenchy and solidary online payment system');

        $this->logger = new FileLogger(0);
        $this->logger->setFilename(dirname(__FILE__) . '/lib/debug.log');

        $this->createOrderStatuses();

        PaygreenApiClient::setHost($this->getPaygreenConfig('host'));
    }

    protected function log($identifier, $data)
    {
        $this->logger->logDebug('|' . microtime(true) . '|' . $identifier . '|' . Tools::jsonEncode($data));
    }

    public function getPaygreenConfig($attr = null)
    {
        $config = $this->getConfig();
        $host = null;
        $token = $config[self::_CONFIG_SHOP_TOKEN];
        $type = Tools::substr($token, 0, 2);
        
        if ($type == 'PP') {
            $host = 'http://preprod.paygreen.fr';
            $token = Tools::substr($token, 2);
            
        } elseif ($this->isPreprod()) {
            $host = 'http://preprod.paygreen.fr';
            $type = 'PP';

        } elseif ($type == 'LC') {
            $host = 'http://local.paygreen.fr';
            $token = Tools::substr($token, 2);
        } else {
            $type = 'P';
            $host = 'https://paygreen.fr';
        }

        $data = array(
            'token' => $token,
            'privateKey' => $config[self::_CONFIG_PRIVATE_KEY],
            'host' => $host,
            'type' => $type
        );
        if (empty($attr)) {
            return $data;
        } else {
            return $data[$attr];
        }
    }

    public function getCaller()
    {
        $config = $this->getPaygreenConfig();

        $paiement = new PaygreenClient($config['privateKey'], $config['host']);
        $paiement->setToken($config['token']);

        return $paiement;
    }

    //version_compare
    protected function verifyConfigurationNotImportant()
    {
        $warning = '';
        $content = @Tools::file_get_contents('https://paygreen.fr/ressources/documentation/module/prestashop.json');

        if (Tools::strlen($content) > 1) {
            $versions = Tools::jsonDecode($content);
            $curVersion = Tools::substr(_PS_VERSION_, 0, 3);

            if (property_exists($versions, $curVersion)) {
                $serverVersion = $versions->$curVersion;

                if (version_compare($this->version, $serverVersion) < 0) {
                    $string = 'A new version of the module is available,';
                    $string .= 'please visit paygren.fr to recover.';
                    $warning .= ' - ' . $this->l($string);
                }
            }
        }
    }

    protected function verifyConfiguration($checkBtnConfig = false)
    {
        $config = $this->getConfig();
        $warning = '';

        if (empty($config[self::_CONFIG_PRIVATE_KEY]) || empty($config[self::_CONFIG_SHOP_TOKEN])) {

            $warning = $this->l('Missing parameters') . ' :';
            if (empty($config[self::_CONFIG_PRIVATE_KEY])) {
                $warning .= ' - ' . $this->l('Private key');
            }
            if (empty($config[self::_CONFIG_SHOP_TOKEN])) {
                $warning .= ' - ' . $this->l('Unique Identifier');
            }
        }
        if (!extension_loaded('mcrypt')) {
            $warning .= ' - ' . $this->l('PHP module \'mcrypt\' is required.');
        }


        // Verifications of button's parameters
        if ($checkBtnConfig) {

            $error_tmp = '';
            $nb_error = 0;

            foreach ($this->getButtonsList() as $btn) {
                if ($this->checkBtn($btn) != '') {
                    $nb_error++;
                    $error_tmp = $this->checkBtn($btn);
                }
            }
            if ($nb_error > 1) {
                $warning .= ' - ' . $this->l('There are errors of button\'s configuration');
            } else {
                $warning .= ($error_tmp == '') ? null : ' - ' . $error_tmp;
            }
        }

        return $warning;
    }

    /**
     * Don't forget to create update methods if needed:
     * http://doc.prestashop.com/display/PS16/Enabling+the+Auto-Update
     */
    public function install()
    {
        Configuration::updateValue(self::_CONFIG_PRIVATE_KEY, '');
        Configuration::updateValue(self::_CONFIG_SHOP_TOKEN, '');
        Configuration::updateValue(self::_CONFIG_SHOP_INPUT_METHOD, 'POST');
        Configuration::updateValue(self::_CONFIG_VISIBLE, 1);

        Configuration::updateValue(self::_CONFIG_PAIEMENT_ACCEPTED, $this->l('Your payment was accepted'));
        Configuration::updateValue(self::_CONFIG_PAIEMENT_REFUSED, $this->l('Your payment was unsuccessful'));

        Configuration::updateValue(self::_CONFIG_PAIEMENT_REFUSED, $this->l('Your payment was unsuccessful'));

        // Allow to refund with Paygreen
        Configuration::updateValue(self::_CONFIG_PAYMENT_REFUND, 0);
        // Footer Config
        Configuration::updateValue(self::_CONFIG_FOOTER_DISPLAY, 1);
        Configuration::updateValue(self::_CONFIG_FOOTER_LOGO_COLOR, 'white');
        Configuration::updateValue(self::_CONFIG_VERIF_ADULT, 0);
        Configuration::updateValue('oauth_access', '');
        include(dirname(__FILE__) . '/sql/install.php');

        // Add button paygreen in menu
        try {
            $tab_parent_id = Tab::getIdFromClassName('AdminParentModules');
            $tab = new Tab();
            $tab->class_name = 'AdminPaygreen';
            $tab->name[$this->context->language->id] = $this->l('Paygreen');
            $tab->id_parent = $tab_parent_id;
            $tab->module = $this->name;
            $tab->add();
        } catch (Exception $ex) {
            $tab = null;
        }
    
        return parent::install() &&
        $this->createOrderStatuses() &&
        $this->initializeDb() &&
        $this->registerHook('header') &&
        $this->registerHook('backOfficeHeader') &&
        $this->registerHook('displayPayment') &&
        $this->registerHook('displayPaymentReturn') &&
        $this->registerHook('postUpdateOrderStatus') &&
        $this->registerHook('ActionObjectOrderSlipAddAfter') &&
        $this->registerHook('postUpdateOrderStatus') &&
        $this->registerHook('displayFooter');
    }

    public function uninstall()
    {
        Configuration::deleteByName(self::_CONFIG_PRIVATE_KEY);
        Configuration::deleteByName(self::_CONFIG_SHOP_TOKEN);

        Configuration::deleteByName(self::_CONFIG_SHOP_INPUT_METHOD);
        Configuration::deleteByName(self::_CONFIG_VISIBLE);

        Configuration::deleteByName(self::_CONFIG_PAIEMENT_ACCEPTED);
        Configuration::deleteByName(self::_CONFIG_PAIEMENT_REFUSED);
        Configuration::deleteByName(self::_CONFIG_PAYMENT_REFUND);

        Configuration::deleteByName(self::_CONFIG_FOOTER_DISPLAY);
        Configuration::deleteByName(self::_CONFIG_FOOTER_LOGO_COLOR);
        Configuration::deleteByName(self::_CONFIG_VERIF_ADULT);


        $idTab = Tab::getIdFromClassName('AdminPaygreen');
        $tab = new Tab($idTab);
        $tab->delete();

        include(dirname(__FILE__) . '/sql/uninstall.php');

        return parent::uninstall();
    }

    /**
     * If connected
     * @return boolean true or false;
     */
    public function isConnected()
    {
        if (trim(Configuration::get(self::_CONFIG_PRIVATE_KEY)) == '') {
            return false;
        }
        if (trim(Configuration::get(self::_CONFIG_SHOP_TOKEN)) == '') {
            return false;
        }
        return true;
    }

    /**
    * If Preprof or not
    * @return true or false
    */
    public function isPreprod()
    {
        return $this->is_preprod;
    }

    /**
    * Return the Unique ID for API (remove PP)
    * @return String $token
    */
    public function getUniqueIdPP()
    {
        $token = Configuration::get(self::_CONFIG_SHOP_TOKEN);
        if (in_array(Tools::substr($token, 0, 2), array('PP', 'LC'))) {
            $token = Tools::substr($token, 2);
        }
        return $token;
    }

    /**
     * Load the configuration form
     */
    public function getContent()
    {
        // Configuration::deleteByName('oauth_access');
        $output = $this->postProcess();

        if (Configuration::get('URL_BASE')==null) {
            Configuration::updateValue('URL_BASE', 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
        }

        if (Tools::getValue("connect") == 'true' || Tools::getValue("code") != '') {
            if (extension_loaded('curl') || ini_get('allow_url_fopen')) {
                $this->auth();
            } else {
                $this->errorPaygreenApiClient((object) array('error' => 0));
            }
        }

        if (Tools::getValue('deconnect')) {
            if (Tools::getValue('deconnect') == 'true') {
                $this->logout();
            }
        }

        $buttonsList = $this->getButtonsList();
        array_push($buttonsList, $this->a_model_buttons);

        $len = count($buttonsList);

        foreach ($buttonsList as $key => $btn) {
            if ($key != $len - 1) {
                $buttonsList[$key]['error'] = ($this->checkBtn($btn) == '') ? null : $this->checkBtn($btn);
            }
        }

        $infoShop='';
        $infoAcccount='';

        if ($this->isConnected()) {
            if ($this->paygreenValidIds()) {

                $infoShop = PaygreenApiClient::getStatusShop(
                    $this->getUniqueIdPP(),
                    Configuration::get(self::_CONFIG_PRIVATE_KEY),
                    $this->isPreprod()
                );
                if ($infoShop != false) {
                    if (!$this->errorPaygreenApiClient($infoShop)) {
                        $infoShop = $infoShop->data;
                    }
                }


                $infoAcccount = PaygreenApiClient::getAccountInfos(
                    $this->getUniqueIdPP(),
                    Configuration::get(self::_CONFIG_PRIVATE_KEY),
                    $this->isPreprod()
                );
                if ($infoAcccount != false) {
                    $this->errorPaygreenApiClient($infoAcccount);
                }
            }
        }


        // Appel avec header location si on clique sur le bouton connecté
        $this->context->smarty->assign(array(
            'prestashop' => Tools::substr(_PS_VERSION_, 0, 3),
            'module_dir' => $this->_path,
            'connected' => $this->isConnected(),
            'urlBase' => Configuration::get('URL_BASE') . "&connect=true",
            'urlBaseDeconnect' => Configuration::get('URL_BASE') . "&deconnect=true",
            'request_uri' => $_SERVER['REQUEST_URI'],
            'buttons' => $buttonsList,
            'infoShop' => $infoShop,
            'infoAccount' => $infoAcccount,
            'imgdir' => $this->getImgDirectory("", true),
            'icondir' => $this->getIconDirectory("", true),
            // 'recurringPayments' => $this->getRecurringPayment(),
            'allowRefund' => Configuration::get(self::_CONFIG_PAYMENT_REFUND)
        ));

        // check version for templates
        $version = Tools::substr(_PS_VERSION_, 0, 3);

        $output .= $this->context->smarty->fetch(
            $this->local_path . 'views/templates/admin/' . $version . '/connectApi.tpl'
        );
        $output .= $this->renderForm();
        $this->context->controller->addJS($this->_path . 'views/js/' . $version . '/back.js');
        $this->context->controller->addCSS($this->_path . 'views/css/' . $version . '/back.css');

        return $output . $this->context->smarty->fetch(
            $this->local_path . 'views/templates/admin/' . $version . '/configureButtons.tpl'
        );
    }


    /**
     *  Authentication and full private key and unique id
     */
    private function auth()
    {
        $libOAuth =  DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'OAuth2' . DIRECTORY_SEPARATOR ;
        require_once(dirname(__FILE__) . $libOAuth . 'Client.php');
        require_once(dirname(__FILE__) . $libOAuth . 'GrantType' . DIRECTORY_SEPARATOR . 'IGrantType.php');
        require_once(dirname(__FILE__) . $libOAuth . 'GrantType' . DIRECTORY_SEPARATOR . 'AuthorizationCode.php');


        $ipAddress = $_SERVER['REMOTE_ADDR'];
        $email = $this->context->cookie->email;
        $name = Configuration::get('PS_SHOP_NAME');
        $oauth_access = Configuration::get('oauth_access');

        if (empty($oauth_access) || $oauth_access='null') {

            $datas = PaygreenApiClient::getOAuthServerAccess(
                $email,
                $name,
                null,
                $ipAddress,
                $this->isPreprod()
            );

            if (!$this->errorPaygreenApiClient($datas)) {
                $encodedData = Tools::jsonEncode($datas);
                Configuration::updateValue('oauth_access', $encodedData);
            }
        }
        $REDIRECT_URI = Configuration::get('URL_BASE');


        $CLIENT_ID = Tools::jsonDecode(Configuration::get('oauth_access'))->data->accessPublic;
        $CLIENT_SECRET = Tools::jsonDecode(Configuration::get('oauth_access'))->data->accessSecret;

        $client = new OAuthClient($CLIENT_ID, $CLIENT_SECRET, OAuthClient::AUTH_TYPE_AUTHORIZATION_BASIC);


        if (Tools::getValue('code') == null) {

            $auth_url = $client->getAuthenticationUrl(
                PaygreenApiClient::getOAuthAutorizeEndpoint($this->isPreprod()),
                $REDIRECT_URI
            );

            Tools::redirect($auth_url);

        } else {
            $params = array('code' => Tools::getValue('code'), 'redirect_uri' => Configuration::get('URL_BASE'));

            $response = $client->getAccessToken(
                PaygreenApiClient::getOAuthTokenEndpoint($this->isPreprod()),
                'authorization_code',
                $params
            );

            if ($response['result']['success'] == 1) {
                Configuration::updateValue('_PG_CONFIG_PRIVATE_KEY', $response['result']['data']['privateKey']);
                $pp = '';
                if ($this->isPreprod()) {
                    $pp = 'PP';
                }
                Configuration::updateValue('_PG_CONFIG_SHOP_TOKEN', $pp.$response['result']['data']['id']);
                $this->log('OAuth', 'Login');
            } else {
                $stringError = $this->l(
                    'There is a problem with the module PayGreen'.
                    ',please contact the technical supports support@paygreen.fr'
                );
                $this->context->controller->errors[] =  $stringError . ' : ' . $response['result']['message'];
            }

            Configuration::deleteByName('oauth_access');
        }
    }

    /**
     * Remove private key and unique id
     */
    private function logout()
    {
        Configuration::updateValue('_PG_CONFIG_PRIVATE_KEY', '');
        Configuration::updateValue('_PG_CONFIG_SHOP_TOKEN', '');
        $this->log('OAuth', 'Logout');
    }

    private function getButtonsList()
    {
        if (Module::isInstalled($this->name)) {
            return Db::getInstance()->executeS(
                'SELECT * FROM ' . _DB_PREFIX_ . 'paygreen_buttons ORDER BY position ASC'
            );
        }
        return array();
    }

    /**
     * Create the form that will be displayed in the configuration of your module.
     */
    protected function renderForm()
    {
        $helper = new HelperForm();

        $helper->show_toolbar = false;
        $helper->table = $this->table;
        $helper->module = $this;
        $helper->default_form_language = $this->context->language->id;
        $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0);

        $helper->identifier = $this->identifier;
        $helper->submit_action = 'submitPaygreenModule';
        $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false)
            . '&configure=' . $this->name . '&tab_module=' . $this->tab . '&module_name=' . $this->name;
        $helper->token = Tools::getAdminTokenLite('AdminModules');

        $helper->tpl_vars = array(
            'fields_value' => $this->getConfig(), /* Add values for your inputs */
            'languages' => $this->context->controller->getLanguages(),
            'id_language' => $this->context->language->id,
        );

        return $helper->generateForm(array($this->getForm()));


    }

    protected function createSwitch($name, $label, $desc, $id)
    {
        return array(
            'type' => 'switch',
            'label' => $label,
            'name' => $name,
            'is_bool' => true,
            'desc' => $desc,
            'values' => array(
                array(
                    'id' => $id . '_on',
                    'value' => 1,
                    'label' => $this->l('Enabled')
                ),
                array(
                    'id' => $id . '_off',
                    'value' => 0,
                    'label' => $this->l('Disabled')
                )
            ),
        );
    }

    protected function createRadio($name, $label, $label_yes, $p_yes, $label_no, $p_no, $id)
    {
        return array(
            'type' => 'radio',
            'label' => $label,
            'name' => $name,
            'values' => array(
                array(
                    'id' => $id . '_yes',
                    'label' => $label_yes,
                    'value' => 1,
                    'p' => $p_yes,
                ),
                array(
                    'id' => $id . '_no',
                    'label' => $label_no,
                    'value' => 0,
                    'p' => $p_no,
                )
            ),
            'class' => 'fixed-width-xxl'
        );
    }

    protected function getFormValidator()
    {
        return array(
            self::_CONFIG_PRIVATE_KEY => array(
                'regexp' => array(
                    'params' => '^[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}$',
                    'msg' => $this->l('Your private key is wrong.')
                ),
            ),
            self::_CONFIG_SHOP_TOKEN => array(
                'regexp' => array(
                    'params' => '^(PP|LC)?[a-f0-9]{32}$',
                    'msg' => $this->l('Your unique Identifier is wrong.')
                ),
            ),
        );
    }

    protected function regexpValidator($value, $args)
    {
        $output_array = null;
        preg_match("/".$args."/i", $value, $output_array);
        return $output_array!=null && count($output_array)>0;
    }

    /**
     * Create the structure of your form.
     */
    protected function getForm()
    {
        $config_cancel_action = $this->createRadio(
            self::_CONFIG_CANCEL_ACTION,
            $this->l('Action during cancellation'),
            $this->l('Order creation'),
            $this->l('Generate canceled order and send e-mails'),
            $this->l('No action'),
            $this->l('To a classic boutique return to see his cart'),
            'cancel_action_'
        );
        $config_visible = $this->createRadio(
            self::_CONFIG_VISIBLE,
            $this->l('Visible module'),
            $this->l('Activated module'),
            $this->l('The module is visible by all.'),
            $this->l('Invisible module (mode TEST)'),
            $this->l('The module is visible only by administrator'),
            'config_visible'
        );

        if (Tools::substr(_PS_VERSION_, 0, 3) == 1.5) {
            $config_payment_refund = $this->createRadio(
                self::_CONFIG_PAYMENT_REFUND,
                $this->l('Paygreen refund'),
                $this->l('Activated refund'),
                $this->l('Paygreen can refund.'),
                $this->l('disabled refund'),
                $this->l('Paygreen can\'t refund'),
                'config_refund'
            );

            $config_footer_display = $this->createRadio(
                self::_CONFIG_FOOTER_DISPLAY,
                $this->l('Show PayGreen security'),
                $this->l('Footer Displayed'),
                $this->l(' '),
                $this->l('Footer Disabled'),
                $this->l(' '),
                'display_logo'
            );

            $config_verif_adult = $this->createRadio(
                self::_CONFIG_VERIF_ADULT,
                $this->l('Check age of clients'),
                $this->l('Date of birth asked'),
                $this->l(' '),
                $this->l('Date of birth don\'t asked'),
                $this->l(' '),
                'display_verif_adult'
            );

        } else {

            $config_payment_refund = $this->createSwitch(
                self::_CONFIG_PAYMENT_REFUND,
                $this->l('Paygreen refund'),
                $this->l('Allow refund with paygreen by your back office prestashop'),
                'active'
            );

            $config_footer_display = $this->createSwitch(
                self::_CONFIG_FOOTER_DISPLAY,
                $this->l('Show PayGreen security'),
                $this->l('Display Paygreen Logo in your footer website'),
                'logo'
            );

            $config_verif_adult = $this->createSwitch(
                self::_CONFIG_VERIF_ADULT,
                $this->l('Check age of clients'),
                $this->l('Ask the date of birth before payment to check majority'),
                'display_verif_adult'
            );

        }
        $colors = array(
            array(
                'id_option' => 'white',
                'name' => $this->l('white')
            ),
            array(
                'id_option' => 'green',
                'name' => $this->l('green')
            ),
            array(
                'id_option' => 'black',
                'name' => $this->l('black')
            )
        );
        return array(
            'form' => array(
                'legend' => array(
                    'title' => $this->l('Payment system configuration'),
                    'icon' => 'icon-cogs',
                ),
                'input' => array(
                    array(
                        'type' => 'text',
                        'label' => $this->l('Unique Identifier'),
                        'name' => self::_CONFIG_SHOP_TOKEN,
                        'size' => 33,
                        'required' => true,
                        'placeholder' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
                        'class' => 'fixed-width-xxl'
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Private key'),
                        'name' => self::_CONFIG_PRIVATE_KEY,
                        'size' => 28,
                        'required' => true,
                        'placeholder' => 'xxxx-xxxx-xxxx-xxxxxxxxxxxx',
                        'class' => 'fixed-width-xxl'
                    ),
                    array(
                        'type' => 'button',
                        'name' => 'connectApi',
                        'value' => 'Connect'
                    ),
                    $config_cancel_action,
                    array(
                        'type' => 'text',
                        'label' => $this->l('Sentence during a successful payment'),
                        'name' => self::_CONFIG_PAIEMENT_ACCEPTED,
                        'size' => 150,
                        'required' => false,
                        'placeholder' => $this->l('Your payment was accepted'),
                        'class' => 'fixed-width-xxl'
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Sentence during an unsuccessful payment'),
                        'name' => self::_CONFIG_PAIEMENT_REFUSED,
                        'size' => 150,
                        'required' => false,
                        'placeholder' => $this->l('Your payment was unsuccessful'),
                        'class' => 'fixed-width-xxl'
                    ),
                    $config_visible,
                    $config_payment_refund,
                    $config_footer_display,
                    array(
                        'type' => 'select',
                        'label' => $this->l('Color logo'),
                        'desc' => $this->l('Color of the Paygreen Logo in the footer '),
                        'name' => self::_CONFIG_FOOTER_LOGO_COLOR,
                        'options' => array(
                            'query' => $colors,
                            'id' => 'id_option',
                            'name' => 'name'
                        )
                    ),
                    $config_verif_adult,
                ),
                'submit' => array(
                    'title' => $this->l('Save'),
                    'class' => 'btn btn-default pull-right button'
                )
            ),
        );
    }


    /**
     *   Return state of transaction by the id order
     * @param $id_order
     * @return state or false if not exists
     */
    protected function getStateTransactionByIdOrder($id_order)
    {

        return Db::getInstance()->getValue(
            'SELECT state FROM ' . _DB_PREFIX_ . 'paygreen_transactions
    WHERE id_order=' . ((int)$id_order) . ';'
        );
    }

    /**
     *   Return state of transaction by the id order
     * @param $id_order
     * @return state or false if not exists
     */
    protected function getPIDByOrder($id_order)
    {

        return Db::getInstance()->getValue(
            'SELECT pid FROM ' . _DB_PREFIX_ . 'paygreen_transactions
    WHERE id_order=' . ((int)$id_order) . ';'
        );
    }



    /**
     * Check if an order is already refunded
     * @param $id_order
     * @return true or false
     */
    protected function isRefunded($id_order)
    {

        $stateTransac = $this->getStateTransactionByIdOrder($id_order);

        // 7 for refund
        if ($stateTransac == 7 || $stateTransac == null) {
            return true;
        }
        return false;
    }


    /**
     * Insert paygreen transaction with id_order and pid
     * @param $id_order
     * @param $client
     * @param $id_cart
     * @param $current_state
     * @return true or false
     */
    protected function insertPaygreenTransaction($id_order, $client, $id_cart, $current_state)
    {

        if ($this->isPaygreenSamePID($id_cart, $client->pid)) {
            return false;
        }
        $date = new DateTime();
        $paygreenTransaction = array();
        $paygreenTransaction['id_cart'] = ((int)$id_cart);
        $paygreenTransaction['pid'] = pSQL($client->pid);
        $paygreenTransaction['id_order'] = ((int)$id_order);
        $paygreenTransaction['state'] = pSQL($current_state);
        $paygreenTransaction['type'] = pSQL($client->mode);
        $paygreenTransaction['created_at'] = pSQL($date->format('Y-m-d H:i:s'));

        $this->log("InsertPaygreenTransaction", "New Transaction");
        if (Db::getInstance()->insert('paygreen_transactions', $paygreenTransaction)) {
            // INSERTION Of deadlines if recurring payment
            if ($client->mode == 'RECURRING') {
                $this->insertPaygreenRecurringTransaction($id_cart, $current_state);
            }
        }

    }


    /**
     * Insert paygreen recurring transaction
     *
     */
    protected function insertPaygreenRecurringTransaction($id_cart, $current_state)
    {

        $last_recurring_t_state = Db::getInstance()->getValue('SELECT state FROM ' . _DB_PREFIX_ . 'paygreen_transaction
    WHERE id_cart=' . ((int)$id_cart) . ' ORDER BY created_at DESC LIMIT 1,1;');

        // Status Annulé : 6
        // Status erreur de paiement : 8
        if ($last_recurring_t_state == 6 || $last_recurring_t_state == 6) {
            return false;
        }
        $recurringTransaction = array();
        $recurringTransaction['id_cart'] = ((int)$id_cart);
        $recurringTransaction['state'] = pSQL($current_state);

        Db::getInstance()->insert('paygreen_recurring_transaction', $recurringTransaction);

    }

    /**
     * test if Paygreen Transaction exists
     * @param $id_cart
     * @param $id paygreen
     * @return true of false
     */
    protected function isPaygreenSamePID($id_cart, $pid)
    {

        $transacPid = Db::getInstance()->getValue(
            'SELECT pid FROM ' . _DB_PREFIX_ . 'paygreen_transactions
    WHERE id_cart=' . ((int)$id_cart) . ';'
        );

        if ($transacPid == $pid) {
            $this->log("isPaygreenTransacExist", "Same pid");
            return true;
        }

        return false;
    }

    protected function getRecurringPayment()
    {
        return Db::getInstance()->executeS(
            'SELECT * FROM ' . _DB_PREFIX_ .
            'paygreen_transactions WHERE type=\'RECURRING\' ORDER BY id_cart ASC'
        );
    }


    public function validateWebPayment($a_data, $isCallback = false)
    {
        $this->log('validateWebPayment', $isCallback ? 'CALLBACK' : 'RETURN');

        if (!isset($a_data['data'])) {
            list($name, $value) = explode('=', $_SERVER['QUERY_STRING'], 2);
            if ($name != 'data' && !isset($value)) {
                return false;
            }
            $a_data['data'] = urldecode($value);
        }
        $config = $this->getConfig();

        $client = $this->getCaller();
        $client->parseData($a_data['data']);

        $f_amount = $client->amount / 100;

        $o_cart = new Cart($client->cart_id);

        $o_customer = new Customer((int)$o_cart->id_customer);


        if ($client->result['status'] == PaygreenClient::STATUS_REFUSED) {
            $status = Configuration::get('PS_OS_ERROR');
        } elseif ($client->result['status'] == PaygreenClient::STATUS_CANCELLING) {
            $status = Configuration::get('PS_OS_CANCELED');
        } elseif ($client->result['status'] == PaygreenClient::STATUS_PENDING_EXEC) {
            $status = Configuration::get(self::_CONFIG_ORDER_AUTH);
            $f_amount = 0;
        } elseif ($client->result['status'] == PaygreenClient::STATUS_SUCCESSED) {
            $status = Configuration::get('PS_OS_PAYMENT');
        } else {
            if (!$isCallback) {
                $this->redirectToConfirmationPage();
            }
            return true;
        }

        if ($config[self::_CONFIG_CANCEL_ACTION] == 0 && $status == _PS_OS_CANCELED_) {
            //Tools::redirect('order');
            if (!$isCallback) {
                $this->redirectToConfirmationPage();
            }
            return true;
        }
        if ((int)($client->testMode) == 1 && $status == Configuration::get('PS_OS_PAYMENT')) { //_CONFIG_CANCEL_ACTION
            $status = Configuration::get(self::_CONFIG_ORDER_TEST);
            $f_amount = 0;
        }

        $a_vars = $client->result;
        $a_vars['date'] = time();
        $a_vars['transaction_id'] = $client->transaction_id;
        $a_vars['mode'] = $client->mode;
        $a_vars['amount'] = $client->amount;
        $a_vars['currency'] = $client->currency;
        $a_vars['by'] = 'webPayment';

        $n_order_id = (int)Order::getOrderByCartId($o_cart->id);

        if (!$this->isPaygreenSamePID($client->cart_id, $client->pid)) {

        }

        if (!$n_order_id) {

            $this->validateOrder(
                $o_cart->id,
                $status,
                $f_amount,
                $this->displayName,
                $this->l('Transaction Paygreen') . ': ' . (int)$o_cart->id . ' (' . $client->paiement_btn . ')' .
                ((int)($client->testMode) == 1 ? '|/!\ ' . $this->l('WARNING transaction in TEST mode') . '/!\ ' : ''),
                $a_vars,
                null,
                false,
                $o_customer->secure_key
            );
            $n_order_id = (int)Order::getOrderByCartId((int)$o_cart->id);

            $this->log('validateWebPayment-validateOrder', $n_order_id);
        } else {
            $this->log('Order already exists => ' . $n_order_id);
        }

        if ($n_order_id) {

            $o_order = new Order($n_order_id);

            $this->insertPaygreenTransaction($n_order_id, $client, $o_cart->id, $o_order->current_state);

            $this->log('Id existant : ', $n_order_id);
            $this->log('validateWebPayment-order', $o_order);

            if ($o_order->current_state != $status) {

                $this->log('validateWebPayment-orderHistory', $o_order->current_state . ' TO ' . $status);
                $o_order->setCurrentState($status);
                $o_order->save();
            }

            if (!$isCallback) {
                $b_err = !in_array($status, array(
                    _PS_OS_PAYMENT_,
                    Configuration::get(self::_CONFIG_ORDER_AUTH),
                    Configuration::get(self::_CONFIG_ORDER_TEST)
                ));


                $this->redirectToConfirmationPage($o_order, $b_err);
            } else {
                print_r(Tools::jsonEncode($o_order));
            }
        }

        return true;
    }

    protected function redirectToConfirmationPage($o_order = null, $b_error = false)
    {
        if ($o_order == null) {
            $link = new Link();
            $error_url = $link->getPageLink('order', null, null, array('step' => 3));
            Tools::redirect($error_url);
            return;
        }
        $a_query = array(
            'id_module' => $this->id,
            'id_cart' => $o_order->id_cart,
            'key' => $o_order->secure_key,
        );

        if ($b_error) {
            $a_query['error'] = 'Payment error';
        }

        Tools::redirectLink(__PS_BASE_URI__ . 'order-confirmation.php?' . http_build_query($a_query));
    }

    protected function isResultInSet($s_result, $m_result_set = self::RS_VALID_SIMPLE)
    {
        if (is_array($m_result_set)) {
            $a_set = $m_result_set;
        } elseif (is_scalar($m_result_set) && isset($this->a_result_sets[$m_result_set])) {
            $a_set = $this->a_result_sets[$m_result_set];
        } else {
            $a_set = array();
        }

        return in_array($s_result, $a_set, true);
    }

    public function getErrorDescription($s_error_code)
    {
        if ($this->isResultInSet($s_error_code, array_keys($this->a_result_sets[self::ERROR_TYPE_BUYER]))) {
            return $this->l('Buyer error') . ' [' . $s_error_code . ']' .
            $this->getL($this->a_result_sets[self::ERROR_TYPE_BUYER][$s_error_code]);
        } elseif ($this->isResultInSet($s_error_code, array_keys($this->a_result_sets[self::ERROR_TYPE_MERCHANT]))) {
            return $this->l('Merchant error') . ' [' . $s_error_code . ']' .
            $this->getL($this->a_result_sets[self::ERROR_TYPE_MERCHANT][$s_error_code]);
        } else {
            return $this->l('Unknown error') . ' [' . $s_error_code . ']' .
            sprintf($this->l('Payment error'), $s_error_code);
        }
    }

    /**
     * Set values for the inputs.
     */
    protected function getConfig()
    {
        $config = Configuration::getMultiple(
            array(
                self::_CONFIG_PRIVATE_KEY,
                self::_CONFIG_SHOP_TOKEN,
                self::_CONFIG_PAIEMENT_ACCEPTED,
                self::_CONFIG_PAIEMENT_REFUSED,
                self::_CONFIG_SHOP_INPUT_METHOD,
                self::_CONFIG_CANCEL_ACTION,
                self::_CONFIG_VISIBLE,
                self::_CONFIG_PAYMENT_REFUND,
                self::_CONFIG_FOOTER_DISPLAY,
                self::_CONFIG_FOOTER_LOGO_COLOR,
                self::_CONFIG_VERIF_ADULT

            )
        );

        if (empty($config[self::_CONFIG_PAIEMENT_ACCEPTED])) {
            $config[self::_CONFIG_PAIEMENT_ACCEPTED] = $this->l('Your payment was accepted');
        }
        if (empty($config[self::_CONFIG_PAIEMENT_REFUSED])) {
            $config[self::_CONFIG_PAIEMENT_REFUSED] = $this->l('Your payment unsuccessful');
        }
        if (empty($config[self::_CONFIG_SHOP_INPUT_METHOD])) {
            $config[self::_CONFIG_SHOP_INPUT_METHOD] = 'POST';
        }
        if (empty($config[self::_CONFIG_CANCEL_ACTION])) {
            $config[self::_CONFIG_CANCEL_ACTION] = 0;
        }
        if (empty($config[self::_CONFIG_VISIBLE])) {
            $config[self::_CONFIG_VISIBLE] = 0;
        }
        if (empty($config[self::_CONFIG_PAYMENT_REFUND])) {
            $config[self::_CONFIG_PAYMENT_REFUND] = 0;
        }
        if (empty($config[self::_CONFIG_FOOTER_LOGO_COLOR])) {
            $config[self::_CONFIG_FOOTER_LOGO_COLOR] = 'white';
        }

        return $config;
    }

    private function getIconDirectory($image = "", $toView = false)
    {
        $baseDn = ($toView == true) ? $this->getShopUrl() . 'modules/paygreen' : dirname(__FILE__);
        $separator = ($toView == true) ? '/' : DIRECTORY_SEPARATOR;
        return implode($separator, array($baseDn, 'views', 'img', 'icons', $image));
    }

    private function getImgDirectory($image = "", $toView = false)
    {
        $baseDn = ($toView == true) ? $this->getShopUrl() . 'modules/paygreen' : dirname(__FILE__);
        $separator = ($toView == true) ? '/' : DIRECTORY_SEPARATOR;
        return implode($separator, array($baseDn, 'views', 'img', $image));
    }

    /**
     * Save form data.
     */
    protected function postProcess()
    {
        if (Tools::isSubmit('submitPaygreenModule')) {
            $form_values = $this->getConfig();
            $validators = $this->getFormValidator();
            foreach (array_keys($form_values) as $key) {
                $fieldValue = trim(Tools::getValue($key));
                if (isset($validators[$key])) {
                    foreach ($validators[$key] as $fn => $conf) {
                        if (!$this->{$fn.'Validator'}($fieldValue, $conf['params'])) {
                            return $this->displayError($conf['msg']);
                        }
                    }
                }
                Configuration::updateValue($key, $fieldValue);
            }
            PaygreenApiClient::setIds(
                Configuration::get(self::_CONFIG_SHOP_TOKEN),
                Configuration::get(self::_CONFIG_PRIVATE_KEY)
            );
            // Recompile the template for footer
            $this->context->smarty->clearCompiledTemplate();
            return $this->displayConfirmation($this->l('Datas saved'));
        }

        if (Tools::isSubmit('submitPaygreenModuleAccount')) {

            $activate = Tools::getValue('PS_PG_activate_account');
            $this->log('submitPaygreenModuleAccount-PS_PG_activate_account', $activate);
            //$this->log('submitPaygreenModuleAccount- TOKEN ', Configuration::get(self::_CONFIG_SHOP_TOKEN));
            $token = $this->getUniqueIdPP();

            $validated = PaygreenApiClient::validateShop(
                $token,
                Configuration::get(self::_CONFIG_PRIVATE_KEY),
                $activate,
                $this->isPreprod()
            );
            $this->errorPaygreenApiClient($validated);
        }

        if (Tools::isSubmit('submitPaygreenModuleButton')) {
            $modelButton = $this->a_model_buttons;
            $id = Tools::getValue('id', '');

            //Upload image
            if (array_key_exists('image', $_FILES) && $_FILES['image']['error'] != UPLOAD_ERR_NO_FILE) {
                if ($_FILES['image']['error'] > 0) {
                    return $this->displayError($this->l('Any image is sent'));
                }
                //Check upload file
                $fileInfo = pathinfo($_FILES['image']['name']);
                if (!in_array(Tools::strtolower($fileInfo['extension']), array('jpg', 'jpeg', 'png'))) {
                    return $this->displayError($this->l('Any image is sent'));
                }
                preg_match("/[a-zA-Z0-9_-]*/", $fileInfo['filename'], $matches);
                if ($matches[0] != $fileInfo['filename']) {
                    return $this->displayError($this->l('Any image is sent'));
                }

                $sImagePath = $this->getIconDirectory($_FILES['image']['name']);
                move_uploaded_file($_FILES["image"]["tmp_name"], $sImagePath);
                $modelButton['image'] = $_FILES['image']['name'];
            } else {
                unset($modelButton['image']);
            }

            foreach (array_keys($modelButton) as $key) {
                $value = Tools::getValue($key, $modelButton[$key]);
                //$this->log("addButton", 'value : ' . $key . ' -> ' . $value);
                if (!empty($value) && isset($value)) {
                    $modelButton[$key] = is_numeric($value)? ((int)$value): pSQL($value);
                }
            }
            unset($modelButton['id']);

            $this->log("addButton", $modelButton);
            if ((int)($modelButton['position']) <= 0) {
                $btn = $this->getButtonsList();
                $modelButton['position'] = (int)(count($btn) + 1);
            }

            if ($id > 0) {
                Db::getInstance()->update('paygreen_buttons', $modelButton, 'id=' . ((int)$id));
                $display = $this->displayConfirmation($this->l('Datas saved'));
            } else {
                Db::getInstance()->insert('paygreen_buttons', $modelButton);
                $display = $this->displayConfirmation($this->l('Datas saved'));
            }

            return $display;

            //return Db::getInstance()->Execute($request);
        }

        if (Tools::isSubmit('submitPaygreenModuleButtonDelete')) {
            $id = Tools::getValue('id', '');
            if ($id == "") {
                return $this->displayError($this->l('Action no possible'));
            }
            Db::getInstance()->delete('paygreen_buttons', 'id=' . ((int)$id));
            return $this->displayConfirmation($this->l('Button') . Tools::getValue('label') . $this->l('deleted'));
        }

        return '';
    }

    /**
     * Check if a payment was done with Paygreen
     * @param $id_order
     * @return true or false
     */
    protected function isPaygreenPayment($id_order)
    {
        if ($this->getPaymentByOrder($id_order) != 'Paygreen') {
            return false;
        }
        return true;
    }

    public function getTotalRefundByIdOrder($id_order)
    {
        if (!(int)$id_order) {
            return false;
        }

        return Db::getInstance()->getValue(
            'SELECT SUM(`unit_price_tax_incl` * `product_quantity_refunded`) FROM '.
            _DB_PREFIX_.'order_detail WHERE `id_order` = ' . (int)$id_order . ';'
        );
    }


    public function paygreenRefundTransaction($id_order, $amount = null)
    {

        if (Configuration::get(self::_CONFIG_PAYMENT_REFUND) != 1) {
            return false;
        }

        if (!$this->isPaygreenPayment($id_order)) {
            return false;
        }

        if ($this->isRefunded($id_order)) {
            return false;
        }

        $pid = $this->getPIDByOrder($id_order);
        if (empty($pid)) {
            return false;
        }

        $token = Configuration::get(self::_CONFIG_SHOP_TOKEN);
        if (Tools::substr($token, 0, 2) == 'PP') {
            $token = Tools::substr($token, 2);
        }
        //round($this->getTotalRefundByIdOrder($id_order), 2)
        $this->log('REFUND', array($pid, $amount));

        $refundStatus = PaygreenApiClient::refundOrder(
            $this->getUniqueIdPP(),
            Configuration::get(self::_CONFIG_PRIVATE_KEY),
            $pid,
            round($amount, 2),
            $this->isPreprod()
        );

        $this->errorPaygreenApiClient($refundStatus);
        if (!$refundStatus) {
            $this->log('PaygreenTRansaction update State ', 'Transacton '. $pid .' NOT refunded');
            return false;
        }
        if (isset($refundStatus->success)) {
            if (!$refundStatus->success) {
                $this->log('PaygreenTRansaction update State ', 'Transacton '. $pid .' NOT refunded');
                return false;
            }
        }

        if (isset($amount)) {
            $order = new Order($id_order);
            if (round($this->getTotalRefundByIdOrder($id_order), 2)>=$order->total_paid) {
                $this->updatePaygreenTransactionStatus($id_order, 7);
            }
        } else {
            $this->updatePaygreenTransactionStatus($id_order, 7);
        }
        return true;
    }

    /**
    * Update status of paygreen transaction
    * @param $id_order id order
    * @param $state of order
    */
    public function updatePaygreenTransactionStatus($id_order, $state)
    {
        $date = new DateTime();
        $transaction = array();
        $transaction['state'] = pSQL($state);
        $transaction['updated_at'] = pSQL($date->format('Y-m-d H:i:s'));
        Db::getInstance()->update('paygreen_transactions', $transaction, 'id_order=' . $id_order);
    }


    /**
     * Hook When refund total_paid_tax_incl
     * @param $params
     */
    public function hookPostUpdateOrderStatus($params)
    {
        if (!isset($params['id_order'])) {
            return false;
        }

        $id_order = $params['id_order'];

        if (!isset($params['newOrderStatus'])) {
            return false;
        }

        if ($params['newOrderStatus']->template != 'refund') {
            return false;
        }

        $refundStatus = $this->paygreenRefundTransaction($id_order);
        if (!$refundStatus) {
            return false;
        }
    }



    /**
     * Hook for when partial refund
     * @param $params
     */
    public function hookActionObjectOrderSlipAddAfter($params)
    {
        if (!isset($params['object'])) {
            return false;
        }

        $amount = $params['object']->amount + $params['object']->shipping_cost_amount;

        if ($amount <= 0) {
            return false;
        }

        return $this->paygreenRefundTransaction($params['object']->id_order, $amount);
    }


    public function hookDisplayFooter($params)
    {

        if (Configuration::get(self::_CONFIG_FOOTER_DISPLAY) != 1) {
            return '';
        }

        $this->context->smarty->assign(array(
            'imgdir' => $this->getImgDirectory('', true),
            'color' => Configuration::get(self::_CONFIG_FOOTER_LOGO_COLOR)
        ));
        return $this->display(__FILE__, 'views/templates/hook/paygreen-footer.tpl');
    }

    /**
     *   Return Payment module name by id order
     * @param $id_order
     * @return name of payment module (ex:paygreen)
     */
    protected function getPaymentByOrder($idOrder)
    {
        if (!(int)$idOrder) {
            return false;
        }

        return Db::getInstance()->getValue(
            'SELECT `payment`
            FROM `' . _DB_PREFIX_ . 'orders`
            WHERE `id_order` = ' . (int)$idOrder . ';'
        );
    }

    /**
     * Generate Payement
     * @param $transactionId
     * @param $nbPaiement
     * @param $amount
     * @param $currency 'EUR' etc...
     * @param $typePayment cash, subscribe etc... with int
     * @param $reoirt
     */
    private function generatePaiementData($transactionId, $nbPaiement, $amount, $currency, $typePayment, $reportPayment)
    {
        $paiement = $this->getCaller();
        $paiement->transaction(
            $transactionId,
            round($amount * 100),
            $currency
        );


        if ($nbPaiement > 1) {

            switch ($typePayment) {
                case 1:
                    $startAtReportPayment = ($reportPayment == 0) ? null : strtotime($reportPayment);

                    $paiement->subscribtionPaiement(
                        PaygreenClient::RECURRING_MONTHLY,
                        $nbPaiement,
                        date('d'),
                        $startAtReportPayment
                    );
                    break;
                case 3:
                    $paiement->xTimePaiement($nbPaiement, $reportPayment);
                    break;
            }

        }

        return $paiement;
    }


    public function isVisible()
    {
        $config = $this->getConfig();
        if ($config[self::_CONFIG_VISIBLE] == 0) {
            $userCookie = new Cookie('psAdmin');
            if (isset($userCookie->id_employee) && $userCookie->id_employee > 0) {
                return true;
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * Check If there are options onstraints
     * @param $btn
     * @return bool
     */
    private function checkBtn($btn)
    {
        $error = '';
        if (!isset($btn['executedAt'])) {
            return $error;
        }
        $type = $btn['executedAt'];

        if (!isset($btn['nbPayment'])) {
            return $error;
        }
        $nbPayment = $btn['nbPayment'];

        if (!isset($btn['reportPayment'])) {
            return $error;
        }
        $report = $btn['reportPayment'];

        if ($nbPayment > 1) {
            // Cash payment
            if ($type == 0) {
                $error = $this->l('The payment cash must be only once');
                // At the delivery
            } else {
                if ($type < 0) {
                    $error = $this->l('The payment at delivery must be only once');
                }
            }
        } else {
            // Subscription payment
            if ($type == 1) {
                $error = $this->l('The subscription payment must have more than one payment due');
                // Recurring payment
            } else {
                if ($type == 3) {
                    $error = $this->l('The recurring payment must have more than one payment due');
                }
            }
        }
        if ($report > 0) {
            // Cash payment
            if ($type == 0) {
                $error = $this->l('The cash payment can\'t have a report payment');
                // At the delivery
            } else {
                if ($type < 0) {
                    $error = $this->l('The payment at the delivery can\'t have a report payment');
                }
            }
        }
        return $error;
    }


    public function paygreenValidIds()
    {
        $validID = PaygreenApiClient::validIdShop(
            $this->getUniqueIdPP(),
            Configuration::get(self::_CONFIG_PRIVATE_KEY),
            $this->isPreprod()
        );
        if ($this->errorPaygreenApiClient($validID)) {
            return false;
        }
        return $validID;

    }

    public function hookDisplayPayment($params)
    {
        /* Place your code here. */
        if ($this->verifyConfiguration() != '') {
            return false;
        }
        if ($this->getPaygreenConfig('type') != 'LC' && !$this->paygreenValidIds()) {
            return false;
        }

        $config = $this->getConfig();

        if (!$this->isVisible()) {
            return false;
        }

        $cust = new Customer((int)$this->context->cookie->id_customer);
        $currency = new Currency((int)$this->context->cart->id_currency);


        $currentConfigureListButtons = $this->getButtonsList();
        $totalCart = $this->context->cart->getOrderTotal();
        $buttons = array();
        $this->log('hookDisplayPayment', $this->context->cart);


        foreach ($currentConfigureListButtons as $btn) {
            //Test
            // SI false > continue
            if ($this->checkBtn($btn) != '') {
                continue;
            }
            if (isset($btn['minAmount'])) {
                if ($btn['minAmount'] > 0 && $totalCart < $btn['minAmount']) {
                    continue;
                }
            }

            if (isset($btn['maxAmount'])) {
                if ($btn['maxAmount'] > 0 && $totalCart > $btn['maxAmount']) {
                    continue;
                }
            }
            if (isset($btn['nbPayment']) && isset($btn['executedAt'])) {
                if (!isset($btn['reportPayment'])) {
                    $btn['reportPayment'] = 0;
                }
                $paiement = $this->generatePaiementData(
                    $this->context->cart->id,
                    $btn['nbPayment'],
                    $totalCart,
                    $currency->iso_code,
                    $btn['executedAt'],
                    $btn['reportPayment']
                );
            }

            switch ($btn['executedAt']) {
                // At the delivery
                case -1:
                    $paiement->cardPrint();
                    break;
            }

            if (!isset($paiement)) {
                return false;
            }

            $paiement->customer(
                $cust->id,
                $cust->lastname,
                $cust->firstname,
                $cust->email
            );

            $paiement->cart_id = $this->context->cart->id;

            if (isset($btn['label'])) {
                $paiement->paiement_btn = $btn['label'];
            }
            $paiement->return_cancel_url = $this->getShopUrl() . 'modules/paygreen/validation.php';
            $paiement->return_url = $this->getShopUrl() . 'modules/paygreen/validation.php';
            $paiement->return_callback_url = $this->getShopUrl() . 'modules/paygreen/notification.php';


            $address = new Address($this->context->cart->id_address_delivery);
            $paiement->shippingTo(
                $address->lastname,
                $address->firstname,
                $address->address1,
                $address->address2,
                $address->company,
                $address->postcode,
                $address->city,
                $address->country
            );

            $btn['debug'] = $paiement;
            $btn['paiement'] = array(
                'action' => $paiement->getActionForm(),
                'paiementData' => $paiement->generateData()
            );
            $buttons[] = $btn;
        }

        $this->context->smarty->assign(array(
            'prestashop' => Tools::substr(_PS_VERSION_, 0, 3),
            'verify_adult'=>Configuration::get(self::_CONFIG_VERIF_ADULT),
            'buttons' => $buttons,
            'icondir' => $this->getIconDirectory("", true),
            'imgdir' => $this->getImgDirectory("", true),
            'config' => $config
        ));

        $version = Tools::substr(_PS_VERSION_, 0, 3);
        $this->context->controller->addJS($this->_path . 'views/js/' . $version . '/front.js');
        $this->context->controller->addCSS($this->_path . 'views/css/' . $version . '/front.css');
        return $this->context->smarty->fetch($this->local_path . 'views/templates/front/' . $version . '/payment.tpl');
    }

    private function getShopUrl()
    {
        if (Configuration::get('PS_SSL_ENABLED')) {
            return 'https://'.$this->context->shop->domain.$this->context->shop->getBaseURI();
        } else {
            return $this->context->shop->getBaseURL();
        }
    }

    public function hookDisplayPaymentReturn()
    {
        /* Place your code here. */
        $config = $this->getConfig();
        $this->context->smarty->assign(array(
            'prestashop' => Tools::substr(_PS_VERSION_, 0, 3),
            'error' => Tools::getValue('error') ? Tools::getValue('error') : 0,
            'config' => $config
        ));
        return $this->context->smarty->fetch($this->local_path . 'views/templates/front/payment_return.tpl');
    }

    protected function executeSqlFile($sFilePath)
    {
        $sSqlString = (file_exists($sFilePath) && is_readable($sFilePath) ? Tools::file_get_contents($sFilePath) : '');

        return $this->executeSqlString($sSqlString);
    }

    protected function executeSqlString($sSqlString)
    {

        $sSqlString = str_replace('%%PREFIX%%', _DB_PREFIX_, $sSqlString);

        $aQueries = preg_split('#;\s*[\r\n]+#', $sSqlString);

        foreach (array_filter(array_map('trim', $aQueries)) as $sQuery) {
            $mResult = Db::getInstance()->execute($sQuery);
            if ($mResult === false) {
                Logger::addLog('Query FAILED ' . $sQuery);
                return false;
            }
        }
        return true;
    }

    /**
     * Insert a default button in the database
     * @return true
     */
    protected function initializeDb()
    {
        $btn = $this->getButtonsList();
        if (count($btn) == 0) {
            $this->executeSqlString(
                "INSERT INTO `%%PREFIX%%paygreen_buttons` (`label`, `position`, `height`, `displayType`, `nbPayment`)" .
                " VALUES ('" . $this->l('Pay by bank card') . "', '1', '60', 'bloc', '1');"
            );
        }
        return true;
    }


    protected function createOrderStatuses()
    {
        $create = true;

        if (!(Configuration::get(self::_CONFIG_ORDER_AUTH) > 0)) {
            $orderState = new OrderState();
        } else {
            $orderState = new OrderState((int)Configuration::get(self::_CONFIG_ORDER_AUTH));
        }

        $orderState->name = array();
        foreach (Language::getLanguages() as $language) {
            if (Tools::strtolower($language['iso_code']) == 'fr') {
                $orderState->name[$language['id_lang']] = 'Autorisation acceptée';
            } else {
                $orderState->name[$language['id_lang']] = 'Authorization accepted';
            }
        }
        $orderState->module_name = $this->name;
        $orderState->send_email = false;
        $orderState->color = '#337ab7';
        $orderState->hidden = false;
        $orderState->delivery = false;
        $orderState->logable = false;
        $orderState->invoice = false;

        if ($orderState->id > 0) {
            $orderState->save();
            $createOrder = true;
        } else {
            $createOrder = $orderState->add();
        }

        if (file_exists(_PS_MODULE_DIR_ . $this->name . '/views/img/rsx/order_auth.gif')) {
            @copy(
                _PS_MODULE_DIR_ . $this->name . '/views/img/rsx/order_auth.gif',
                _PS_IMG_DIR_ . 'os/' . (int)$orderState->id . '.gif'
            );
        }

        if ($createOrder) {
            Configuration::updateValue(self::_CONFIG_ORDER_AUTH, $orderState->id);
        } else {
            $create = false;
        }


        if (!(Configuration::get(self::_CONFIG_ORDER_TEST) > 0)) {
            $orderState = new OrderState();
        } else {
            $orderState = new OrderState((int)Configuration::get(self::_CONFIG_ORDER_TEST));
        }

        $orderState->name = array();
        foreach (Language::getLanguages() as $language) {
            if (Tools::strtolower($language['iso_code']) == 'fr') {
                $orderState->name[$language['id_lang']] = 'TEST - Paiement accepté';
            } else {
                $orderState->name[$language['id_lang']] = 'TEST - Accepted payment';
            }
        }
        $orderState->module_name = $this->name;
        $orderState->send_email = false;
        $orderState->color = '#D4EA62';
        $orderState->hidden = false;
        $orderState->delivery = false;
        $orderState->logable = false;
        $orderState->invoice = false;

        if ($orderState->id > 0) {
            $orderState->save();
            $createOrder = true;
        } else {
            $createOrder = $orderState->add();
        }

        if (file_exists(_PS_MODULE_DIR_ . $this->name . '/views/img/rsx/order_test.gif')) {
            @copy(
                _PS_MODULE_DIR_ . $this->name . '/views/img/rsx/order_test.gif',
                _PS_IMG_DIR_ . 'os/' . (int)$orderState->id . '.gif'
            );
        }
        if ($createOrder) {
            Configuration::updateValue(self::_CONFIG_ORDER_TEST, $orderState->id);
        } else {
            $create = false;
        }
        return $create;
    }

    public function errorPaygreenApiClient($var)
    {
        if (isset($var->error)) {
            switch ($var->error) {
                case 0:
                    $this->context->controller->warnings[] = $this->l(
                        'Curl must be installed to use automatic connexion.'.
                        'Please install Curl or enter you Ids mannualy.'
                    );
                    break;
                case 1:
                    $this->context->controller->errors[] = $this->l(
                        'There is an error in the unique id or the private key'
                    );
                    break;
            }
            return true;
        }

        return false;
    }
}
