<?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
*/


/**
 *
 * @package XenCentral_AdServer
 */
class XenCentral_AdServer_DataWriter_Banner extends XenCentral_AdServer_DataWriter_Abstract
{
    const OPTION_IS_AUTOMATED = 'isAutomated';

    /**
     * Holds the temporary hash used to pull attachments and associate them with this message.
     *
     * @var string
     */
    const DATA_ATTACHMENT_HASH = 'attachmentHash';

    /**
     * Gets the fields that are defined for the table. See parent for explanation.
     *
     * @return array
     */
    protected function _getFields()
    {
        return array(
                'xcas_banner' => array(
                        'bannerId' => array(
                                'type' => self::TYPE_UINT,
                                'autoIncrement' => true
                        ),
                        'title' => array(
                                'type' => self::TYPE_STRING,
                                'required' => true,
                                'minLength' => 0
                        ),
                        'text' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false,
                                'minLength' => 0
                        ),
                        'url' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false,
                                'minLength' => 0
                        ),
                        'image' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false,
                                'default' => '',
                                'minLength' => 0
                        ),
                        'zoneId' => array(
                                'type' => self::TYPE_UINT,
                                'required' => true
                        ),
                        'code' => array(
                                'type' => self::TYPE_STRING,
                                'required' => true
                        ),
                        'mobile_view_code' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false
                        ),
                        'tablet_view_code' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false
                        ),
                        'user_id' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false
                        ),
                        'active_from' => array(
                                'type' => self::TYPE_UINT,
                                'required' => false
                        ),
                        'active_to' => array(
                                'type' => self::TYPE_UINT,
                                'required' => false
                        ),
                        'status' => array(
                                'type' => self::TYPE_STRING,
                                'required' => false,
                                'default' => 'active',
                                'allowedValues' => array('active', 'inactive', 'moderated', 'paused')
                        ),
                        'impressions_left' => array(
                                'type' => self::TYPE_INT,
                                'required' => false,
                                'default' => -1
                        ),
                        'display_order' => array(
                                'type' => self::TYPE_UINT,
                                'required' => false
                        ),
                        'is_placeholder' => array(
                                'type' => self::TYPE_BOOLEAN,
                                'default' => 0,
                                'required' => false
                        ),
                        'safe_mode' => array(
                                'type' => self::TYPE_BOOLEAN,
                                'default' => 0,
                                'required' => false
                        ),
                        'active' => array(
                                'type' => self::TYPE_BOOLEAN,
                                'required' => false
                        ),
                        'notifications_sent' => array(
                                'type' => self::TYPE_UINT,
                                'default' => 0,
                                'required' => false
                        ),
                        'tags' => array(
                                'type' => self::TYPE_SERIALIZED,
                                'default' => 'a:0:{}'
                        ),
                )
        );
    }

    /**
     * Gets the actual existing data out of data that was passed in. See parent for explanation.
     *
     * @param mixed
     *
     * @return array|false
     */
    protected function _getExistingData($data)
    {
        if (!$id = $this->_getExistingPrimaryKey($data)) {
            return false;
        }

        return array(
                'xcas_banner' => $this->_getBannerModel()->getBannerById($id)
        );
    }

    protected function _getUpdateCondition($tableName)
    {
        return 'bannerId = ' . $this->_db->quote($this->getExisting('bannerId'));
    }

    protected function _preSaveDefaults()
    {
        parent::_preSaveDefaults();

        if (($date = $this->get('active_from')) && ($time = $this->getOption('active_from_time'))) {
            $time = explode(':', $time);
            $this->set('active_from', $date + $time[0] * 3600 + $time[1] * 60);
        }
        if (($date = $this->get('active_to')) && ($time = $this->getOption('active_to_time'))) {
            $time = explode(':', $time);
            $this->set('active_to', $date + $time[0] * 3600 + $time[1] * 60);
        }

        if ($this->getOption('username') !== null) {
            $userlist = array();
            $users = array_map('trim', explode(',', $this->getOption('username')));


            for ($i = 0; $i < count($users); $i++) {
                $user = $this->_getUserModel()->getUserByName($users[$i]);
                $userlist[$i] = $user['user_id'];
            }


            $user_separated = rtrim(implode(",", $userlist), ',');
            $this->set('user_id', $user_separated);
        }

        if (
                $this->_hasNewAttachments()
                OR $this->isChanged('text')
                OR (
                        $this->isUpdate()
                        && $this->getExisting('image')
                        && $this->hasAttachments() == false
                )
        ) {
            $newDefault = $oldDefault = '';
            $newDefaultMobile = $oldDefaultMobile = '';
            $newDefaultTablet = $oldDefaultTablet = '';

            if ($this->hasAttachments()) {
                $newDefault = $this->_getBannerModel()->getDefaultCode('image');
                $oldDefault = $this->_getBannerModel()->getDefaultCode('text');
                $newDefaultMobile = $this->_getBannerModel()->getDefaultMobileCode('image');
                $oldDefaultMobile = $this->_getBannerModel()->getDefaultMobileCode('text');
            } else if($this->get('text')) {
                $newDefault = $this->_getBannerModel()->getDefaultCode('text');
                $oldDefault = $this->_getBannerModel()->getDefaultCode('image');
                $newDefaultMobile = $this->_getBannerModel()->getDefaultMobileCode('text');
                $oldDefaultMobile = $this->_getBannerModel()->getDefaultMobileCode('image');
            }
            if (
                    $this->get('code') === null
                    OR $this->get('code') == $oldDefault
            ) {
                $this->set('code', $newDefault);

            }

            if (
                    $this->get('mobile_view_code') === null
                    OR $this->get('mobile_view_code') == $oldDefaultMobile
            ) {
                $this->set('mobile_view_code', $newDefaultMobile);

            }
            if (
                    $this->get('tablet_view_code') === null
                    OR $this->get('tablet_view_code') == $oldDefaultTablet
            ) {
                $this->set('tablet_view_code', $newDefaultTablet);

            }
        }

        if ($this->get('title') === null) {
            $this->set('title', 'test'); // do not show error about this anyway
            $user_id = $this->get('user_id');
            $zoneId = $this->get('zoneId');
            if ($zoneId AND $user_id !== null) {
                // generate banner name automatically
                $username = new XenForo_Phrase('guest');
                if ($user_id AND $user_id === XenForo_Visitor::getUserId()) {
                    $username = XenForo_Visitor::getInstance()->get('username');
                } else if ($user_id) {
                    $user = $this->_getUserModel()->getUserById($user_id);
                    if ($user) {
                        $username = $user['username'];
                    }
                }
                $zone = $this->_getZoneModel()->getZoneByIdFromCache($zoneId);


                $this->set('title', new XenForo_Phrase('xcas_user_banner_by_x_zone_y_at_z', array(
                        'username' => $username,
                        'zoneTitle' => $zone['title'],
                        'date' => XenForo_Locale::date(time(), 'absolute')
                )));
            }

        }
    }

    protected function _preSave()
    {
        parent::_preSave();

        $zone = $this->_getZoneModel()->getZoneObjectById($this->get('zoneId'));

        if(!$zone) {
            return;
        }

        if (
                $zone->get('force_dimensions')
                && ($width = $zone->getZoneWidth())
                && ($height = $zone->getZoneHeight())
        ) {
            foreach ($this->_getNewAttachments() AS $attachment) {
                if (round($width / $height, 1) != round($attachment['width'] / $attachment['height'], 1)) {
                    $this->error(new XenForo_Phrase('xcas_please_cut_in_appropriate_dimensions'));
                    return false;
                }

                if ($attachment['width'] < $width OR $attachment['height'] < $height) {
                    $this->error(new XenForo_Phrase('xcas_selection_is_too_small'));
                    return false;
                }
            }
        }
    }

    protected function _getNewAttachments()
    {
        if (!$this->getExtraData(self::DATA_ATTACHMENT_HASH)) {
            return array();
        }

        return $this->_db->fetchAll('
            SELECT attachment.*, data.*
            FROM xf_attachment AS attachment
            LEFT JOIN xf_attachment_data AS data ON data.data_id=attachment.data_id
            WHERE attachment.temp_hash=?
            AND unassociated=1
        ', array(
                'temp_hash' => $this->getExtraData(self::DATA_ATTACHMENT_HASH),
        ));
    }


    protected function _hasNewAttachments()
    {
        if (!$this->getExtraData(self::DATA_ATTACHMENT_HASH)) {
            return 0;
        }

        return $this->_db->fetchOne('
            SELECT COUNT(*) FROM xf_attachment
            WHERE temp_hash=?
            AND unassociated=1
        ', array(
                'temp_hash' => $this->getExtraData(self::DATA_ATTACHMENT_HASH),
        ));
    }

    public function hasAttachments()
    {
        if ($this->isInsert()) {
            return $this->_hasNewAttachments();
        }

        if ($this->_hasNewAttachments()) {
            return true;
        }

        return $this->_db->fetchOne('
            SELECT COUNT(*) FROM xf_attachment
            WHERE content_type=?
            AND content_id=?
        ', array(
                'content_type' => 'banner',
                'content_id' => $this->get('bannerId'),
        ));
    }

    protected function _getAttachments()
    {
        return $this->_db->fetchAll('
            SELECT attachment.*, data.*
            FROM xf_attachment AS attachment
            LEFT JOIN xf_attachment_data AS data ON data.data_id=attachment.data_id
            WHERE attachment.content_type=?
            AND attachment.content_id=?
        ', array(
                'banner',
                $this->get('bannerId'),
        ));
    }


    protected function _postSave()
    {
        parent::_postSave();

        $attachmentHash = $this->getExtraData(self::DATA_ATTACHMENT_HASH);

        if ($attachmentHash) {
            $this->_associateAttachments($attachmentHash);

            $zone = $this->_getZoneModel()->getZoneObjectById($this->get('zoneId'));

            if (
                    $zone->get('force_dimensions')
                    && ($width = $zone->getZoneWidth())
                    && ($height = $zone->getZoneHeight())
            ) {
                foreach ($this->_getAttachments() AS $attachment) {
                    $this->_getZoneModel()->resizeAttachment($zone, $attachment, $errors);
                }
            }

            $this->_getBannerModel()->updateBannerImages($this->get('bannerId'));
        }

        $this->_updateTaggingVisibility();

        // the ad was approved, send notification
        /** @var XenCentral_AdServer_Model_Notification $notificationModel */
        $notificationModel = $this->getModelFromCache('XenCentral_AdServer_Model_Notification');

        if (
                $this->isUpdate()
                AND $this->get('user_id')

        ) {
            if ($this->getExisting('status') == 'moderated' AND $this->getNew('status') == 'inactive') {
                // moderated by admin
                $userIds = explode(',', $this->get('user_id'));
                foreach ($userIds AS $userId) {
                    $userId = intval(trim($userId));

                    if (!$userId) {
                        continue;
                    }

                    $user = $this->_getUserModel()->getUserById($userId);

                    $params = array(
                            'user' => $user,
                            'banner' => $this->getMergedData()
                    );

                    $notificationModel->sendUserNotification(
                            XenCentral_AdServer_Model_Notification::TYPE_USER_APPROVED,
                            $user,
                            $params
                    );
                }
            } else if (
                    $this->getExisting('status') == 'inactive' AND $this->getNew('status') == 'active'
                    AND XenForo_Visitor::getInstance()->get('is_admin') == false
            ) {
                // banner has been activated by a user
                $params = array(
                        'banner' => $this->getMergedData()
                );
                $notificationModel->sendAdminNotification(XenCentral_AdServer_Model_Notification::TYPE_ADMIN_ACTIVATED, $params);
            }

        }

        if (
                $this->isInsert()
                AND $this->get('user_id')
                AND XenForo_Visitor::getInstance()->get('is_admin') == false
        ) {
            $userId = $this->get('user_id');
            $params = array(
                    'banner' => $this->getMergedData(),
                    'user' => $this->_getUserModel()->getUserById($userId)
            );

            // user banner is being created, send admin notifications
            $notificationModel->sendAdminNotification(XenCentral_AdServer_Model_Notification::TYPE_ADMIN_UPLOADED, $params);
        }

        if (
                $this->isInsert()
                OR $this->isChanged('status')
                OR $this->isChanged('text')
                OR $this->isChanged('url')
        ) {
            $zoneId = $this->get('zoneId');
            $writer = XenForo_DataWriter::create('XenCentral_AdServer_DataWriter_Zone');
            $writer->setExistingData($zoneId);
            $writer->set('last_update', time());
            $writer->save();
        }

        if ($this->getOption(self::OPTION_IS_AUTOMATED) == false) {
            $this->_getBannerModel()->updateCache();
            $this->_getZoneModel()->updateCache();
        }
    }

    /**
     * Associates attachments with this message.
     *
     * @param string $attachmentHash
     */
    protected function _associateAttachments($attachmentHash)
    {
        $rows = $this->_db->update('xf_attachment', array(
                'content_type' => 'banner',
                'content_id' => $this->get('bannerId'),
                'temp_hash' => '',
                'unassociated' => 0
        ), 'temp_hash = ' . $this->_db->quote($attachmentHash));
    }

    protected function _postDelete()
    {
        parent::_postDelete();
        /** @var XenForo_Model_Tag $tagModel */
        $tagModel = $this->getModelFromCache('XenForo_Model_Tag');
        $tagModel->deleteContentTags('banner', $this->get('bannerId'));

        // delete impressions and clicks
        $this->_db->delete('xcas_impressions_banner', array(
                'bannerId=' . $this->get('bannerId')
        ));
        $this->_db->delete('xcas_clicks_banner', array(
                'bannerId=' . $this->get('bannerId')
        ));


        $this->_getBannerModel()->updateCache();
    }

    protected function _updateTaggingVisibility()
    {
        $newState = $this->get('status');
        $oldState = $this->getExisting('status');

        if ($newState != 'moderated' && $oldState == 'moderated') {
            $newVisible = true;
        } else if ($oldState != 'moderated' && $newState == 'moderated') {
            $newVisible = false;
        } else {
            return;
        }

        /** @var XenForo_Model_Tag $tagModel */
        $tagModel = $this->getModelFromCache('XenForo_Model_Tag');
        $tagModel->updateContentVisibility('banner', $this->get('bannerId'), $newVisible);
    }


    protected function _getDefaultOptions()
    {
        return array(
                self::OPTION_IS_AUTOMATED => 0,
                'username' => null,
                'active_from_time' => 0,
                'active_to_time' => 0
        );
    }

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

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