<?php

/**
 * Class d3_order_heidelpay
 */
class d3_order_heidelpay extends d3_order_heidelpay_parent
{

    /**
     * Return-Klasse, die von der hp_resonse.php nach Aufruf order::execute() erhalten wurde (z.B. "thankyou")
     *
     * @var string
     */
    public $s3dsClassReturn;

    /**
     * Kontrollvariable fuer die Beendigung des 3DSecure-iFrames
     *
     * @var string
     */
    protected $_blIsHeidelpaySecureSuccess = false;

    protected $_sHeidelpaySecureiFrameTemplate = 'd3_d3heidelpay_views_azure_tpl_order_3ds_iframe.tpl';

    /**
     * array of years
     * @var array
     */
    protected $_aCreditYears = null;

    /**
     * class constructor, register d3_d3heidelpay_models_settings_heidelpay
     */
    public function __construct()
    {
        $settings = oxNew('d3_d3heidelpay_models_settings_heidelpay', d3_cfg_mod::get('d3heidelpay'));
        oxRegistry::set('d3_d3heidelpay_models_settings_heidelpay', $settings);
        parent::__construct();
    }

    /**
     * try to execute order
     * Returns the following action
     *
     * @throws oxException
     * @return string Return-Wert fuer weiteren Klassen-Shopaufruf
     */
    public function execute()
    {
        if (false == d3_cfg_mod::get('d3heidelpay')->isActive()) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'module is inactive',
                'module is inactive'
            );

            return parent::execute();
        }

        try {
            $mPayment = $this->getPayment();

            if (false === $mPayment) {
                d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                    d3log::WARNING,
                    __CLASS__,
                    __FUNCTION__,
                    __LINE__,
                    'payment is not set, execute parent',
                    print_r(var_export($mPayment, true), true)
                );

                return parent::execute();
            }

            $sUseHPStore = $this->getConfig()->getRequestParameter("usehpstore");
            if ($this->hasUserHPStoreData($mPayment->getId()) && $sUseHPStore) {
                d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                    d3log::INFO,
                    __CLASS__,
                    __FUNCTION__,
                    __LINE__,
                    'load user storage data',
                    $sUseHPStore
                );

                $userStoredData = oxNew('oxbase');
                $userStoredData->init('d3hpuid');
                if ($userStoredData->load($sUseHPStore)) {
                    $userStoredData->aDynValue          = unserialize($userStoredData->d3hpuid__oxpaymentdata->rawValue);
                    $userStoredData->aDynValue['oxuid'] = $userStoredData->getFieldData('oxuid');
                    $this->getSession()->setVariable('dynvalue', $userStoredData->aDynValue);
                    d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                        d3log::INFO,
                        __CLASS__,
                        __FUNCTION__,
                        __LINE__,
                        'set user storage data to session',
                        print_r(var_export($userStoredData->aDynValue, true), true)
                    );
                }

                return parent::execute();
            }

            /** @var d3_d3heidelpay_models_settings_heidelpay $settings */
            $settings       = oxRegistry::get('d3_d3heidelpay_models_settings_heidelpay');
            $oHeidelPayment = $settings->getPayment($mPayment);

            /** @var d3_d3heidelpay_controllers_order $controllerFacade */
            $controllerFacade = oxNew(
                'd3_d3heidelpay_controllers_order',
                oxRegistry::get('oxRegistry'),
                d3_cfg_mod::get('d3heidelpay'),
                oxNew('d3_d3heidelpay_models_factory', d3_cfg_mod::get('d3heidelpay'))
            );
            $mResult          = $controllerFacade->execute($oHeidelPayment);

            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'd3_d3heidelpay_controllers_order return value',
                print_r(var_export($mResult, true), true)
            );


            if (true === $mResult) {
                return parent::execute();
            }

            if (is_string($mResult)) {
                $urlparameter = $this->d3GetHeidelpayURLParameter();
                $urlparameter = http_build_query($urlparameter, '', '&');

                return $mResult . "&{$urlparameter}";
            }

        } catch (d3_d3heidelpay_models_verify_exception_notloggedinexception $oEx) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'exception handling',
                get_class($oEx) . PHP_EOL . $oEx->getMessage() . PHP_EOL . $oEx->getTraceAsString()
            );

            return 'user';
        } catch (d3_d3heidelpay_models_verify_exception_checksessionchallengeexception $oEx) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'exception handling',
                get_class($oEx) . PHP_EOL . $oEx->getMessage() . PHP_EOL . $oEx->getTraceAsString()
            );

            return '';
        } catch (d3_d3heidelpay_models_verify_exception_agbnotacceptedexception $oEx) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'exception handling',
                get_class($oEx) . PHP_EOL . $oEx->getMessage() . PHP_EOL . $oEx->getTraceAsString()
            );
            $this->_blConfirmAGBError = 1;

            return '';
        } catch (d3_d3heidelpay_models_verify_exception_customerinformationnotacceptedexception $oEx) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'exception handling',
                get_class($oEx) . PHP_EOL . $oEx->getMessage() . PHP_EOL . $oEx->getTraceAsString()
            );
            $this->_blConfirmCustInfoError = 1;

            return '';
        } catch (d3_d3heidelpay_models_payment_exception_PaymentNotReferencedToHeidelpayException $oEx) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'exception handling',
                get_class($oEx) . PHP_EOL . $oEx->getMessage() . PHP_EOL . $oEx->getTraceAsString()
            );

            return parent::execute();
        } catch (d3_d3heidelpay_models_settings_exception_emptypaymentlistexception $oEx) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'exception handling',
                get_class($oEx) . PHP_EOL . $oEx->getMessage() . PHP_EOL . $oEx->getTraceAsString()
            );

            return parent::execute();
        }

        /** @var oxException $exception */
        $exception = oxNew('oxException', oxRegistry::getLang()->translateString('d3heidelpay_execute_error'));
        oxRegistry::get("oxUtilsView")->addErrorToDisplay($exception);

        d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
            d3log::INFO,
            __CLASS__,
            __FUNCTION__,
            __LINE__,
            'exception handling',
            get_class($exception) . PHP_EOL . $exception->getMessage() . PHP_EOL . $exception->getTraceAsString()
        );

        return '';
    }

    /**
     * {@inheritdoc}
     */
    protected function _getNextStep($mSuccess)
    {
        if (false == d3_cfg_mod::get('d3heidelpay')->isActive()) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'module is inactive',
                'module is inactive'
            );

            return parent::_getNextStep($mSuccess);
        }

        if ($mSuccess === 'Show3DSecureFrame') {
            $sTemplateFor3DSecure = 'd3_d3heidelpay_views_azure_tpl_order_3ds_iframe.tpl';
            if ($this->d3CheckForMobileTheme()) {
                $sTemplateFor3DSecure = 'd3_d3heidelpay_views_mobile_tpl_order_3ds_iframe.tpl';
            }

            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'next step is Show3DSecureFrame',
                "set return: 'order?fnc=Show3DSecureFrame&heidelpaytemplate=" . $sTemplateFor3DSecure . "'"
            );

            return 'order?fnc=Show3DSecureFrame&heidelpaytemplate=' . $sTemplateFor3DSecure;
        }

        $sReturn = parent::_getNextStep($mSuccess);

        /** @var d3_d3heidelpay_controllers_order $controllerFacade */
        $controllerFacade = oxNew(
            'd3_d3heidelpay_controllers_order',
            oxRegistry::get('oxRegistry'),
            d3_cfg_mod::get('d3heidelpay'),
            oxNew('d3_d3heidelpay_models_factory', d3_cfg_mod::get('d3heidelpay'))
        );

        $mNextStep = $controllerFacade->getNextOrderStep($sReturn, $mSuccess);

        d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
            d3log::INFO,
            __CLASS__,
            __FUNCTION__,
            __LINE__,
            'return value',
            "success: $mSuccess, sReturn: $sReturn, nextstep: " . var_export($mNextStep, true)

        );

        return $mNextStep;

    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        $ret = parent::render();
        if (false === d3_cfg_mod::get('d3heidelpay')->isActive()) {
            return $ret;
        }
        $this->addTplParam('isHeidelpayDebugMode', (bool)d3_cfg_mod::get('d3heidelpay')->getValue('d3heidelpay_blTestmode'));

        $oHeidelpayViewConfig = oxNew(
            'd3_d3heidelpay_models_viewconfig',
            d3_cfg_mod::get('d3heidelpay'),
            oxRegistry::get('oxRegistry'),
            oxNew('d3_d3heidelpay_models_factory', d3_cfg_mod::get('d3heidelpay'))
        );

        $this->addTplParam('oHeidelpayViewConfig', $oHeidelpayViewConfig);
        $sHeidelpayTemplate = oxRegistry::getConfig()->getRequestParameter('heidelpaytemplate');

        if (false == empty($sHeidelpayTemplate)) {
            $this->_sThisTemplate = $sHeidelpayTemplate;
        }

        return $this->_sThisTemplate;
    }

    /**
     * Return route to payment if no d3 secure payment
     *
     * @return string partizielle rueckgabe der klasse
     */
    public function show3DSecureFrame()
    {
        if (false == d3_cfg_mod::get('d3heidelpay')->isActive()) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'module is inactive',
                'module is inactive'
            );

            return '';
        }

        /** @var d3_d3heidelpay_models_factory $oFactory */
        $oFactory = oxNew('d3_d3heidelpay_models_factory', d3_cfg_mod::get('d3heidelpay'));
        $sReturn  = '';

        // irgendein Wert nicht gesetzt oder falsch? Dann zurueck zu Schitt 3 !
        if (false == $oFactory->getSettings()->isSecurePayment(oxRegistry::get('oxRegistry'), $oFactory)) {
            $sReturn = 'payment?payerror=2';
        }

        d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
            d3log::INFO,
            __CLASS__,
            __FUNCTION__,
            __LINE__,
            'return value',
            var_export($sReturn, true)
        );

        return $sReturn;
    }

    /**
     * @return bool
     */
    public function d3CheckForMobileTheme()
    {
        $blIsMobile = false;
        if (class_exists('oeThemeSwitcherThemeManager') == true) {
            /** @var oeThemeSwitcherThemeManager $oThemeManager */
            $oThemeManager = new oeThemeSwitcherThemeManager();
            $blIsMobile    = $oThemeManager->isMobileThemeRequested();
        }

        return $blIsMobile;
    }

    /**
     * Template variable getter. Returns array of years for credit cards
     *
     * @return array
     */
    public function getCreditYears()
    {
        if ($this->_aCreditYears === null) {
            $this->_aCreditYears = false;

            $this->_aCreditYears = range(date('Y'), date('Y') + 10);
        }

        return $this->_aCreditYears;
    }

    //<editor-fold desc="TODO:3 ways with existing paymentdata possible. see /tests/acceptance/selenium/dudeWantToPay.graphml">
    /**
     * Returns true if user has stored payment data
     *
     * @param $sPaymentId
     *
     * @return bool
     */
    public function hasUserHPStoreData($sPaymentId)
    {
        if (false == d3_cfg_mod::get('d3heidelpay')->isActive()) {
            d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                'module is inactive',
                'module is inactive'
            );

            return false;
        }

        // keine Anzeige gespeicherter Registrierungsdaten erlauben?
        if (false == d3_cfg_mod::get('d3heidelpay')->getValue('d3heidelpay_blShowStoredHPData')) {
            return false;
        }

        return (bool)$this->getUserHPStoreID($sPaymentId);
    }

    /**
     * Returns user stored payment data
     *
     * @param $sPaymentId
     *
     * @return array
     */
    public function getUserHPStoreData($sPaymentId)
    {
        if (false == d3_cfg_mod::get('d3heidelpay')->isActive()) {
            return array();
        }

        $storeIds = $this->getUserHPStoreIDs($sPaymentId);
        if (empty($storeIds)) {
            return array();
        }

        $storedData = array();

        foreach($storeIds as $storeId) {
            /** @var oxbase $oUsrStoreData */
            $oUsrStoreData = oxNew('oxbase');
            $oUsrStoreData->init('d3hpuid');
            $oUsrStoreData->load($storeId['OXID']);

            $oUsrStoreData->aDynValue          = unserialize($oUsrStoreData->d3hpuid__oxpaymentdata->rawValue);
            $oUsrStoreData->aDynValue['oxuid'] = $oUsrStoreData->getFieldData('oxuid');
            $storedData[$storeId['OXID']] = $oUsrStoreData;
        }

        return $storedData;
    }

    /**
     * Returns id of user stored payment data
     *
     * @param $sPaymentId
     *
     * @return string
     */
    public function getUserHPStoreID($sPaymentId)
    {
        if (false == ($sUserID = $this->getSession()->getVariable("usr"))) {
            return '';
        }

        return oxDb::getDb()->getOne(
            "SELECT `oxid` FROM `d3hpuid` WHERE `oxuserid` = '$sUserID' AND `oxpaymentid` = '$sPaymentId'"
        );
    }
    /**
     * Returns id of user stored payment data
     *
     * @param $sPaymentId
     *
     * @return array
     */
    public function getUserHPStoreIDs($sPaymentId)
    {
        if (false == ($sUserID = $this->getSession()->getVariable("usr"))) {
            return array();
        }

        return oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->getAll(
            "SELECT `oxid` AS OXID FROM `d3hpuid` WHERE `oxuserid` = '$sUserID' AND `oxpaymentid` = '$sPaymentId'"
        );
    }
    //</editor-fold>

    /**
     * @return string
     */
    public function d3GetAfterStepTemplate()
    {
        $themeId = d3_cfg_mod::get('d3heidelpay')->getMappedThemeId();
        $blUseHPStore = $this->getConfig()->getRequestParameter("usehpstore");
        $oBasket      = $this->getBasket();
        $sPaymentid   = $oBasket->getPaymentId();

        if ($this->hasUserHPStoreData($sPaymentid) && is_null($blUseHPStore)) {
            return "d3_d3heidelpay_views_{$themeId}_tpl_storeduid.tpl";
        }

        return "d3_d3heidelpay_views_{$themeId}_tpl_order_iframe.tpl";
    }

    /**
     * @return string
     */
    public function d3PayWithStoreData()
    {

        $oBasket    = $this->getBasket();
        $sPaymentid = $oBasket->getPaymentId();

        $blUseHPStore = $this->getConfig()->getRequestParameter("usehpstore");
        if ($this->hasUserHPStoreData($sPaymentid) && $blUseHPStore) {
            return $this->execute();
        }

        return "";
    }

    public function d3GetHeidelpayPostparameter()
    {
        //fake User-Checkboxen
        $mPostFields = d3_cfg_mod::get('d3heidelpay')->getValue('d3_cfg_mod__d3heidelpay_orderExecutePostFields');
        $aPostFields = explode(PHP_EOL, $mPostFields);
        $aHeidelpayPostparameter = array();
        foreach ($aPostFields as $sFieldDefinition) {
            list($sFieldName, $sValue) = explode('=>', $sFieldDefinition);
            $aHeidelpayPostparameter[trim($sFieldName)] = trim($sValue);
        }
        return $aHeidelpayPostparameter;

    }

    protected function d3GetHeidelpayURLParameter()
    {
        //fake User-Checkboxen
        $mPostFields             = d3_cfg_mod::get('d3heidelpay')->getValue('d3_cfg_mod__d3heidelpay_additionalUrlParameter');
        $aPostFields             = explode(PHP_EOL, $mPostFields);
        $aHeidelpayPostparameter = array();
        foreach ($aPostFields as $sFieldDefinition) {
            list($sFieldName, $sValue) = explode('=>', $sFieldDefinition);
            $aHeidelpayPostparameter[trim($sFieldName)] = trim($sValue);
        }

        return $aHeidelpayPostparameter;
    }

    public function d3ValidateTransactionlogParameters()
    {
        $d3TransactionLogId = oxRegistry::getConfig()->getRequestParameter('d3trlgid');

        d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
            d3log::INFO,
            __CLASS__,
            __FUNCTION__,
            __LINE__,
            'Validate Transactionlog Parameters',
            '$d3TransactionLogId is '. $d3TransactionLogId
        );

        $controllerFacade = oxNew(
            'd3_d3heidelpay_controllers_order',
            oxRegistry::get('oxRegistry'),
            d3_cfg_mod::get('d3heidelpay'),
            oxNew('d3_d3heidelpay_models_factory', d3_cfg_mod::get('d3heidelpay'))
        );

        $return = $controllerFacade->validateTransactionlogParameters($this, $d3TransactionLogId);

        d3_cfg_mod::get('d3heidelpay')->d3getLog()->log(
            d3log::INFO,
            __CLASS__,
            __FUNCTION__,
            __LINE__,
            'return of Validate Transactionlog Parameters',
            'return is '. empty($return) ? 'order': $return
        );

        return $return;
    }

    public function d3GetTemplateName($templateName)
    {
        if (is_string($templateName)) {
            $sTemplate = d3_cfg_mod::get('d3heidelpay')->getMappedThemeId();

            return "d3_d3heidelpay_views_{$sTemplate}_tpl_{$templateName}.tpl";
        }

        return '';
    }

    public function getHeidelpayEasyCreditInformations()
    {
        $oBasket      = $this->getBasket();
        $sPaymentid   = $oBasket->getPaymentId();

        $oSettings = oxNew('d3_d3heidelpay_models_settings_heidelpay', d3_cfg_mod::get('d3heidelpay'));
        $oPayment  = oxNew('oxPayment');
        $oPayment->load($sPaymentid);
        if (false == $oSettings->isAssignedToHeidelPayment($oPayment)) {
            return null;
        }

        $oHeidelpayment = $oSettings->getPayment($oPayment);

        if ($oHeidelpayment instanceof d3_d3heidelpay_models_payment_easycredit) {
            $easyCreditParameters = array(
                'criterion_easycredit_amortisationtext',
                'criterion_easycredit_totalamount',
                'criterion_easycredit_accruinginterest',
                'criterion_easycredit_precontractinformationurl',
            );
            $criterionContainer = oxNew(
                'd3_d3heidelpay_models_containers_criterions',
                oxNew('d3_d3heidelpay_models_factory', d3_cfg_mod::get('d3heidelpay')),
                $easyCreditParameters
            );

            return $criterionContainer->getParameters();
        }

        return null;
    }
}

