<?php
 /**
 * This Software is the property of Data Development and is protected
 * by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * http://www.shopmodule.com
 *
 * @copyright © Dł Data Development, Thomas Dartsch
 * @author    Dł Data Development - Daniel Seifert <ds@shopmodule.com>
 * @link      http://www.oxidmodule.com
 */

class d3_alist_extsearch extends d3_alist_extsearch_parent
{
    private $_sModId = 'd3_extsearch'; // in ModCfg used module ident
    public $oD3SearchHandler = null;
    public $oD3OwnSearchHandler = null;
    /** @var oxVendorList */
    public $oSearchVendorList;
    /** @var oxManufacturerList */
    public $oSearchManufacturerList;
    public $aPriceSteps;
    public $aPriceSelector;
    public $sPriceSelector;
    protected $_sSearchVendor;
    protected $_sSearchManufacturer;
    protected $_sD3AdditionalParams = null;
    protected $_aSelectedAttributes;
    protected $_aD3AdditionalSearchParams = array('filterparam', 'searchmanufacturer', 'searchvendor');
    private $_blUseAlistFilter;
    public $aSearchAttribList = array();

    /**
     * @return string
     */
    public function render()
    {
        if ($this->_d3UseAlistFilters()) {
            $this->_d3AddAllTplParams();
        }

        return parent::render();
    }

    protected function _d3AddAllTplParams()
    {
        // set TPL parameter, if category and vendor selectlists on frontends left side shouldn't changed
        if (oxRegistry::getConfig()->getRequestParameter('isextsearch') == 'true') {
            $this->addTplParam(
                'additionalparams',
                $this->getViewDataElement('additionalparams') . '&isextsearch=alist'
            );
            $this->addTplParam('isextsearch', 'alist');
        }

        // set price selection params
        $this->d3GetPriceSelectors();

        if (($sSearchVendor = $this->getSearchVendor())) {
            $this->addTplParam(
                'additionalparams',
                $this->getViewDataElement('additionalparams') . "&amp;searchvendor=" . urlencode(
                    $sSearchVendor
                )
            );
        }

        if (($sSearchManufacturer = $this->getSearchManufacturer())) {
            $this->addTplParam(
                'additionalparams',
                $this->getViewDataElement('additionalparams') . "&amp;searchmanufacturer=" . urlencode(
                    $sSearchManufacturer
                )
            );
        }

        // add price selectors parameter to url variables
        $this->getAttributeFilters();

        // send browser plugin status to smarty
        $this->addTplParam('blSearchPluginLink', $this->d3GetSet()->getValue('blExtSearch_enablePluginLink'));
    }

    /**
     * @param oxcategory $oCategory
     *
     * @return array
     */
    protected function _loadArticles($oCategory)
    {
        /** @var oxarticlelist $oArtList */
        $oArtList = parent::_loadArticles($oCategory);

        if ($this->_d3UseAlistFilters()) {
            if (false == method_exists($oCategory, 'isPriceCategory')  // in case of manufacturerlist class
                || false == $oCategory->isPriceCategory()
            ) {
                if (strtolower($this->getClassName()) == 'alist') {
                    $_POST["searchcnid"] = oxRegistry::getConfig()->getRequestParameter('cnid');
                } elseif (strtolower($this->getClassName()) == 'manufacturerlist') {
                    $_POST["searchmanufacturer"] = oxRegistry::getConfig()->getRequestParameter('mnid');
                } elseif (strtolower($this->getClassName()) == 'vendorlist') {
                    $sActCat = oxRegistry::getConfig()->getRequestParameter('cnid');
                    $_POST["searchvendor"] = (getStr()->preg_match('/^v_.?/i', $sActCat)) ? str_replace(
                        'v_',
                        '',
                        $sActCat
                    ) : null;
                } elseif (strtolower($this->getClassName()) == 'tag') {
                    // ToDo: add tag parameter for article list filter in search and articlelists
                }

                if (strtolower($this->getClassName()) != 'vendorlist') {
                    $this->_getVendorList();
                }
                if (strtolower($this->getClassName()) != 'manufacturerlist') {
                    $this->_getManufacturerList();
                }
                /*
                            if (strtolower($this->getClassName()) != 'alist') {
                // ToDo: add category selection
                                $this->_getCategoryList();
                            }
                */

                $this->_getAttributeList();
                $this->_getPriceSteps();

                $this->addTplParam('blD3ShowFilters', $this->d3GetShowFilters());
                $this->addTplParam('blD3HasSelectedFilters', $this->d3HasSelectedFilters());
            }
        }

        return $oArtList;
    }

    /**
     * @return bool
     */
    public function d3HasSelectedFilters()
    {
        if ($this->_d3UseAlistFilters()
            && (
                $this->getSearchManufacturer()
                || $this->getSearchVendor()
                || $this->_d3HasPriceSteps()
                || $this->_d3HasAttributeValues()
            )
        ) {
            return true;
        }

        return false;
    }

    /**
     * @return bool
     */
    protected function _d3HasPriceSteps()
    {
        $aPriceSteps = $this->d3getPriceSteps();
        if ($this->d3HasjQuerySlider()) {
            $blPriceStepSet = (isset($aPriceSteps['min']) && $aPriceSteps['min'] != 0)
                || (isset($aPriceSteps['max']) && $aPriceSteps['max'] != 0);
        } else {
            $blPriceStepSet = (bool) count($aPriceSteps);
        }

        return $blPriceStepSet;
    }

    /**
     * @return bool
     */
    protected function _d3HasAttributeValues()
    {
        $aSessionAttribs = oxRegistry::getSession()->getVariable('d3searchattrib');
        $aSessionMultiAttribs = oxRegistry::getSession()->getVariable('d3searchattribmulti');
        /** @var d3_alist_extsearch $oActView */
        $oActView = oxRegistry::getConfig()->getActiveView();

        $aAttribMultiSelector = oxRegistry::getConfig()->getRequestParameter('d3searchattribmultiselector');
        if (false == is_array($aAttribMultiSelector)) {
            $aAttribMultiSelector = array();
        }

        $aSearchAttrib = oxRegistry::getConfig()->getRequestParameter('d3searchattrib');
        $aSessionSearchAttrib = $aSessionAttribs[$oActView->d3getFilterPageId()];
        if (isset($aSearchAttrib) && is_array($aSearchAttrib)) {
            foreach ($aSearchAttrib as $sId => $sValue) {
                if ((count($aAttribMultiSelector)
                    && isset($aAttribMultiSelector[$sId])
                    && $aAttribMultiSelector[$sId] == 'on')
                    || ($sValue == '' || $sValue == $this->_d3GetSearchHandler()->d3GetDeselectValue())
                ) {
                    unset($aSearchAttrib[$sId]);
                    unset($aSessionSearchAttrib[$sId]);
                }
            }
        }

        $aMultiSearchAttrib = oxRegistry::getConfig()->getRequestParameter('d3searchattribmulti');
        $aSessionMultiSearchAttrib = $aSessionMultiAttribs[$oActView->d3getFilterPageId()];
        if (isset($aMultiSearchAttrib) && is_array($aMultiSearchAttrib)) {
            foreach ($aMultiSearchAttrib as $sId => $aValues) {
                if (false == count($aAttribMultiSelector)
                    || false == isset($aAttribMultiSelector[$sId])
                    || $aAttribMultiSelector[$sId] != 'on'
                    || false == is_array($aValues)
                    || false == count($aValues)
                ) {
                    unset($aMultiSearchAttrib[$sId]);
                    unset($aSessionMultiSearchAttrib[$sId]);
                } else {
                    foreach ($aValues as $sValueId => $sValue) {
                        if ($sValue == '' || $sValue == $this->_d3GetSearchHandler()->d3GetDeselectValue()) {
                            unset($aMultiSearchAttrib[$sId][$sValueId]);
                            unset($aSessionMultiSearchAttrib[$sId][$sValueId]);
                        }
                    }
                }

                if (false == count($aMultiSearchAttrib[$sId])) {
                    unset($aMultiSearchAttrib[$sId]);
                    unset($aSessionMultiSearchAttrib[$sId]);
                }
            }
        }

        return count($aSearchAttrib)
        || count($aSessionSearchAttrib)
        || count($aMultiSearchAttrib)
        || count($aSessionMultiSearchAttrib);
    }

    /**
     * @return bool
     */
    public function d3GetShowFilters()
    {
        if ($this->d3GetSet()->isActive()
            && $this->_d3UseAlistFilters()
            && (
                strtolower($this->getClassName()) == 'alist'
                || strtolower($this->getClassName()) == 'manufacturerlist'
                || strtolower($this->getClassName()) == 'vendorlist'
                // || strtolower($this->getClassName()) == 'tag'
            )
            && (
                count($this->d3getVendorList())
                || $this->getSearchVendor()
                || count($this->d3getManufacturerList())
                || $this->getSearchManufacturer()
                || $this->d3GetPriceSteps()
                || $this->d3GetAttributeList()
            )
        ) {
            return true;
        }

        return false;
    }

    /**
     * @return bool|string
     */
    public function getSearchVendor()
    {
        if ($this->_sSearchVendor === null) {
            // searching in vendor #671
            $this->_sSearchVendor = rawurldecode($this->getConfig()->getRequestParameter('searchvendor'));
        }

        return $this->_sSearchVendor;
    }

    /**
     * @return bool|string
     */
    public function getSearchManufacturer()
    {
        if ($this->_sSearchManufacturer === null) {
            // searching in vendor #671
            $this->_sSearchManufacturer = rawurldecode($this->getConfig()->getRequestParameter('searchmanufacturer'));
        }

        return $this->_sSearchManufacturer;
    }

    /**
     * @return array
     */
    public function getAttributeFilters()
    {
        if (null == $this->_aSelectedAttributes
            && $this->_d3UseAlistFilters()
        ) {
            $this->_aSelectedAttributes = $this->_d3GetSearchHandler()->getAttributeFilters();

            foreach ($this->_aSelectedAttributes as $sKey => $mValue) {
                if (is_array($mValue) && count($mValue)) {
                    foreach ($mValue as $iIdent => $sValue) {
                        $sAddStr = "&amp;d3searchattribmulti[$sKey][$iIdent]=" . urlencode(trim($sValue));
                        $this->_sD3AdditionalParams .= $sAddStr;
                        /*$this->addTplParam(
                            'additionalparams',
                            $this->getViewDataElement('additionalparams') . $sAddStr
                        );*/
                    }
                } elseif (is_string($mValue) && trim($mValue)) {
                    $sAddStr = "&amp;d3searchattrib[$sKey]=" . urlencode(trim($mValue));
                    $this->_sD3AdditionalParams .= $sAddStr;
                    //$this->addTplParam('additionalparams', $this->getViewDataElement('additionalparams') . $sAddStr);
                }
            }

            $this->addTplParam('aD3AttribFilters', $this->_aSelectedAttributes);
        }

        return $this->_aSelectedAttributes;
    }

    /**
     * @return array
     */
    public function d3GetPriceSelectors()
    {
        if (false == $this->_d3UseAlistFilters()) {
            return array();
        }

        $mPriceSelectors = oxRegistry::getConfig()->getRequestParameter('priceselector');

        if (is_array($mPriceSelectors)) {
            $this->aPriceSelector['min'] = $mPriceSelectors['min'];
            $this->aPriceSelector['max'] = $mPriceSelectors['max'];
            foreach ($this->aPriceSelector as $sKey => $sValue) {
                $this->aPriceSelector[$sKey] = str_replace(',', '.', $sValue);
            }
        } else {
            $this->sPriceSelector = str_replace(',', '.', $mPriceSelectors);
        }

        $this->_setPriceSelectorValues();

        return array(
            'sPriceSelector' => $this->sPriceSelector,
            'aPriceSelector' => $this->aPriceSelector
        );
    }

    /**
     * set url extensions and smarty variables, if price selector is chosen
     */
    protected function _setPriceSelectorValues()
    {
        // price selectors original values
        if ($this->d3HasjQuerySlider()
            && oxRegistry::getConfig()->getRequestParameter('priceselector')
            && ($aPSOV = oxRegistry::getConfig()->getRequestParameter('d3psov'))
        ) {
            if (isset($aPSOV) && is_array($aPSOV)) {
                foreach ($aPSOV as $sKey => $sValue) {
                    $this->_sD3AdditionalParams .= "&amp;d3psov[".$sKey."]=" . urlencode($sValue);
                    $this->addTplParam(
                        'additionalparams',
                        $this->getViewDataElement('additionalparams') . "&amp;d3psov[".$sKey."]=" . urlencode($sValue)
                    );
                };
            }
        }

        if ($this->d3HasjQuerySlider()
            && is_array($this->aPriceSelector)
        ) {
            $this->addTplParam(
                'submpriceselectors',
                array('min' => $this->aPriceSelector['min'] * 100, 'max' => $this->aPriceSelector['max'] * 100)
            );
            $this->addTplParam('priceselector', implode('-', $this->aPriceSelector));
            $this->_sD3AdditionalParams .= "&amp;priceselector=" . urlencode(implode('-', $this->aPriceSelector));
            $this->addTplParam(
                'additionalparams',
                $this->getViewDataElement('additionalparams') . "&amp;priceselector=" . urlencode(
                    implode('-', $this->aPriceSelector)
                )
            );
        } elseif ($this->sPriceSelector) {
            $this->addTplParam('priceselector', $this->sPriceSelector);
            $this->_sD3AdditionalParams .= "&amp;priceselector=" . urlencode($this->sPriceSelector);
            $this->addTplParam(
                'additionalparams',
                $this->getViewDataElement('additionalparams') . "&amp;priceselector=" . urlencode($this->sPriceSelector)
            );
        }
    }

    /**
     * @return array
     */
    public function getPriceFilters()
    {
        return $this->_d3GetSearchHandler()->getPriceSelectors();
    }

    /**
     * @return d3_cfg_mod
     */
    public function d3GetSet()
    {
        $oSet = d3_cfg_mod::get($this->_d3getModId());
        // set "allow search without searchparam"
        $oSet->setValue('blExtSearch_emptySearch', true);

        return $oSet;
    }

    /**
     * @return string
     */
    private function _d3getModId()
    {
        return $this->_sModId;
    }

    /**
     * performance, use a class wide instance
     *
     * @return d3_oxsearch_extsearch
     */
    protected function _d3GetSearchHandler()
    {
        if (!$this->oD3SearchHandler) {
            $this->oD3SearchHandler = oxNew('oxsearch');
        }

        return $this->oD3SearchHandler;
    }

    /**
     * performance, use a class wide instance
     *
     * @return d3_search
     */
    protected function _d3GetOwnSearchHandler()
    {
        if (!$this->oD3OwnSearchHandler) {
            $this->oD3OwnSearchHandler = oxNew('d3_search');
        }

        return $this->oD3OwnSearchHandler;
    }

    /**
     * generates a hit related vendor list and its further informations (counters etc.)
     */
    protected function _getVendorList()
    {
        if (false == $this->d3GetSet()->isActive()
            || false == $this->_d3UseAlistFilters()
            || false == $this->d3GetSet()->getValue('blExtSearch_showVendorList')
        ) {
            return;
        }

        // if not all vendors were shown, set state in session (shop wide access required)
        if (oxRegistry::getConfig()->getRequestParameter('showall_vendors') == '1') {
            oxRegistry::getSession()->setVariable('showall_vendors', '1');
        } elseif (oxRegistry::getConfig()->getRequestParameter('showall_vendors') == '0') {
            oxRegistry::getSession()->setVariable('showall_vendors', '0');
        }

        if ($this->d3GetSet()->d3getLog() && $this->d3GetSet()->getValue('oxismodulelog')) {
            $this->d3GetSet()->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                "",
                "generating vendor list"
            );
        }

        // calls database query execution
        $this->oSearchVendorList = $this->_d3GetSearchHandler()->getSearchVendors();

        // decides, if an "extend" button (or a "less" button) is required for vendor list view
        if ($this->getSearchViewListType() == 'linklist'
            && $this->oSearchVendorList
            && $this->oSearchVendorList->count() == $this->d3GetSet()->getValue('iExtSearch_smallListItems')
        ) {
            // "more" button required
            $this->addTplParam('limitedVendorSearch', true);
        } elseif ($this->getSearchViewListType() == 'linklist'
            && $this->oSearchVendorList
            && $this->oSearchVendorList->count() > $this->d3GetSet()->getValue('iExtSearch_smallListItems')
        ) {
            // "less" button required
            $this->addTplParam('limitedVendorButton', true);
        }

        // get vendors name, if one is selected
        if ($this->getSearchVendor()) {
            $this->addTplParam(
                'sSelectedVendor',
                $this->_d3GetOwnSearchHandler()->getVendorTitle($this->getSearchVendor())
            );

            $this->addTplParam('sSelectedVendorId', $this->getSearchVendor());
        }
    }

    /**
     * Template variable getter. Returns hits related vendor list (generating in $this->_getVendorList() above)
     *
     * @return oxvendorlist
     */
    public function d3GetVendorList()
    {
        if (isset($this->oSearchVendorList)
            && $this->oSearchVendorList
            && $this->oSearchVendorList instanceof oxVendorList
            && $this->oSearchVendorList->count()
        ) {
            return $this->oSearchVendorList;
        }

        $oVendorList = oxNew('oxvendorlist');

        return $oVendorList;
    }

    /**
     * generates a hit related manufacturer list and its further informations (counters etc.)
     */
    protected function _getManufacturerList()
    {
        if (false == $this->d3GetSet()->isActive()
            || false == $this->_d3UseAlistFilters()
            || false == $this->d3GetSet()->getValue('blExtSearch_showManufacturerList')
        ) {
            return;
        }

        // if not all manufacturers were shown, set state in session (shop wide access required)
        if (oxRegistry::getConfig()->getRequestParameter('showall_manufacturers') == '1') {
            oxRegistry::getSession()->setVariable('showall_manufacturers', '1');
        } elseif (oxRegistry::getConfig()->getRequestParameter('showall_manufacturers') == '0') {
            oxRegistry::getSession()->setVariable('showall_manufacturers', '0');
        }

        if ($this->d3GetSet()->d3getLog() && $this->d3GetSet()->getFieldData('oxismodulelog')) {
            $this->d3GetSet()->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                "",
                "generating manufacturer list"
            );
        }

        // calls database query execution
        $this->oSearchManufacturerList = $this->_d3GetSearchHandler()->getSearchManufacturers();

        // decides, if an "extend" button (or a "less" button) is required for manufacturer list view
        if ($this->getSearchViewListType() == 'linklist'
            && $this->oSearchManufacturerList
            && $this->oSearchManufacturerList->count() == $this->d3GetSet()->getValue('iExtSearch_smallListItems')
        ) {
            // "more" button required
            $this->addTplParam('limitedManufacturerSearch', true);
        } elseif ($this->getSearchViewListType() == 'linklist'
            && $this->oSearchManufacturerList
            && $this->oSearchManufacturerList->count() > $this->d3GetSet()->getValue('iExtSearch_smallListItems')
        ) {
            // "less" button required
            $this->addTplParam('limitedManufacturerButton', true);
        }

        // get manufacturers name, if one is selected
        if ($this->getSearchManufacturer()) {
            $this->addTplParam(
                'sSelectedManufacturer',
                $this->_d3GetOwnSearchHandler()->getManufacturerTitle($this->getSearchManufacturer())
            );
            $this->addTplParam(
                'sSelectedManufacturerId',
                $this->getSearchManufacturer()
            );
        }
    }

    /**
     * Template variable getter.  Returns hits related manufacturer list
     * (generating in $this->_getManufacturerList() above)
     *
     * @return oxmanufacturerlist
     */
    public function d3GetManufacturerList()
    {
        if (isset($this->oSearchManufacturerList)
            && $this->oSearchManufacturerList
            && $this->oSearchManufacturerList instanceof oxManufacturerList
            && $this->oSearchManufacturerList->count()
        ) {
            return $this->oSearchManufacturerList;
        }

        $oManufacturerList = oxNew('oxmanufacturerlist');

        return $oManufacturerList;
    }

    /**
     * generates a hit related attribute list
     */
    protected function _getAttributeList()
    {
        if (false == $this->d3GetSet()->isActive()
            || false == $this->_d3UseAlistFilters()
            || false == $this->d3GetSet()->getValue('blExtSearch_showAttributeList')
        ) {
            return;
        }

        if ($this->d3GetSet()->d3getLog()
            && $this->d3GetSet()->getFieldData('oxismodulelog')
        ) {
            $this->d3GetSet()->d3getLog()->log(
                d3log::INFO,
                __CLASS__,
                __FUNCTION__,
                __LINE__,
                "",
                "generating attribute list"
            );
        }

        // calls database query execution
        $this->aSearchAttribList = $this->_d3GetSearchHandler()->getSearchAttributes();
    }

    /**
     * Template variable getter. Returns hits related attribute list (generating in $this->_getAttributeList())
     *
     * @return array
     */
    public function d3GetAttributeList()
    {
        if (isset($this->aSearchAttribList) && $this->aSearchAttribList && count($this->aSearchAttribList)) {
            return $this->aSearchAttribList;
        }

        return array();
    }

    /**
     * @param $sAttrId
     *
     * @return bool
     */
    public function d3AttributeFilterUseMultipleValues($sAttrId)
    {
        return $this->_d3GetSearchHandler()->d3AttributeFilterUseMultipleValues($sAttrId);
    }

    /**
     * generates a hit related price step list
     */
    protected function _getPriceSteps()
    {
        if (false == $this->d3GetSet()->isActive()
            || false == $this->_d3UseAlistFilters()
            || false == $this->d3GetSet()->getValue('blExtSearch_showPriceSelector')
        ) {
            return;
        }

        $this->aPriceSteps = $this->_d3GetSearchHandler()->getPriceSteps();

        // adds used price selector values
        if ($this->d3HasjQuerySlider()
            && is_array($this->aPriceSelector)
        ) {
            $this->addTplParam('sSelectedPriceStep', implode('-', $this->aPriceSelector));
        } elseif ($this->sPriceSelector) {
            $this->addTplParam('sSelectedPriceStep', $this->sPriceSelector);
        }
    }

    /**
     * Template variable getter. Returns price selector list (generated in $this->_getPriceSteps() above)
     *
     * @return array
     */
    public function d3getPriceSteps()
    {
        if (is_array($this->aPriceSteps) && count($this->aPriceSteps)) {
            return $this->aPriceSteps;
        }

        return array();
    }

    /**
     * @return bool
     */
    public function d3HasjQuerySlider()
    {
        if ($this->d3GetSet()->getValue('blExtSearch_showPriceSelector')
            && $this->d3GetSet()->getValue('sExtSearch_PriceSelectorsDispType') == 'jqslider'
        ) {
            /** @var oeThemeSwitcherThemeManager $oThemeManager */
            if (class_exists('oeThemeSwitcherThemeManager') == true
                && ($oThemeManager = new oeThemeSwitcherThemeManager())
                && $oThemeManager->isMobileThemeRequested()
            ) {
                return false;
            }

            return true;
        }

        return false;
    }

    /**
     * defines the presentment type, disabled in admin panel
     *
     * @return string
     */
    public function getSearchViewListType()
    {
        if ($this->d3GetSet()->getValue('sExtSearch_ListType')) {
            return $this->d3GetSet()->getValue('sExtSearch_ListType');
        }

        return 'dropdown';
    }

    /**
     * @param string $sUrl
     * @param int    $iPage
     * @param null   $iLang
     *
     * @return string
     */
    protected function _addPageNrParam($sUrl, $iPage, $iLang = null)
    {
        if (false == $this->_d3UseAlistFilters()) {
            return parent::_addPageNrParam($sUrl, $iPage, $iLang);
        }

        $sUrl = parent::_addPageNrParam($sUrl, $iPage, $iLang);

        $sUrlAdd = $this->getViewDataElement('additionalparams');

        if ($sUrlAdd) {
            $sUrl .= ((strpos($sUrl, '?') === false) ? '?' : '') . $sUrlAdd;
        }

        return $sUrl;
    }

    /**
     * returns additional url params for dynamic url building
     *
     * @return string
     */
    public function getDynUrlParams()
    {
        $sRet = parent::getDynUrlParams();

        if ($this->_d3UseAlistFilters()) {
            $sRet .= $this->_d3AddBaseUrlParams();
        }

        return $sRet;
    }

    /**
     * Returns additional URL parameters which must be added to list products urls
     *
     * @return string
     */
    public function getAddUrlParams()
    {
        $sAddParams = parent::getAddUrlParams();

        if ($this->_d3UseAlistFilters()) {
            $sAddParams .= $this->_d3AddBaseUrlParams();
        }

        return $sAddParams;
    }

    /**
     * Returns additional URL parameters which must be added to list products seo urls
     */
    public function getAddSeoUrlParams()
    {
        $sAddParams = parent::getAddUrlParams();

        if ($this->_d3UseAlistFilters()) {
            $sAddParams .= $this->_d3AddBaseUrlParams();
        }

        return $sAddParams;
    }

    /**
     * @return string
     */
    protected function _d3AddBaseUrlParams()
    {
        $sRet = '';
        if ($this->d3GetSet()->isActive()) {

            $sRet .= "&amp;isextsearch=alist";

            // price selectors original values
            if ($this->d3HasjQuerySlider()
                && oxRegistry::getConfig()->getRequestParameter('priceselector')
                && ($aPSOV = oxRegistry::getConfig()->getRequestParameter('d3psov'))
            ) {
                if (isset($aPSOV) && is_array($aPSOV)) {
                    foreach ($aPSOV as $sKey => $sValue) {
                        $sRet .= "&amp;d3psov[".$sKey."]=" . urlencode($sValue);
                    };
                }
            }

            // adds used price selector values
            if ($this->d3HasjQuerySlider()
                && is_array($this->aPriceSelector)
            ) {
                $sRet .= "&amp;priceselector=" . urlencode(implode('-', $this->aPriceSelector));
            } elseif ($this->sPriceSelector) {
                $sRet .= "&amp;priceselector=" . urlencode($this->sPriceSelector);
            }

            if (is_array($this->getD3AdditionalSearchParamList()) && count($this->getD3AdditionalSearchParamList())) {
                foreach ($this->getD3AdditionalSearchParamList() as $sAddSearchParam) {
                    $sParamValue = oxRegistry::getConfig()->getRequestParameter($sAddSearchParam);
                    if ($sParamValue) {
                        $sRet .= "&amp;" . $sAddSearchParam . "=" . urlencode($sParamValue);
                    }
                }
            }
        }

        return $sRet;
    }

    /**
     * Returns array of params => values which are used in hidden forms and as additional url params
     *
     * @return array
     */
    public function getNavigationParams()
    {
        $aParams = parent::getNavigationParams();

        if ($this->d3GetSet()->isActive()
            && $this->_d3UseAlistFilters()
        ) {
            $aParams['searchparam'] = htmlspecialchars(
                html_entity_decode(oxRegistry::getConfig()->getRequestParameter('searchparam'))
            );

            if ($this->d3HasjQuerySlider()
                && oxRegistry::getConfig()->getRequestParameter('priceselector')
                && ($aPSOV = oxRegistry::getConfig()->getRequestParameter('d3psov'))
            ) {
                if (isset($aPSOV) && is_array($aPSOV)) {
                    foreach ($aPSOV as $sKey => $sValue) {
                        $aParams['d3psov['.$sKey.']'] = urlencode($sValue);
                    };
                }
            }

            // adds used price selector values
            if ($this->d3HasjQuerySlider()
                && is_array($this->aPriceSelector)
            ) {
                $aParams['priceselector'] = implode('-', $this->aPriceSelector);
            } elseif ($this->sPriceSelector) {
                $aParams['priceselector'] = $this->sPriceSelector;
            }

            if (is_array($this->getD3AdditionalSearchParamList()) && count($this->getD3AdditionalSearchParamList())) {
                foreach ($this->getD3AdditionalSearchParamList() as $sAddSearchParam) {
                    $sParamValue = oxRegistry::getConfig()->getRequestParameter($sAddSearchParam);
                    if ($sParamValue) {
                        $aParams[$sAddSearchParam] = urlencode($sParamValue);
                    }
                }
            }
        }

        return $aParams;
    }

    /**
     * @return array
     */
    public function getD3AdditionalSearchParamList()
    {
        return $this->_aD3AdditionalSearchParams;
    }

    /**
     * @return string
     */
    public function d3GetDeselectValue()
    {
        return $this->_d3GetSearchHandler()->d3GetDeselectValue();
    }

    /**
     * @return mixed
     */
    public function d3getFilterPageId()
    {
        return oxRegistry::getConfig()->getRequestParameter('cnid');
    }

    /**
     * @param $sOptionTitle
     *
     * @return string
     */
    public function getMultipleSelectionTranslation($sOptionTitle)
    {
        return sprintf(oxRegistry::getLang()->translateString('D3_EXTSEARCH_EXT_MULTIPLESELECT'), $sOptionTitle);
    }

    /**
     * @return string
     */
    public function getPriceSliderInfoMinValue()
    {
        $dMin        = 0;
        $aPriceSteps = $this->d3getPriceSteps();
        if (count($aPriceSteps)) {
            $dMin = $aPriceSteps['min'];
        }

        $dMin = sprintf('%.2f', $dMin / 100);

        return $dMin;
    }

    /**
     * @return string
     */
    public function getPriceSliderInfoMaxValue()
    {
        $dMax        = 0;
        $aPriceSteps = $this->d3getPriceSteps();

        if (count($aPriceSteps)) {
            $dMax = $aPriceSteps['max'];
        }

        $dMax = sprintf('%.2f', $dMax / 100);

        return $dMax;
    }

    /**
     * @return string
     */
    public function getPriceSliderInputMinValue()
    {
        $dMin               = 0;
        $aPriceSteps        = $this->d3getPriceSteps();
        $aSubmPriceSelector = $this->getViewParameter('submpriceselectors');
        if (count($aSubmPriceSelector) && $aSubmPriceSelector['min']) {
            $dMin = $aSubmPriceSelector['min'];
        } elseif (count($aPriceSteps)) {
            $dMin = $aPriceSteps['min'];
        }

        $dMin = sprintf('%.2f', $dMin / 100);

        return $dMin;
    }

    /**
     * @return string
     */
    public function getPriceSliderInputMaxValue()
    {
        $dMax               = 0;
        $aPriceSteps        = $this->d3getPriceSteps();
        $aSubmPriceSelector = $this->getViewParameter('submpriceselectors');

        // per Formular gesetzte Werte
        if (count($aSubmPriceSelector) && $aSubmPriceSelector['max']) {
            $dMax = $aSubmPriceSelector['max'];
        } elseif (count($aPriceSteps)) {
            $dMax = $aPriceSteps['max'];
        }

        $dMax = sprintf('%.2f', $dMax / 100);

        return $dMax;
    }

    /**
     * @return array
     */
    public function d3getPriceLimits()
    {
        $aPriceSliderOriginalValues = oxRegistry::getConfig()->getRequestParameter('d3psov');

        if (isset($aPriceSliderOriginalValues) && is_array($aPriceSliderOriginalValues)) {
            return array(
                'min'   => str_replace('.', '', $aPriceSliderOriginalValues['min']),
                'max'   => str_replace('.', '', $aPriceSliderOriginalValues['max']),
            );
        }

        return $this->_d3GetSearchHandler()->getPriceLimits();
    }

    /**
     * @return string
     */
    public function getPriceSliderOriginalMinValue()
    {
        $aPriceSliderOriginalValues = oxRegistry::getConfig()->getRequestParameter('d3psov');
        if (isset($aPriceSliderOriginalValues)
            && is_array($aPriceSliderOriginalValues)
            && isset($aPriceSliderOriginalValues['min'])
        ) {
            return $aPriceSliderOriginalValues['min'];
        }

        return $this->getPriceSliderInputMinValue();
    }

    /**
     * @return string
     */
    public function getPriceSliderOriginalMaxValue()
    {
        $aPriceSliderOriginalValues = oxRegistry::getConfig()->getRequestParameter('d3psov');
        if (isset($aPriceSliderOriginalValues)
            && is_array($aPriceSliderOriginalValues)
            && isset($aPriceSliderOriginalValues['max'])
        ) {
            return $aPriceSliderOriginalValues['max'];
        }

        return $this->getPriceSliderInputMaxValue();
    }

    public function d3ClearFilter()
    {
        $this->_d3GetSearchHandler()->d3ClearFilters();
    }

    /**
     * @return bool
     */
    private function _d3UseAlistFilters()
    {
        if (null === $this->_blUseAlistFilter) {
            $this->_blUseAlistFilter = $this->d3GetSet()->getLicenseConfigData('blUseFilterInArticleLists', false)
                && $this->d3GetSet()->getValue('blExtSearch_useAListFilter');
        }
        return $this->_blUseAlistFilter;
    }

    /**
     * @return string
     */
    public function getAdditionalParams()
    {
        $this->_sAdditionalParams = parent::getAdditionalParams();

        if ($this->d3GetSet()->isActive()) {
            $this->_sAdditionalParams .= $this->_sD3AdditionalParams;

            if (!strstr($this->_sAdditionalParams, '&amp;isextsearch=true')) {
                $this->_sAdditionalParams .= '&amp;isextsearch=true';
            }
        }

        return $this->_sAdditionalParams;
    }
}
