<?php
    /*********************************************************************************
     * Zurmo is a customer relationship management program developed by
     * Zurmo, Inc. Copyright (C) 2017 Zurmo Inc.
     *
     * Zurmo is free software; you can redistribute it and/or modify it under
     * the terms of the GNU Affero General Public License version 3 as published by the
     * Free Software Foundation with the addition of the following permission added
     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
     *
     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
     * details.
     *
     * You should have received a copy of the GNU Affero General Public License along with
     * this program; if not, see http://www.gnu.org/licenses or write to the Free
     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     * 02110-1301 USA.
     *
     * You can contact Zurmo, Inc. with a mailing address at 27 North Wacker Drive
     * Suite 370 Chicago, IL 60606. or at email address contact@zurmo.com.
     *
     * The interactive user interfaces in original and modified versions
     * of this program must display Appropriate Legal Notices, as required under
     * Section 5 of the GNU Affero General Public License version 3.
     *
     * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
     * these Appropriate Legal Notices must retain the display of the Zurmo
     * logo and Zurmo copyright notice. If the display of the logo is not reasonably
     * feasible for technical reasons, the Appropriate Legal Notices must display the words
     * "Copyright Zurmo Inc. 2017. All rights reserved".
     ********************************************************************************/

    class MarketingListMember extends OwnedModel
    {
        const SCENARIO_MANUAL_CHANGE        = 'manualChange';

        public static function getModuleClassName()
        {
            return 'MarketingListsModule';
        }

        /**
         * Returns the display name for plural of the model class.
         * @param null | string $language
         * @return dynamic label name based on module.
         */
        protected static function getPluralLabel($language = null)
        {
            return Zurmo::t('MarketingListsModule', 'Marketing List Members', array(), null, $language);
        }

        protected static function getLabel($language = null)
        {
            return Zurmo::t('MarketingListsModule', 'Marketing List Member', array(), null, $language);
        }

        public static function getDefaultMetadata()
        {
            $metadata = parent::getDefaultMetadata();
            $metadata[__CLASS__] = array(
                'members' => array(
                    'createdDateTime',
                    'modifiedDateTime',
                    'unsubscribed',
                ),
                'relations' => array(
                    'contact'               => array(static::HAS_ONE, 'Contact', static::NOT_OWNED),
                    'marketingList'         => array(static::HAS_ONE, 'MarketingList' , static::NOT_OWNED),
                ),
                'rules' => array(
                    array('createdDateTime',       'required'),
                    array('createdDateTime',       'type', 'type' => 'datetime'),
                    array('modifiedDateTime',      'type', 'type' => 'datetime'),
                    array('unsubscribed',          'boolean'),
                    array('unsubscribed',          'default', 'value' => false),
                    array('unsubscribed',          'isNotIllegalStateChange'),
                    array('unsubscribed',          'doesNotAlreadyExist'),
                ),
                'elements' => array(
                    'createdDateTime'  => 'DateTime',
                    'modifiedDateTime' => 'DateTime',
                    'unsubscribed'     => 'CheckBox',
                ),
                'defaultSortAttribute' => 'createdDateTime',
                'indexes' => array(
                    'contact_id' => array(
                        'members' => array('contact_id'),
                        'unique' => false),
                    'marketinglist_id' => array(
                        'members' => array('marketinglist_id'),
                        'unique' => false)
                ),
            );
            return $metadata;
        }

        public static function isTypeDeletable()
        {
            return true;
        }

        public static function canSaveMetadata()
        {
            return true;
        }

        public static function getCountByMarketingListIdAndUnsubscribed($marketingListId, $unsubscribed)
        {
            $searchAttributeData = array();
            $searchAttributeData['clauses'] = array(
                1 => array(
                    'attributeName'             => 'unsubscribed',
                    'operatorType'              => 'equals',
                    'value'                     => intval($unsubscribed)
                ),
                2 => array(
                    'attributeName'             => 'marketingList',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($marketingListId),
                ),
            );
            $searchAttributeData['structure'] = '(1 and 2)';
            $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter(get_called_class());
            $where             = RedBeanModelDataProvider::makeWhere(get_called_class(), $searchAttributeData, $joinTablesAdapter);
            return self::getCount($joinTablesAdapter, $where, get_called_class(), true);
        }

        public static function getByMarketingListIdContactIdAndUnsubscribed($marketingListId, $contactId, $unsubscribed)
        {
            // TODO: @Shoaibi: Critical: Add Tests to cover:
            $searchAttributeData = array();
            $searchAttributeData['clauses'] = array(
                1 => array(
                    'attributeName'             => 'unsubscribed',
                    'operatorType'              => 'equals',
                    'value'                     => intval($unsubscribed)
                ),
                2 => array(
                    'attributeName'             => 'contact',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($contactId),
                ),
                3 => array(
                    'attributeName'             => 'marketingList',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($marketingListId),
                ),
            );
            $searchAttributeData['structure'] = '(1 and 2 and 3)';
            $joinTablesAdapter  = new RedBeanModelJoinTablesQueryAdapter(get_called_class());
            $where              = RedBeanModelDataProvider::makeWhere(get_called_class(), $searchAttributeData, $joinTablesAdapter);
            $member             = self::getSubset($joinTablesAdapter, null, null, $where, null);
            if (count($member) > 1)
            {
                throw new NotSupportedException();
            }
            elseif (count($member) === 0)
            {
                return false;
            }
            return $member;
        }

        public static function getByMarketingListIdAndContactId($marketingListId, $contactId)
        {
            $searchAttributeData = array();
            $searchAttributeData['clauses'] = array(
                1 => array(
                    'attributeName'             => 'contact',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($contactId),
                ),
                2 => array(
                    'attributeName'             => 'marketingList',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($marketingListId),
                ),
            );
            $searchAttributeData['structure'] = '(1 and 2)';
            $joinTablesAdapter  = new RedBeanModelJoinTablesQueryAdapter(get_called_class());
            $where              = RedBeanModelDataProvider::makeWhere(get_called_class(), $searchAttributeData, $joinTablesAdapter);
            $member             = self::getSubset($joinTablesAdapter, null, null, $where, null);
            if (count($member) > 1)
            {
                throw new NotSupportedException();
            }
            elseif (count($member) === 0)
            {
                return false;
            }
            return $member;
        }

        public static function getByContactIdAndSubscribed($contactId, $unsubscribed)
        {
            // TODO: @Shoaibi: Critical: Add Tests to cover:
            $searchAttributeData = array();
            $searchAttributeData['clauses'] = array(
                1 => array(
                    'attributeName'             => 'unsubscribed',
                    'operatorType'              => 'equals',
                    'value'                     => intval($unsubscribed)
                ),
                2 => array(
                    'attributeName'             => 'contact',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($contactId),
                ),
            );
            $searchAttributeData['structure'] = '(1 and 2)';
            $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter(get_called_class());
            $where             = RedBeanModelDataProvider::makeWhere(get_called_class(), $searchAttributeData, $joinTablesAdapter);
            $members           = self::getSubset($joinTablesAdapter, null, null, $where, null);
            return $members;
        }

        /**
         * @param $contactId
         * @return members associated to given contactId
         */
        public static function getByContactId($contactId)
        {
            $searchAttributeData = array();
            $searchAttributeData['clauses'] = array(
                1 => array(
                    'attributeName'             => 'contact',
                    'relatedAttributeName'      => 'id',
                    'operatorType'              => 'equals',
                    'value'                     => intval($contactId),
                ),
            );
            $searchAttributeData['structure'] = '1';
            $joinTablesAdapter = new RedBeanModelJoinTablesQueryAdapter(get_called_class());
            $where             = RedBeanModelDataProvider::makeWhere(get_called_class(), $searchAttributeData, $joinTablesAdapter);
            $members           = self::getSubset($joinTablesAdapter, null, null, $where, null);
            return $members;
        }

        public function onCreated()
        {
            parent::onCreated();
            $this->unrestrictedSet('createdDateTime',  DateTimeUtil::convertTimestampToDbFormatDateTime(time()));
            $this->unrestrictedSet('modifiedDateTime', DateTimeUtil::convertTimestampToDbFormatDateTime(time()));
        }

        public function beforeSave()
        {
            if (!parent::beforeSave())
            {
                return false;
            }
            if ($this->id < 0 || (isset($this->originalAttributeValues['unsubscribed']) &&
                                            $this->originalAttributeValues['unsubscribed'] != $this->unsubscribed))
            {
                $operation = Autoresponder::OPERATION_SUBSCRIBE;
                if ($this->unsubscribed)
                {
                    $operation = Autoresponder::OPERATION_UNSUBSCRIBE;
                }
                AutoresponderItem::registerAutoresponderItemsByAutoresponderOperation($operation,
                                                                                        $this->marketingList->id,
                                                                                        $this->contact);
            }
            $this->modifiedDateTime     = DateTimeUtil::convertTimestampToDbFormatDateTime(time());
            return true;
        }

        public function doesNotAlreadyExist($attribute, $params)
        {
            if ($this->id < 0)
            {
                $query  = 'SELECT COUNT(*) FROM ' . static::getTableName();
                $query  .= ' WHERE contact_id=' . $this->contact->id . ' AND marketinglist_id=' . $this->marketingList->id;
                if (ZurmoRedBean::getCell($query))
                {
                    $this->addError($attribute, Zurmo::t('MarketingListsModule', 'Member already exists'));
                    return false;
                }
            }
            return true;
        }

        public function isNotIllegalStateChange($attribute, $params)
        {
            if (isset($this->originalAttributeValues['unsubscribed']) &&
                $this->originalAttributeValues['unsubscribed'] != $this->unsubscribed)
            {
                // if current state is unsubscribed, new state is subscribed and scenario is not set to manual then return true
                if ($this->originalAttributeValues['unsubscribed'] && $this->getScenario() != static::SCENARIO_MANUAL_CHANGE)
                {
                    $this->addError($attribute, Zurmo::t('MarketingListsModule', 'Automated State change to subscribed is not allowed.'));
                    return false;
                }
            }
            return true;
        }

        public function unrestrictedSave($runValidation = true, array $attributeNames = null)
        {
            // enforce validation to ensure record:
            // a- does not already exist
            // b- is not an illegal state change
            return parent::unrestrictedSave(true, $attributeNames);
        }
    }
?>
