<?php
/**
* @package XenCentral Ad Server
* @author Skydevelop EU
* @copyright Drnoyan & Nalyan LDA, Portugal, EU
* @license http://www.dnf.pt/eula.html
* @link http://www.skydevelop.com
* @revision 97
* @version 2.0.0 beta 3 rev. 3
*/

class XenCentral_AdServer_Hooks extends XenForo_Model
{
    public static function initDependencies(XenForo_Dependencies_Abstract $dependencies, array $data)
    {
        if (self::_productDisabled()) {
            return;
        }
    }

    public static function loadModel($class, &$extend)
    {
        if (self::_productDisabled()) {
            return;
        }

        if($class=='XenForo_Model_Post') {
            $extend[]='XenCentral_AdServer_Model_XenForo_Post';
        } else if($class=='XenForo_Model_User') {
            $extend[]='XenCentral_AdServer_Model_XenForo_User';
        } else if ($class == 'XenForo_Model_Attachment') {
            $extend[] = 'XenCentral_AdServer_Model_XenForo_Attachment';
        }
    }

    public static function loadController($class, &$extend)
    {
        if (self::_productDisabled()) {
            return;
        }
    }

    public static function loadClass($class, &$extend)
    {
        if (self::_productDisabled()) {
            return;
        }

        if ($class == 'XenForo_ControllerHelper_ForumThreadPost') {
            $extend[] = 'XenCentral_AdServer_ControllerHelper_XenForo_ForumThreadPost';
        } else if($class=='XenForo_ViewPublic_Attachment_DoUpload') {
            $extend[] = 'XenCentral_AdServer_ViewPublic_XenForo_Attachment_DoUpload';
        } else if($class=='XenCentral_Framework_ViewAdmin_Attachment_DoUpload') {
            $extend[] = 'XenCentral_AdServer_ViewAdmin_Attachment_DoUpload';
        }
    }

    protected static function _productDisabled()
    {
        $options = Xenforo_Application::get('options');
        if (!$options->xcas_on) {
            return true;
        }

        return false;
    }

    public static function postView(XenForo_FrontController $fc, &$content)
    {
        if (self::_productDisabled()) {
            return;
        }
        if(class_exists('XenCentral_AdServer_Model_Capping', false)) {
            // if not already loaded it could not contain cookies
            self::_getModelFromCache('XenCentral_AdServer_Model_Capping')->sendCookies();
        }
    }

    public static function preView(XenForo_FrontController $fc, XenForo_ControllerResponse_Abstract &$controllerResponse, XenForo_ViewRenderer_Abstract &$viewRenderer,
                                   array &$containerParams)
    {
        // activate XenCentral tab in admin navigation menu
        self::_activateXenCentralTab($fc, $controllerResponse, $viewRenderer, $containerParams);

        if (self::_productDisabled()) {
            return;
        }

        if($controllerResponse instanceof XenForo_ControllerResponse_View) {
            XenForo_Application::set('mainTemplateName', $controllerResponse->templateName);
        }
    }

    protected static function _activateXenCentralTab(XenForo_FrontController $fc, XenForo_ControllerResponse_Abstract &$controllerResponse,
                                                     XenForo_ViewRenderer_Abstract &$viewRenderer, array &$containerParams)
    {
        if ($fc->getRequest()->getParam('group_id', false) == 'xcas' || $fc->getRequest()->getParam('addon_id', false) == 'xcas') {
            $containerParams['majorSection'] = 'xencentral';
            $containerParams['minorSection'] = 'xcas';
        }
        if (
                $controllerResponse->controllerName == 'XenCentral_AdServer_ControllerAdmin_Zone'
                OR $controllerResponse->controllerName == 'XenCentral_AdServer_ControllerAdmin_Banner'
                OR $controllerResponse->controllerName == 'XenCentral_AdServer_ControllerAdmin_Main'
        ) {
            if ($containerParams['majorSection'] == 'xcas') {
                $containerParams['majorSection'] = 'xencentral';
                $containerParams['minorSection'] = 'xcas';
            }
        }
    }

    public static function templateCreate(&$templateName, array &$params, XenForo_Template_Abstract $template)
    {
        if (self::_productDisabled()) {
            return;
        }

        if ($templateName == 'PAGE_CONTAINER') {
            $template->preloadTemplate('xcas_account_sidebar');
            $template->preloadTemplate('xcas_profile_popup');
            $template->preloadTemplate('xcas_head_include');
            $template->preloadTemplate('xcas_zone_code');
            $template->preloadTemplate('xcas_request_script_code');
            $template->preloadTemplate('xcas_head_include');
            $template->preloadTemplate('xcas_profile_popup');
            $template->preloadTemplate('xcas_zone_code');

            // apply zone filtering by page container and user
            $locations=XenCentral_AdServer_LocationList::getInstance()->getLocationList();
            foreach($locations AS $location) {
                $template->preloadTemplate($location->getWrapper());
            }

            unset($locations);
        }
    }

    public static function templatePostRender($templateName, &$content, array &$containerData, XenForo_Template_Abstract $template)
    {
        if (self::_productDisabled()) {
            return;
        }

        if (
            $template instanceof XenForo_Template_Public
            AND (
                $templateName == 'PAGE_CONTAINER'
                OR (
                    XenForo_Application::isRegistered('mainTemplateName')
                    AND $templateName== XenForo_Application::get('mainTemplateName')
                )
            )
        ) {
            self::_getZoneModel()->applyPageFilters($template->getParams(), $template->getParams() + $containerData);
            self::_getZoneModel()->applyUserFilters(XenForo_Visitor::getInstance()->toArray());
            self::_getZoneModel()->processPlaceholders($template, $content);
        }

        if ($templateName == 'option_list') {
            $group = $template->getParam('group');
            if ($group['group_id'] == 'xcfw') {
                // define tabs and attach framework template
                $tabs = array(
                    new XenForo_Phrase('xcfw_option_tab_general'),
                    new XenForo_Phrase('xcfw_option_tab_skrill_configuration')
                );

                foreach ($tabs AS $key => $tab) {
                    $tabs[$key] = $tab->render();
                }

                $content .= $template->create('xcfw_option_tabs', array(
                            'tabs' => json_encode($tabs),
                            'id' => $group['group_id'] . 'Tabs'
                        ) + $template->getParams());
            }
        }
    }

    public static function executeTemplateHooks($hookName, &$contents, array $hookParams, XenForo_Template_Abstract $template)
    {
        if (self::_productDisabled()) {
            return;
        }

        self::_normalizeHookParams($hookName, $hookParams, $template);

        switch ($hookName) {
            case 'account_wrapper_sidebar':
                if (XenCentral_AdServer_Permissions::canUse()) {
                    $contents = str_replace(
                        '<!-- slot: pre_settings -->',
                            $template->create('xcas_account_sidebar',
                                $template->getParams()
                                +XenCentral_AdServer_Permissions::getPermissions()
                                    +array(
                                    'showSidebar'=> self::_getOptionsModel()->showAccountSidebar(),
                                    'showSiteZones'=> self::_getOptionsModel()->showSiteZones()
                                )
                            ) .
                            '<!-- slot: pre_settings -->',
                        $contents
                    );
                }
                break;
            case 'footer_after_copyright':
                if ($copyrightInfo = XenCentral_Framework_Hooks::getProductCopyright('xcas')) {
                    $contents .= $template->create('xcfw_copyright', $copyrightInfo);
                }
                break;
            case 'navigation_visitor_tab_links1':
                if (XenCentral_AdServer_Permissions::canUse() AND self::_getOptionsModel()->add_in_user_popup()) {
                    $contents .= $template->create('xcas_profile_popup');
                }
                break;
            case 'page_container_head':
                $contents .= $template->create('xcas_head_include');
                break;
        }

        if(XenCentral_AdServer_Permissions::isExcludedUsergroup()) {
            return;
        }

        static $allActiveZones;
        
        if (is_array(XenCentral_AdServer_Model_Zone::$zoneCache)) {
            $allActiveZones = XenCentral_AdServer_Model_Zone::$zoneCache;
        } else {
            if (is_null($allActiveZones)) {
                $allActiveZones = self::_getZoneModel()->getActiveZones();
            }
        }

        if(empty($allActiveZones)) {
            return;
        }

        // get active zones
        $zoneIds = self::_getZoneModel()->getHookRelatedZones($hookName);

        if(empty($zoneIds)) {
            return;
        }

        $hookSpecificLocations = XenCentral_AdServer_LocationList::getInstance()->getLocationsByHookName($hookName);

        $customHookLocation = XenCentral_AdServer_LocationList::getInstance()->getCustomHookLocation();
        $customHookLocationId=$customHookLocation->getLocationId();

        foreach (array('prepend', 'append', 'callback') AS $modificationMode) {
            $callbackLocations = array();
            $zoneWrappers = array();
            $activeZones = array();
            // check if any zone has any active banner for this modification type and location
            foreach ($zoneIds AS $zoneId) {
                if(empty($allActiveZones[$zoneId])) {
                    continue;
                }

                $zone =& $allActiveZones[$zoneId];
                $customHookLocations=array();
                // get custom hooks and add to default ones
                $locationData = $zone->getLocationData($customHookLocationId);
                if ($locationData) {
                    foreach ($locationData['hooks'] AS $hookData) {
                        if (!$hookData['hook_name'] OR $hookData['hook_name'] != $hookName) {
                            continue;
                        }
                        /** @var XenCentral_AdServer_Locations_CustomHook $locationClone */
                        $locationClone = clone $customHookLocation;
                        if (!empty($hookData['warpper_template'])) {
                            $locationClone->setWrapper($hookData['warpper_template']);
                        }
                        $locationClone->setHookName($hookData['hook_name']);
                        $locationClone->setModificationMode($hookData['modification_type']);
                        $locationClone->prepareFromData($locationData);
                        $locationClone->setLocationid('custom_hook_'.rand());
                        $customHookLocations[] = $locationClone;
                    }
                }
                $combinedLocations=array_merge($customHookLocations, $hookSpecificLocations);
                if ($combinedLocations) {
                    foreach ($combinedLocations AS $hookSpecificLocation) {
                        /** @var XenCentral_AdServer_Locations_Hooks_Abstract $hookSpecificLocation */
                        $hookSpecificLocationId=$hookSpecificLocation->getLocationId();
                        if (
                                $hookSpecificLocation
                                AND $zone->hasLocation($hookSpecificLocationId)
                        ) {
                            $locationData = $zone->getLocationData($hookSpecificLocationId);
                            $hookSpecificLocation->prepareFromData($locationData);
                        } else if(($hookSpecificLocation instanceof XenCentral_AdServer_Locations_CustomHook)==false) {
                            // this is not a custom hook and does not have any date for the zone
                            continue;
                        }
                        $hookSpecificLocation->setHookParams($hookParams);
                        $hookSpecificLocation->setTemplate($template);

                        if ($hookSpecificLocation->getModificationMode() == $modificationMode) {
                            if(!$hookSpecificLocation->preCheck()) {
                                continue;
                            }
                            $activeZones[$zone->getZoneId()] = $zone->getZoneId();
                            $zoneWrappers[$hookSpecificLocation->getWrapper()] = $hookSpecificLocation->getWrapper();
                            $callbackLocations[$hookSpecificLocationId] = $hookSpecificLocation;
                        }
                    }
                }

                unset($combinedLocations, $customHookLocations);
            }
            if ($activeZones) {
                $randomId = XenCentral_AdServer_Zone::getRandomId();
                $zoneData = array(
                    'randomId' => $randomId,
                    'zones' => $activeZones,
                    'linkParams' => array(
                        'randomId' => $randomId,
                        'zones' => implode(',', $activeZones)
                    )
                );
                $zoneData['wrappers'] = $zoneWrappers;

                // allow all registered locations to modify hook content
                foreach ($callbackLocations AS $callbackLocation) {
                    /** @var XenCentral_AdServer_Locations_Hooks_Abstract $callbackLocation */
                    $callbackLocation->modifyContent($contents, $zoneData);
                }

                unset($zoneData, $callbackLocations);
            }

        }
    }

    /**
     * @param $hookName
     * @param $hookParams
     * @param XenForo_Template_Abstract $template
     * Stores hook params passed into some hooks and adds them into others, which miss that params
     */
    protected static function _normalizeHookParams($hookName, &$hookParams, XenForo_Template_Abstract $template)
    {
        static $paramMapping,$paramParentList;
        if(is_null($paramMapping)) {
            $paramMapping=array(
                'message_user_info_avatar'=>array(
                    'params' => array(),
                    'children' => array(
                        'message_user_info_avatar'
                    ),
                    'renameParam' => array(
                        'user' => 'post'
                    )
                ),
                'message_user_info_extra'=>array(
                    'params' => array(),
                    'children' => array(
                        'message_user_info_extra'
                    ),
                    'renameParam' => array(
                        'user' => 'post'
                    )
                ),
                'message_user_info_text'=>array(
                    'params' => array(),
                    'children' => array(
                        'message_user_info_text'
                    ),
                    'renameParam' => array(
                        'user' => 'post'
                    )
                ),
                'message_content'=>array(
                    'params'=>array(),
                    'children'=>array(
                        'message_content'
                    ),
                    'renameParam'=>array(
                        'message'=>'post'
                    )
                ),
                'message_notices'=>array(
                    'params' => array(),
                    'children' => array(
                        'ad_message_body',
                        'ad_message_below'
                    ),
                    'renameParam'=>array(
                        'message'=>'post'
                    )
                ),
                'thread_view_pagenav_before' => array(
                    'params' => array(),
                    'children' => array(
                        'ad_thread_view_above_messages',
                        'ad_thread_view_below_messages'
                    )
                ),
                'forum_view_pagenav_before' => array(
                    'params' => array(),
                    'children' => array(
                        'ad_forum_view_above_thread_list',
                        'ad_forum_view_below_thread_list'
                    )
                ),
                'ad_member_view_below_avatar'=>array(
                    'params'=>array(),
                    'templateParam'=>'user',
                    'children'=>array(
                        'ad_member_view_below_avatar',
                        'ad_member_view_above_messages',
                        'member_view_info_block',
                        'ad_member_view_sidebar_bottom'
                    )
                )
            );
            $paramParentList=array();
            foreach($paramMapping AS $parentId=>$parentInfo) {
                foreach($parentInfo['children'] AS $childId) {
                    $paramParentList[$childId]=$parentId;
                }
            }
        }
        if (isset($paramMapping[$hookName])) {
            if (!empty($paramMapping[$hookName]['templateParam'])) {
                $paramMapping[$hookName]['params'][$paramMapping[$hookName]['templateParam']] = $template->getParam($paramMapping[$hookName]['templateParam']);
            }
            foreach($hookParams AS $k=>$v) {
                $paramMapping[$hookName]['params'][$k]=$v;
            }
            if(!empty($paramMapping[$hookName]['renameParam'])) {
                foreach($paramMapping[$hookName]['renameParam'] AS $oldName=>$newName) {
                    if(isset($hookParams[$oldName])) {
                        $paramMapping[$hookName]['params'][$newName]= $hookParams[$oldName];
                    }
                }
            }
        }
        if (isset($paramParentList[$hookName])) {
            $hookParams += $paramMapping[$paramParentList[$hookName]]['params'];
        }
    }

    /**
     * @return XenCentral_AdServer_Model_Zone
     */
    protected static function _getZoneModel()
    {
        return self::_getModelFromCache('XenCentral_AdServer_Model_Zone');
    }

    /**
     * Get options model
     * @return XenCentral_AdServer_Model_Options
     */
    protected static function _getOptionsModel()
    {
        return self::_getModelFromCache('XenCentral_AdServer_Model_Options');
    }

    protected static function _getModelFromCache($model)
    {
        static $modelCacheArray;

        if (isset($modelCacheArray[$model])) {
            return $modelCacheArray[$model];
        }

        $modelCacheArray[$model] = XenForo_Model::create($model);

        return $modelCacheArray[$model];
    }
}