<?php

class QueueStrategy
{

    const ring_all = 0;
    const longest_idle_agent = 1;
    const round_robin = 2;
    const top_down = 3;
    const agent_with_least_talk_time = 4;
    const agent_with_fewest_calls = 5;
    const sequentially_by_agent_order = 6;
    const random = 7;

    public static function getQueueStrategy($type)
    {
        switch ($type) {
            case QueueStrategy::ring_all :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_RING_ALL');
                break;
            case QueueStrategy::longest_idle_agent :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_LONGEST_IDLE_AGENT');
                break;
            case QueueStrategy::round_robin :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_ROUND_ROBIN');
                break;
            case QueueStrategy::top_down :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_TOP_DOWN');
                break;
            case QueueStrategy::agent_with_least_talk_time :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_AGENT_WITH_LEAST_TALK_TIME');
                break;
            case QueueStrategy::agent_with_fewest_calls :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_AGENT_WITH_FEWEST_CALLS');
                break;
            case QueueStrategy::sequentially_by_agent_order :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_SEQUENTIALLY_BY_AGENT_ORDER');
                break;
            case QueueStrategy::random :
                $typeAsString = __('QUEUE_MODEL_QUEUE_STRATEGY_RANDOM');
                break;
        }
        return $typeAsString;
    }
}

class TimeBaseScore
{

    const system = 0;
    const queue = 1;

    public static function getTimeBaseScore($type)
    {
        switch ($type) {
            case TimeBaseScore::system :
                $typeAsString = __('QUEUE_MODEL_TIME_BASE_SCORE_SYSTEM');
                break;
            case TimeBaseScore::queue :
                $typeAsString = __('QUEUE_MODEL_TIME_BASE_SCORE_QUEUE');
                break;
        }
        return $typeAsString;
    }
}

class Queue extends PhonalisaRecord
{

    public $extension;
    public $name;
    public $moh;
    public $strategy;
    public $time_base_score;
    public $cid_prefix;
    public $announce_file;
    public $tier_rules_apply;
    public $tier_rule_wait_second;
    public $tier_rule_wait_multiply_level;
    public $tier_rule_no_agent_no_wait = 1;
    public $discard_abandoned_after;
    public $abandoned_resume_allowed;
    public $max_wait_time;
    public $max_wait_time_with_no_agent = 10;
    public $max_wait_time_with_no_agent_time_reached;
    public $target_on_timeout;
    public $target_type_on_timeout;
    public $target_on_timeout_meta;
    public $target_on_no_agents;
    public $target_type_on_no_agents;
    public $target_on_no_agents_meta;
    public $target_on_no_agents_reachable;
    public $target_type_on_no_agents_reachable;
    public $scriptExtension;
    public $max_subscriber;
    public $target_on_full;
    public $target_type_on_full;
    public $target_on_full_meta;

    public static function myAttributes()
    {
        return array(
            'extension' => 'extension',
            'name' => 'name',
            'moh' => 'moh',
            'strategy' => 'strategy',
            'time_base_score' => 'time_base_score',
            'cid_prefix' => 'cid_prefix',
            'announce_file' => 'announce_file',
            'tier_rules_apply' => 'tier_rules_apply',
            'tier_rule_wait_second' => 'tier_rule_wait_second',
            'tier_rule_wait_multiply_level' => 'tier_rule_wait_multiply_level',
            'tier_rule_no_agent_no_wait' => 'tier_rule_no_agent_no_wait',
            'discard_abandoned_after' => 'discard_abandoned_after',
            'abandoned_resume_allowed' => 'abandoned_resume_allowed',
            'max_wait_time' => 'max_wait_time',
            'max_wait_time_with_no_agent' => 'max_wait_time_with_no_agent',
            'max_wait_time_with_no_agent_time_reached' => 'max_wait_time_with_no_agent_time_reached',
            'target_on_timeout' => 'target_on_timeout',
            'target_on_timeout_meta' => 'target_on_timeout_meta',
            'target_type_on_timeout' => 'target_type_on_timeout',
            'target_on_no_agents' => 'target_on_no_agents',
            'target_type_on_no_agents' => 'target_type_on_no_agents',
            'target_on_no_agents_meta' => 'target_on_no_agents_meta',
            'target_on_no_agents_reachable' => 'target_on_no_agents_reachable',
            'target_type_on_no_agents_reachable' => 'target_type_on_no_agents_reachable',
            "scriptExtension" => "scriptExtension",
            'target_on_full' => 'target_on_full',
            'max_subscriber' => 'max_subscriber',
            'target_type_on_full' => 'target_type_on_full',
            'target_on_full_meta' => 'target_on_full_meta'
        );
    }

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Job the static model class
     */
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'Queue';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('extension, name', 'required'),
            array('extension,'
                . 'tier_rule_wait_second,'
                . 'discard_abandoned_after,'
                . 'max_wait_time,'
                . 'max_wait_time_with_no_agent,'
                . 'max_wait_time_with_no_agent_time_reached,'
                . 'max_subscriber',
                'numerical',
                'integerOnly' => true
            ),
            array('extension', 'ext.PhonalisaValidators.uniqueExtension'),
            array('extension', 'length', 'min' => 2, 'max' => 10),
            array(
                'extension',
                'match',
                'pattern' => '/^[1-9]/',
                'message' => __('USER_MODEL_SHOULD_NOT_START_WITH_ZERO_ERROR_MESSAGE')
            ),
            array('name', 'length', 'max' => 255),
            array('announce_file, scriptExtension', 'safe'),
            array('cid_prefix', 'length', 'max' => 6),
            array(
                'cid_prefix',
                'match',
                'pattern' => '/^[0-9a-zA-Z_-]*$/',
                'message' => __('USER_MODEL_SHOULD_ONLY_CONTAIN_UNDERLINE_AND_MINUS_CHARACTERS_ERROR_MESSAGE')
            ),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('extension,'
                . 'name,'
                . 'moh,'
                . 'strategy,'
                . 'time_base_score,'
                . 'tier_rules_apply,'
                . 'tier_rule_wait_second,'
                . 'tier_rule_wait_multiply_level,'
                . 'tier_rule_no_agent_no_wait,'
                . 'discard_abandoned_after,'
                . 'abandoned_resume_allowed,'
                . 'max_wait_time,'
                . 'max_wait_time_with_no_agent,'
                . 'max_wait_time_with_no_agent_time_reached,'
                . 'target_on_timeout,'
                . 'target_type_on_timeout,'
                . 'target_on_no_agents,'
                . 'target_type_on_no_agents,'
                . 'target_on_no_agents_meta,'
                . 'target_on_timeout_meta,'
                . 'target_on_no_agents_reachable,'
                . 'target_type_on_no_agents_reachable,'
                . 'target_on_full,'
                . 'target_type_on_full,'
                . 'target_on_full_meta',
                'safe'
            ),
            array('extension, name', 'safe', 'on' => 'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'extension' => __('QUEUE_MODEL_EXTENSION'),
            'name' => __('QUEUE_MODEL_NAME'),
            'moh' => __('QUEUE_MODEL_MOH'),
            'strategy' => __('QUEUE_MODEL_STRATEGY'),
            'time_base_score' => __('QUEUE_MODEL_TIME_BASE_SCORE'),
            'cid_prefix' => __('QUEUE_MODEL_CID_PREFIX'),
            'announce_file' => __('QUEUE_MODEL_ANNOUNCE_FILE'),
            'tier_rules_apply' => __('QUEUE_MODEL_TIER_RULES_APPLY'),
            'tier_rule_wait_second' => __('QUEUE_MODEL_TIER_RULE_WAIT_SECOND'),
            'tier_rule_wait_multiply_level' => __('QUEUE_MODEL_TIER_RULE_WAIT_MULTIPLY_LEVEL'),
            'tier_rule_no_agent_no_wait' => __('QUEUE_MODEL_TIER_RULE_NO_AGENT_NO_WAIT'),
            'discard_abandoned_after' => __('QUEUE_MODEL_DISCARD_ABANDONED_AFTER'),
            'abandoned_resume_allowed' => __('QUEUE_MODEL_ABANDONED_RESUME_ALLOWED'),
            'max_wait_time' => __('QUEUE_MODEL_MAX_WAIT_TIME'),
            'max_wait_time_with_no_agent' => __('QUEUE_MODEL_MAX_WAIT_TIME_NO_AGENT'),
            'max_wait_time_with_no_agent_time_reached' => __('QUEUE_MODEL_MAX_WAIT_TIME_NO_AGENT_TIME_REACHED'),
            'target_on_timeout' => __('QUEUE_MODEL_TARGET_ON_TIMEOUT'),
            'target_on_no_agents' => __('QUEUE_MODEL_TARGET_ON_NO_AGENTS_LOGGED_IN'),
            'target_on_no_agents_meta' => __('QUEUE_MODEL_TARGET_ON_NO_AGENTS_META'),
            'target_on_timeout_meta' => __('QUEUE_MODEL_TARGET_ON_TIMEOUT_META'),
            'target_on_no_agents_reachable' => __('QUEUE_MODEL_TARGET_ON_NO_AGENTS_REACHABLE'),
            "scriptExtension" => __("USER_MODEL_SCRIPT_EXTENSION"),
            'target_on_full' => __('QUEUE_MODEL_TARGET_ON_FULL'),
            'target_on_full_meta' => __('QUEUE_MODEL_TARGET_ON_FULL_META'),
            'max_subscriber' => __('QUEUE_MODEL_MAX_SUBSCRIBER'),
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CPhonalisaDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search($order = 'name')
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria = new CDbCriteria;
        $filter = $this->getFilter($criteria, $order);
        $filter['pagination'] = array(
            'pageSize' => getGridPageSize('routing_queue-grid'),
        );

        if ($filter != null) {
            $dataprovider = new CPhonalisaDataProvider($this, $filter);

            $routingQueuesMax = PhonalisaLicenseManager::routingQueuesMax();
            if ($routingQueuesMax >= 0) {
                $dataprovider->pagination->pageSize = $dataprovider->pagination->pageSize > $routingQueuesMax ? $routingQueuesMax : $dataprovider->pagination->pageSize;
                $dataprovider->totalItemCount = $dataprovider->totalItemCount > $routingQueuesMax ? $routingQueuesMax : $dataprovider->totalItemCount;
            }
            return $dataprovider;
        }
    }

    public static function getAnnouncementFileList($withEmptyEntry = true)
    {
        $audioFiles = AudioFile::model()->findAllByAttributes(array('type' => AudioFileType::systemType));
        foreach ($audioFiles as $key => $model) {
            if (!AudioFileUseCase::compare($model->usecase, AudioFileUseCase::QUEUE)) {
                unset($audioFiles[$key]);
            }
        }

        $result = CHtml::listData($audioFiles, 'id', 'name');
        if ($withEmptyEntry) {
            $result = TargetHelper::emptyArrayEntry() + $result;
        }
        return $result;
    }

    public function getAudioFileList()
    {
        $models = MusicOnHold::model()->find(array(), 'name');
        $list = array(
            'default' => __("DEFAULT_MOH_PLAYLIST_NAME")
        );
        foreach ($models as $playlist) {
            $list[$playlist->id] = $playlist->name;
        }
        return $list;
    }

    public function renderMohList(PhonalisaRecord $data, $row)
    {

        if ($data->moh == 'default') {
            return __('DEFAULT_MOH_PLAYLIST_NAME');
        } else {
            $model = MusicOnHold::model()->findByPk($data->moh);

            if ($model == NULL) {
                return __('ROUTING_QUEUE_DEFAULT_MOH');
            } else {
                return $model->name;
            }
        }
    }

    public function getQueueStrategyList()
    {
        $strategyList = array(
            QueueStrategy::ring_all => __('QUEUE_MODEL_QUEUE_STRATEGY_RING_ALL'),
            QueueStrategy::longest_idle_agent => __('QUEUE_MODEL_QUEUE_STRATEGY_LONGEST_IDLE_AGENT'),
            QueueStrategy::round_robin => __('QUEUE_MODEL_QUEUE_STRATEGY_ROUND_ROBIN'),
            QueueStrategy::top_down => __('QUEUE_MODEL_QUEUE_STRATEGY_TOP_DOWN'),
            QueueStrategy::agent_with_least_talk_time => __('QUEUE_MODEL_QUEUE_STRATEGY_AGENT_WITH_LEAST_TALK_TIME'),
            QueueStrategy::agent_with_fewest_calls => __('QUEUE_MODEL_QUEUE_STRATEGY_AGENT_WITH_FEWEST_CALLS'),
            QueueStrategy::sequentially_by_agent_order => __('QUEUE_MODEL_QUEUE_STRATEGY_SEQUENTIALLY_BY_AGENT_ORDER'),
            QueueStrategy::random => __('QUEUE_MODEL_QUEUE_STRATEGY_RANDOM'),
        );

        if (PhonalisaLicenseManager::enterpriseQueuesAvailable() === false) {
            unset($strategyList[QueueStrategy::sequentially_by_agent_order]);
        }
        asort($strategyList);

        return $strategyList;
    }

    public function getTimeBaseScoreList()
    {

        $baseScoreList = array(
            TimeBaseScore::queue => __('QUEUE_MODEL_TIME_BASE_SCORE_QUEUE'),
            TimeBaseScore::system => __('QUEUE_MODEL_TIME_BASE_SCORE_SYSTEM'),
        );
        asort($baseScoreList);

        return $baseScoreList;
    }

    public function renderQueueStrategy(PhonalisaRecord $data, $row)
    {
        return QueueStrategy::getQueueStrategy($data->strategy);
    }

    public function renderTimeBaseScore(PhonalisaRecord $data, $row)
    {
        return TimeBaseScore::getTimeBaseScore($data->time_base_score);
    }

    public function getQueueMembers()
    {
        $tiers = Tiers::model()->findAllByAttributes(array('queueId' => $this->id, 'type' => TiersType::user));
        $members = array();
        foreach ($tiers as $tier) {
            $user = User::model()->findByPk($tier->userId);
            if ($user) {
                $members[$user->id] = $user;
            }
        }
        return $members;
    }

    public function getExternalAgents()
    {
        $tiers = Tiers::model()->findAllByAttributes(array('queueId' => $this->id, 'type' => TiersType::external));

        $members = array();
        foreach ($tiers as $tier) {
            $user = ExternalAgent::model()->findByPk($tier->userId);
            if ($user) {
                $members[$user->id] = $user;
            }
        }
        return $members;
    }

    public function beforeDelete()
    {

        parent::beforeDelete();

        if (!$this->deleteTiers()) {
            return false;
        }

        return true;
    }

    public function deleteTiers()
    {

        $tiers = Tiers::model()->findAllByAttributes(array("queueId" => $this->id));
        if (!empty($tiers)) {
            foreach ($tiers as $tier) {
                if (!$tier->delete()) {
                    return false;
                }
            }
        }
        return true;
    }

    public function getQueuePermissionsDataprovider()
    {
        $rawData = $this->find(array(), 'name');
        return new CArrayDataProvider($rawData, array('pagination' => false));
    }

    // FIXME ! 
    public function getFormattedName()
    {
        return '<' . $this->extension . '> ' . $this->name;
    }

    public function getQueueTimeBaseScore()
    {
        return array(
            TimeBaseScore::system => TimeBaseScore::getTimeBaseScore(TimeBaseScore::system),
            TimeBaseScore::queue => TimeBaseScore::getTimeBaseScore(TimeBaseScore::queue)
        );
    }

    public function getTargetList()
    {
        $targetHelper = new TargetHelper;
        $targetList = $targetHelper->getRedirectionTargetList();
        if (isset($targetList[__('QUEUES')][TargetType::Queue . '_' . $this->id])) {
            unset($targetList[__('QUEUES')][TargetType::Queue . '_' . $this->id]);
        }
        if (empty($targetList[__('QUEUES')])) {
            unset($targetList[__('QUEUES')]);
        }
        $targetList = array_merge(array('_' => '---'), $targetList);
        $targetList[__('RENDER_TARGET_MANUAL')] = array(TargetType::Manual => __('RENDER_TARGET_TYPE_MANUAL'));

        return $targetList;
    }

    public function getSelectedValueForTarget($targetAttribute)
    {
        $targetHelper = new TargetHelper();
        $typeAttribute = $this->getTypeAttributeForTargetAttribute($targetAttribute);
        $result = $targetHelper->getSelectedValueForAttributes($typeAttribute, $targetAttribute, $this);
        if ($this->$typeAttribute == TargetType::Manual) {
            $result = $this->$typeAttribute;
        }
        return $result;
    }

    protected function getTypeAttributeForTargetAttribute($targetAttribute)
    {
        $explodedAttr = explode('_', $targetAttribute);
        $result = $explodedAttr[0] . '_type_' . $explodedAttr[1] . '_' . $explodedAttr[2];

        if (isset($explodedAttr[3])) {
            $result .= '_' . $explodedAttr[3];
        }
        return $result;
    }

    public function getVisibilityByLicense()
    {
        $visibility = false;
        if (PhonalisaLicenseManager::enterpriseQueuesAvailable() === true) {
            $visibility = true;
        }
        return $visibility;
    }

    public function getDefaultValue($model)
    {
        if ($model->isNewRecord) {
            $defaultValue = cfg('DP_DIAL_TIMEOUT');
            return $defaultValue;
        }
    }

    public function getAudioFileListWithJustRingOption()
    {
        $data[''] = __("ROUTING_QUEUE_DEFAULT_MOH");
        return array_merge($data, $this->getAudioFileList());
    }

    public function queueAddressbookProvider()
    {
        $addressbooks = Addressbook::model()->findAll();
        $filterBooks = array();
        foreach ($addressbooks as $addressbook) {
            if ($addressbook->type != AddressbookType::personal) {
                $filterBooks[] = $addressbook;
            }
        }
        return new CArrayDataProvider($filterBooks, array('pagination' => false));
    }
}
