<?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_ControllerPublic_Banner extends XenCentral_AdServer_ControllerPublic_Account
{
    /**
     * Display list of banners user owns
     */
    public function actionIndex()
    {
        return $this->responseReroute('XenCentral_AdServer_ControllerPublic_Zone', 'index');
    }

    public function actionCopyCode()
    {
        if (
                !XenCentral_AdServer_Permissions::canSeeEmbedButtonBanner()
                AND !XenCentral_AdServer_Permissions::isAdmin()
        ) {
            return $this->responseNoPermission();
        }

        $bannerId = $this->_input->filterSingle('bannerId', XenForo_Input::UINT);
        if (XenCentral_AdServer_Permissions::isAdmin()) {
            $banners = $this->_getBannerModel()->getAllBanners();
        } else {
            $banners = $this->_getBannerModel()->getUserBanners(XenForo_Visitor::getUserId());
        }
        if (!isset($banners[$bannerId])) {
            // should not happen
            return $this->responseNoPermission();
        }

        $zone = $this->_getZoneModel()->getZoneByIdFromCache($banners[$bannerId]['zoneId']);

        $viewParams = array(
                'banner' => $banners[$bannerId],
                'zone' => $zone,
                'explain' => new XenForo_Phrase('xcas_banner_embed_explain')
        );
        return $this->responseView('XenCentral_AdServer_ViewPublic_BannerCode', 'xcas_embed_wrapper', $viewParams);
    }

    public function actionActivate()
    {
        $banner = $this->_assertCorrectBanner();

        $banner = $this->_getBannerModel()->prepareForListing($banner);

        if ($banner['status'] == 'moderated') {
            return $this->_getIndexWrapper($this->responseMessage(new XenForo_Phrase(
                    'xcas_this_ad_is_waiting_for_approval'
            )));
        }

        $zone = $this->_getZoneModel()->getZoneByIdFromCache($banner['zoneId']);

        $zone->prepareZoneInformation();

        if ($zone->isCustomZone()) {
            if (!$zone->isZoneOwner(XenForo_Visitor::getUserId())) {
                return $this->responseNoPermission();
            }

            if ($banner['status'] == 'paused') {
                return $this->responseMessage(new XenForo_Phrase(
                        'xcas_you_need_credits_to_activate'
                ));
            }

            // activate the banner immediately
            $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Banner');
            $writer->setExistingData($banner['bannerId']);
            $writer->set('status', 'active');
            $writer->save();

            XenCentral_AdServer_Cron::updateBannerStatus($banner['bannerId']);

            $banner = $this->_getBannerModel()->getBannerById($banner['bannerId']);

            if ($banner['status'] == 'paused') {
                $message = new XenForo_Phrase('xcas_ad_is_activated_and_paused');
            } else {
                $message = new XenForo_Phrase('xcas_ad_is_activated');
            }

            return $this->responseRedirect(
                    XenForo_ControllerResponse_Redirect::RESOURCE_UPDATED,
                    XenForo_Link::buildPublicLink('ads/zone/custom'),
                    $message
            );
        }

        if (
                !$zone->isUserZone()
                OR !XenCentral_AdServer_Permissions::canCreateBanner()
        ) {
            // this should not happen
            return $this->_getIndexWrapper($this->responseNoPermission());
        }

        if (!$zone->getFreeSlots()) {
            return $this->_getIndexWrapper($this->responseMessage(new XenForo_Phrase('xcas_no_free_slots_available_expires_at_x', array(
                    'x' => $zone->getFirstExpirationDate()
            ))));
        }

        $packages = $zone['packages'];

        if (isset($packages[9999999])) {
            unset($packages[9999999]);
        }

        if (empty($packages)) {
            return $this->responseMessage(new XenForo_Phrase('xcas_administrator_did_not_specify_any_pricing_rules'));
        }

        $packages = $this->_getZoneModel()->preparePackages($packages);

        if ($this->isConfirmedPost()) {
            $packageId = $this->getInput()->filterSingle('package', XenForo_Input::UINT);
            if (!isset($packages[$packageId])) {
                // should not happen
                return $this->responseNoPermission();
            }

            $package = $packages[$packageId];

            $methodList = new XenCentral_PaymentApi_MethodList(
                    'ads',
                    'XenCentral_AdServer_ControllerPublic_Index',
                    new XenForo_Phrase('xcas_banner_activation_x', array('x' => $banner['bannerId'])),
                    $banner['bannerId'],
                    $package['price'],
                    $package['currency']
            );

            $methodList->setAdditionalInformation(array(
                    'package' => $package,
                    'banner' => $banner
            ));

            if ($paypalEmail = $this->_getOptionsModel()->getPaypalEmail()) {
                $methodList->addPayPal($paypalEmail, $this->_getOptionsModel()->debugMode());
            }

            $methodList->addManualMethod($this->_getOptionsModel()->debugMode());

            if (XenForo_Visitor::getInstance()->isSuperAdmin()) {
                $methodList->addLocalMethod();
            }

            $paymentApiErrors = array();

            $paymentApiForms = $methodList->getForms($paymentApiErrors);

            if (!empty($paymentApiErrors)) {
                if (XenForo_Visitor::getInstance()->isSuperAdmin()) {
                    return $this->responseError(implode('<br />', $paymentApiErrors));
                }
            }

            if (empty($paymentApiForms)) {
                return $this->responseMessage(new XenForo_Phrase('xcfw_no_payment_methods_configured'));
            }

            foreach ($paymentApiForms AS &$paymentMethodInfo) {
                $paymentMethodInfo['title'] = new XenForo_Phrase('xcfw_pay_via_' . $paymentMethodInfo['id']);
            }

            return $this->_getIndexWrapper(
                    $this->responseView('XenCentral_AdServer_ViewPublic_ConfirmActivateBanner', 'xcas_confirm_activate_banner', array(
                                    'forms' => $paymentApiForms,
                                    'banner' => $banner,
                                    'zone' => $zone,
                                    'package' => $package,
                                    'breadCrumbs' => $this->_getBreadCrumbs(new XenForo_Phrase('xcas_confirm_activate_banner')),
                            )
                    )
            );
        }

        return $this->_getIndexWrapper(
                $this->responseView('XenCentral_AdServer_ViewPublic_ActivateBanner', 'xcas_activate_banner', array(
                                'banner' => $banner,
                                'zone' => $zone,
                                'packages' => $packages,
                                'breadCrumbs' => $this->_getBreadCrumbs(new XenForo_Phrase('xcas_activate_banner_x', array('title' => $banner['title']))),
                        )
                )
        );
    }

    public function actionDeactivate()
    {
        $banner = $this->_assertCorrectBanner();

        $banner = $this->_getBannerModel()->prepareForListing($banner);

        if ($banner['status'] == 'inactive') {
            return $this->responseError(new XenForo_Phrase(
                    'xcas_the_banner_is_already_inactive'
            ));
        }

        $zone = $this->_getZoneModel()->getZoneByIdFromCache($banner['zoneId']);

        $zone->prepareZoneInformation();

        if ($zone->isCustomZone()) {
            if (!$zone->isZoneOwner(XenForo_Visitor::getUserId())) {
                return $this->responseNoPermission();
            }

            // deactivate the banner immediately
            $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Banner');
            $writer->setExistingData($banner['bannerId']);
            $writer->set('status', 'inactive');
            $writer->save();

            XenCentral_AdServer_Cron::updateBannerStatus($banner['bannerId']);

            return $this->responseRedirect(
                    XenForo_ControllerResponse_Redirect::RESOURCE_UPDATED,
                    XenForo_Link::buildPublicLink('ads/zone/custom'),
                    new XenForo_Phrase('xcas_banner_is_successfully_deactivated')
            );
        }

        if (
                !$zone->isUserZone()
                OR !XenCentral_AdServer_Permissions::canCreateBanner()
        ) {
            // this should not happen
            return $this->_getIndexWrapper($this->responseNoPermission());
        }

        if ($this->isConfirmedPost()) {
            $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Banner');
            $writer->setExistingData($banner['bannerId']);
            $writer->set('active_from', 0);
            $writer->set('active_to', 0);
            $writer->set('status', 'inactive');
            $writer->save();
            return $this->responseRedirect(
                    XenForo_ControllerResponse_Redirect::RESOURCE_UPDATED,
                    XenForo_Link::buildPublicLink('ads'),
                    new XenForo_Phrase('xcas_banner_is_successfully_deactivated')
            );
        }

        return $this->_getIndexWrapper(
                $this->responseView('XenCentral_AdServer_ViewPublic_DeActivateBanner', 'xcas_deactivate_banner', array(
                                'item' => $banner
                        )
                )
        );
    }

    public function actionDoImportRss()
    {
        $this->_assertPostOnly();

        $this->_assertManagePermissions();

        $import = $this->_input->filter(array(
                'zoneId' => XenForo_Input::UINT,
                'rss_url' => XenForo_Input::STRING
        ));

        $item = array();
        $item['zoneId'] = $import['zoneId'];

        $itemCount = $this->_input->filterSingle('item_count', XenForo_Input::UINT);

        $feedData = $this->getModelFromCache('XenForo_Model_Feed')->getFeedData($import['rss_url'], $ex);

        if (empty($feedData) OR empty($feedData['entries'])) {
            if ($ex) {
                $error = $ex->getMessage();
            } else {
                $error = new XenForo_Phrase('xcas_there_are_no_items_found_in_feed');
            }

            return $this->responseError($error);
        }

        $zones = $this->_getZoneModel()->getCustomZones(XenForo_Visitor::getUserId());
        if (!isset($zones[$item['zoneId']])) {
            return $this->responseNoPermission();
        }

        $zone = $zones[$item['zoneId']];

        $writers = array();
        $taggers = array();

        $errors = array();

        foreach ($feedData['entries'] AS $entry) {
            if ($itemCount == 0) {
                break;
            }

            $itemCount--;

            $writerIndex = count($writers);

            $title = $entry['title'];
            $link = $entry['link'];
            if (
                    !empty($entry['enclosure_url']) AND strpos($entry['enclosure_type'], 'image/') === 0
            ) {
                $image = $entry['enclosure_url'];
            } else {
                $image = '';
            }
            $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Banner');

            $item['user_id'] = XenForo_Visitor::getUserId();
            $item['image'] = '';

            if ($image) {
                $imageData = XenForo_Helper_Http::getClient($image)->request()->getBody();
                $imageName = basename($image);
                file_put_contents(XenForo_Application::getInstance()->getRootDir() . '/test_banner_images/' . $imageName, $imageData);

                $uploadedImage = new XenForo_Upload($imageName, XenForo_Application::getInstance()->getRootDir() . '/test_banner_images/' . $imageName);
                $uploadErrors = $this->_getZoneModel()->validateImage($uploadedImage, $zone['zoneId']);
                if ($uploadErrors) {
                    $errors = array_merge($errors, $uploadErrors);
                } else {
                    $item['image'] = $this->_getBannerModel()->saveImage($uploadedImage);
                }
            }

            if (XenForo_Application::getOptions()->get('xcas_banner_text_max_length') AND strlen($title) > XenForo_Application::getOptions()->get('xcas_banner_text_max_length')) {
                $title = substr($title, 0, XenForo_Application::getOptions()->get('xcas_banner_text_max_length') - 3) . '...';
            }

            $item['title'] = $title;
            $item['text'] = $title;
            $item['url'] = $link;

            $writer->bulkSet($item);

            if (XenCentral_AdServer_Permissions::canSkipModeration()) {
                if ($zone->isCustomZone()) {
                    // for user campaigns banners are activated immediately
                    $writer->set('status', 'active');
                } else {
                    $writer->set('status', 'inactive');
                }
            } else {
                $writer->set('status', 'moderated');
            }

            $writer->set('impressions_left', 0);

            $writer->preSave();

            $taggers[$writerIndex] = null;

            if ($this->_getBannerModel()->canEditTags($item)) {
                /** @var XenForo_Model_Tag $tagModel */
                $tagModel = $this->getModelFromCache('XenForo_Model_Tag');
                $taggers[$writerIndex] = $tagModel->getTagger('banner');

                $taggers[$writerIndex]->setPermissionsFromContext(array())
                        ->setTags($tagModel->splitTags(
                                $this->getInput()->filterSingle('tags', XenForo_Input::STRING)
                        ));
                $writer->mergeErrors($taggers[$writerIndex]->getErrors());
            }

            if ($writer->hasErrors()) {
                $errors = array_merge($errors, $writer->getErrors());
            } else {
                $writers[] = $writer;
            }
        }

        foreach ($writers AS $writerIndex => $writer) {
            $writer->save();
            $bannerId = $writer->get('bannerId');

            if ($taggers[$writerIndex]) {
                $taggers[$writerIndex]->setContent($bannerId, true);
                $taggers[$writerIndex]->save();
            }
        }

        // update banner statuses to reflect moderation status
        XenCentral_AdServer_Cron::updateBannerStatus();

        $redirectParams = array();

        return $this->responseRedirect(
                XenForo_ControllerResponse_Redirect::SUCCESS,
                $zone->isCustomZone() ? XenForo_Link::buildPublicLink('ads/zone/custom') : XenForo_Link::buildPublicLink('ads/zone/site'),
                null,
                $redirectParams
        );
    }

    public function actionImportRss()
    {
        $this->_assertManagePermissions();

        $defaultBanner = $this->_getBannerModel()->getDefaultBanner();

        $userZones = array(); // RSS allowed only in user campaigns
        $customZones = $this->_getZoneModel()->getCustomZones(XenForo_Visitor::getUserId());

        if (empty($userZones) AND empty($customZones)) {
            return $this->responseError(new XenForo_Phrase('xcas_there_are_no_user_zones_created'));
        }

        $zoneId = $this->getInput()->filterSingle('zoneId', XenForo_Input::UINT);

        if ($zoneId) {
            if (isset($userZones[$zoneId])) {
                $defaultBanner['zoneId'] = $zoneId;
            } else if (isset($customZones[$zoneId])) {
                $defaultBanner['zoneId'] = $zoneId;
            } else {
                return $this->responseError(new XenForo_Phrase('xcas_this_zone_is_not_available_for_user_banners'));
            }
        }

        $viewParams = array(
                'title' => new XenForo_Phrase('xcas_import_rss'),
                'item' => $defaultBanner,
                'canEditTags' => $this->_getBannerModel()->canEditTags($defaultBanner),
                'zoneOptions' => $this->_getZoneModel()->getZoneOptions($userZones),
                'customZoneOptions' => $this->_getZoneModel()->getZoneOptions($customZones),
                'breadCrumbs' => $this->_getBreadCrumbs(new XenForo_Phrase('xcas_add_banner')),
                'moderationMessage' => XenCentral_AdServer_Permissions::canSkipModeration() == false
        );

        return $this->_getIndexWrapper(
                $this->responseView('XenCentral_AdServer_ViewPublic_BannerAdd', 'xcas_import_rss', $viewParams)
        );
    }

    public function actionAdd()
    {
        $this->_assertManagePermissions();

        $defaultBanner = $this->_getBannerModel()->getDefaultBanner();

        $userZones = $this->_getZoneModel()->getUserZones();
        $customZones = $this->_getZoneModel()->getCustomZones(XenForo_Visitor::getUserId());

        if (empty($userZones) AND empty($customZones)) {
            return $this->responseError(new XenForo_Phrase('xcas_there_are_no_user_zones_created'));
        }

        $zoneId = $this->getInput()->filterSingle('zoneId', XenForo_Input::UINT);

        if (!$zoneId) {
            return $this->_getIndexWrapper(
                    $this->responseView('XenCentral_AdServer_ViewPublic_BannerAdd', 'xcas_choose_zone', array(
                            'breadCrumbs' => $this->_getBreadCrumbs(new XenForo_Phrase('xcas_add_banner')),
                            'zoneOptions' => $this->_getZoneModel()->getZoneOptions($userZones),
                            'customZoneOptions' => $this->_getZoneModel()->getZoneOptions($customZones),
                    ))
            );
        }

        $zone = false;

        if ($zoneId) {
            if (isset($userZones[$zoneId])) {
                $defaultBanner['zoneId'] = $zoneId;
                $zone = $userZones[$zoneId];
            } else if (isset($customZones[$zoneId])) {
                $defaultBanner['zoneId'] = $zoneId;
                $zone = $customZones[$zoneId];
            } else {
                return $this->responseError(new XenForo_Phrase('xcas_this_zone_is_not_available_for_user_banners'));
            }
        }

        $attachmentHash = null;

        $attachmentParams = $this->_getZoneModel()->getAttachmentParams($zone, array(
                'zone_id' => $zone['zoneId']
        ), null, null, $attachmentHash);


        $viewParams = array(
                'title' => new XenForo_Phrase('xcas_add_banner'),
                'zoneId' => $zoneId,
                'item' => $defaultBanner,
                'canEditTags' => $this->_getBannerModel()->canEditTags($defaultBanner),
                'zoneOptions' => $this->_getZoneModel()->getZoneOptions($userZones),
                'customZoneOptions' => $this->_getZoneModel()->getZoneOptions($customZones),
                'breadCrumbs' => $this->_getBreadCrumbs(new XenForo_Phrase('xcas_add_banner')),
                'moderationMessage' => XenCentral_AdServer_Permissions::canSkipModeration() == false,
                'attachmentParams' => $attachmentParams,
                'attachmentConstraints' => $this->_getBannerModel()->getUploadConstraints($zone),
        );

        return $this->_getIndexWrapper(
                $this->responseView('XenCentral_AdServer_ViewPublic_BannerAdd', 'xcas_add_banner', $viewParams)
        );
    }

    public function actionCropImage()
    {
        $attachment_id = $this->_input->filterSingle('attachment_id', XenForo_Input::UINT);

        $temp_hash = $this->_input->filterSingle('temp_hash', XenForo_Input::STRING);

        $attachment = $this->_getAttachmentModel()->getAttachmentById($attachment_id);

        if (!$attachment) {
            return $this->getNotFoundResponse();
        }

        $attachment=$this->_getAttachmentModel()->prepareAttachment($attachment);

        if (!$temp_hash OR $temp_hash != $attachment['temp_hash']) {
            return $this->getNotFoundResponse();
        }

        $zone_id=$this->_input->filterSingle('zoneId', XenForo_Input::UINT);

        if(!$zone_id) {
            return $this->getNotFoundResponse();
        }

        $errors=array();

        $attachment=$this->_getZoneModel()->cropAttachment(
                $zone_id,
                $attachment,
                $this->_input->filterSingle('x1', XenForo_Input::UNUM),
                $this->_input->filterSingle('y1', XenForo_Input::UNUM),
                $this->_input->filterSingle('w', XenForo_Input::UNUM),
                $this->_input->filterSingle('h', XenForo_Input::UNUM),
                $errors
        );

        if($errors OR $attachment==false) {
            return $this->responseError($errors);
        }

        $this->getRouteMatch()->setResponseType('json');

        return $this->responseView(
                'XenCentral_AdServer_ViewPublic_Banner_Crop',
                '',
                array(
                    'attachment'=>$attachment
                )
                );
    }

    public function actionEdit()
    {
        $item = $this->_assertCorrectBanner();

        if ($item['status'] == 'active' AND !XenCentral_AdServer_Permissions::canEditActiveBanner()) {
            return $this->responseNoPermission();
        }

        $item = $this->_getBannerModel()->prepareForListing($item);
        $zoneId= $item['zoneId'];
        $zone=$this->_getZoneModel()->getZoneByIdFromCache($zoneId);

        $attachmentHash = null;

        $attachmentParams = $this->_getZoneModel()->getAttachmentParams($zone, array(
                'zone_id' => $zone['zoneId'],
                'banner_id'=>$item['bannerId']
        ), null, null, $attachmentHash);

        $attachmentModel = $this->_getAttachmentModel();

        $attachments = $attachmentModel->getAttachmentsByContentId('banner', $item['bannerId']);

        $userZones = $this->_getZoneModel()->getUserZones();
        $customZones = $this->_getZoneModel()->getCustomZones(XenForo_Visitor::getUserId());

        $viewParams = array(
                'title' => new XenForo_Phrase('xcas_edit_banner'),
                'zoneId' => $zoneId,
                'zoneOptions' => $this->_getZoneModel()->getZoneOptions($userZones),
                'customZoneOptions' => $this->_getZoneModel()->getZoneOptions($customZones),
                'item' => $item,
                'canEditTags' => $this->_getBannerModel()->canEditTags($item),
                'breadCrumbs' => $this->_getBreadCrumbs($item['title']),
                'attachmentParams' => $attachmentParams,
                'attachmentConstraints' => $this->_getBannerModel()->getUploadConstraints($zone),
                'attachments' => $attachments,
        );

        return $this->_getIndexWrapper(
                $this->responseView('XenCentral_AdServer_ViewPublic_BannerEdit', 'xcas_add_banner', $viewParams)
        );
    }

    public function actionSave()
    {
        $this->_assertPostOnly();

        $this->_assertManagePermissions();

        $item = $this->_input->filter(array(
                'bannerId' => XenForo_Input::UINT,
                'zoneId' => XenForo_Input::UINT,
                'text' => XenForo_Input::STRING,
                'url' => XenForo_Input::STRING,
        ));

        $attachment_hash=$this->_input->filterSingle('attachment_hash', XenForo_Input::STRING);

        $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Banner');

        if ($item['bannerId']) {
            $writer->setExistingData($item['bannerId']);
            $item['zoneId'] = $writer->get('zoneId');

            if ($writer->get('status') == 'active' AND !XenCentral_AdServer_Permissions::canEditActiveBanner()) {
                return $this->responseNoPermission();
            }
        }
        $writer->setExtraData(XenForo_DataWriter_DiscussionMessage::DATA_ATTACHMENT_HASH, $attachment_hash);

        $zones = $this->_getZoneModel()->getUserZones();
        if (!isset($zones[$item['zoneId']])) {
            $zones = $this->_getZoneModel()->getCustomZones(
                    $writer->isInsert()
                            ? XenForo_Visitor::getUserId()
                            :
                            $writer->get('user_id')
            );
            if (!isset($zones[$item['zoneId']])) {
                // should not happen
                return $this->responseNoPermission();
            }
        }

        $zone = $zones[$item['zoneId']];

        $item['text'] = strip_tags($item['text']);

        if (!$writer->hasAttachments()
                AND !$item['text']
        ) {
            return $this->responseError(new XenForo_Phrase('xcas_either_image_or_text_are_required_for_banner'));
        }
        if (!$item['url']) {
            return $this->responseError(new XenForo_Phrase('xcas_url_is_required_for_banner'));
        }

        if (empty($item['user_id'])) {
            $item['user_id'] = XenForo_Visitor::getUserId();
        }

        if ($maxLength = XenForo_Application::getOptions()->get('xcas_banner_text_max_length') AND strlen($item['text']) > $maxLength) {
            return $this->responseError(new XenForo_Phrase('xcas_maximum_number_of_characters_x', array('maxLength' => $maxLength)));
        }

        $writer->bulkSet($item);

        $tagger = null;

        if ($this->_getBannerModel()->canEditTags($item)) {
            /** @var XenForo_Model_Tag $tagModel */
            $tagModel = $this->getModelFromCache('XenForo_Model_Tag');
            $tagger = $tagModel->getTagger('banner');
            if ($item['bannerId']) {
                $tagger->setContent($item['bannerId']);
            }

            $tagger->setPermissionsFromContext(array())
                    ->setTags($tagModel->splitTags(
                            $this->getInput()->filterSingle('tags', XenForo_Input::STRING)
                    ));
            $writer->mergeErrors($tagger->getErrors());
        }

        if ($writer->isInsert()) {
            if (XenCentral_AdServer_Permissions::canSkipModeration()) {
                if ($zone->isCustomZone()) {
                    // for user campaigns banners are activated immediately
                    $writer->set('status', 'active');
                } else {
                    $writer->set('status', 'inactive');
                }

            } else {
                $writer->set('status', 'moderated');
            }
            $writer->set('impressions_left', 0);
        } else {
            // check if image/text/url are changed
            if (!XenCentral_AdServer_Permissions::canSkipModeration()) {
                if ($writer->isChanged('image') OR $writer->isChanged('text') OR $writer->isChanged('url')) {
                    $writer->set('status', 'moderated');
                }
            }
        }

        $writer->preSave();

        if ($dwErrors = $writer->getErrors()) {
            return $this->responseError($dwErrors);
        }

        $writer->save();
        $bannerId = $writer->get('bannerId');

        if ($tagger) {
            if (!$item['bannerId']) {
                $tagger->setContent($bannerId, true);
            }
            $tagger->save();
        }

        // update banner statuses to reflect moderation status
        XenCentral_AdServer_Cron::updateBannerStatus();

        $redirectParams = array();

        return $this->responseRedirect(
                XenForo_ControllerResponse_Redirect::SUCCESS,
                $zone->isCustomZone() ? XenForo_Link::buildPublicLink('ads/zone/custom') : XenForo_Link::buildPublicLink('ads/zone/site'),
                null,
                $redirectParams
        );
    }

    public function actionTags()
    {
        $banner = $this->_assertCorrectBanner();
        $bannerId = $banner['bannerId'];

        if (!$this->_getBannerModel()->canEditTags($banner)) {
            throw $this->getNoPermissionResponseException();
        }

        /** @var XenForo_Model_Tag $tagModel */
        $tagModel = $this->getModelFromCache('XenForo_Model_Tag');
        $tagger = $tagModel->getTagger('banner');
        $tagger->setContent($banner['bannerId'])->setPermissionsFromContext($banner);

        $editTags = $tagModel->getTagListForEdit('banner', $banner['bannerId'], $tagger->getPermission('removeOthers'));

        if ($this->isConfirmedPost()) {
            $tags = $this->_input->filterSingle('tags', XenForo_Input::STRING);
            if ($editTags['uneditable']) {
                // this is mostly a sanity check; this should be ignored
                $tags .= (strlen($tags) ? ', ' : '') . implode(', ', $editTags['uneditable']);
            }
            $tagger->setTags($tagModel->splitTags($tags));

            $errors = $tagger->getErrors();
            if ($errors) {
                return $this->responseError($errors);
            }

            $cache = $tagger->save();

            if ($this->_noRedirect()) {
                $view = $this->responseView('', 'helper_tag_list', array(
                        'tags' => $cache,
                        'editUrl' => XenForo_Link::buildPublicLink('ads/banner/edit', $banner)
                ));
                $view->jsonParams = array(
                        'isTagList' => true,
                        'redirect' => XenForo_Link::buildPublicLink('ads')
                );
                return $view;
            } else {
                return $this->responseRedirect(
                        XenForo_ControllerResponse_Redirect::SUCCESS,
                        XenForo_Link::buildPublicLink('ads')
                );
            }
        } else {
            $viewParams = array(
                    'banner' => $banner,
                    'tags' => $editTags
            );

            return $this->responseView('', '', $viewParams);
        }
    }

    public function actionValidateField()
    {
        return $this->responseMessage('Okay');
    }

    public function actionDelete()
    {
        $item = $this->_assertCorrectBanner();

        if ($this->isConfirmedPost()) {
            $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Banner');
            $writer->setExistingData($item['bannerId']);
            $writer->delete();

            $redirectParams = array();

            return $this->responseRedirect(
                    XenForo_ControllerResponse_Redirect::SUCCESS,
                    XenForo_Link::buildPublicLink('ads'),
                    null,
                    $redirectParams
            );
        }

        $viewParams = array(
                'title' => new XenForo_Phrase('xcas_delete_banner'),
                'item' => $item,
                'breadCrumbs' => $this->_getBreadCrumbs(new XenForo_Phrase('xcas_delete_banner'))
        );

        return $this->_getIndexWrapper(
                $this->responseView('XenCentral_AdServer_ViewPublic_Delete', 'xcas_delete_banner', $viewParams)
        );
    }

    protected function _assertCorrectBanner()
    {
        $this->_assertManagePermissions();

        $bannerId = $this->_input->filterSingle('bannerId', XenForo_Input::UINT);

        if (!$bannerId) {
            $this->responseNoPermission();
        }

        $banner = $this->_getBannerModel()->getBannerById($bannerId);
        $users = explode(',', $banner['user_id']);
        if (
                !$banner
                OR !(in_array(XenForo_Visitor::getUserId(), $users))
                OR !$banner['active']
        ) {
            throw $this->getNoPermissionResponseException();
        }

        $banner = $this->_getBannerModel()->prepareBanner($banner);

        return $banner;
    }

    protected function _assertManagePermissions()
    {
        if (!XenCentral_AdServer_Permissions::canCreateBanner()) {
            throw $this->getNoPermissionResponseException();
        }

        return true;
    }

    /**
     * @return XenCentral_AdServer_Model_Options
     */
    protected function _getOptionsModel()
    {
        return $this->getModelFromCache('XenCentral_AdServer_Model_Options');
    }

    /**
     * @return XenForo_Model_Attachment
     */
    protected function _getAttachmentModel()
    {
        return $this->getModelFromCache('XenForo_Model_Attachment');
    }
}
