<?php

class DefaultController extends Controller
{

    /**
     * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
     * using two-column layout. See 'protected/views/layouts/column2.php'.
     */
    // Disable custom layout
    public $layout = '//layouts/column2';

    /**
     * @return array action filters
     */
    public function filters()
    {
        // perform access control for CRUD operations
        return array(
            'accessControl',
        );
    }

    /**
     * Specifies the access control rules.
     * This method is used by the 'accessControl' filter.
     * @return array access control rules
     */
    public function accessRules()
    {
        return array(
            array('allow', // allow all users to perform 'index' and 'view' actions
                'actions' => array('index', "export", 'checkUserLimitation'),
                //'users'=>array('@')
                'expression' => AccessManager::checkSessionPermission($this->module->id),
            ),
            array('allow', // allow authenticated user to perform 'create' and 'update' actions
                'actions' => array('create', 'update', 'copy'),
                'users' => array('@'),
                'expression' => AccessManager::checkSessionPermission($this->module->id),
            ),
            array('allow', // allow admin user to perform 'admin' and 'delete' actions
                'actions' => array('admin', 'delete', 'extensionMap'),
                //'users'=>array('@'),
                'expression' => AccessManager::checkSessionPermission($this->module->id),
            ),
            array('deny', // deny all users
                'users' => array('*'),
            ),
        );
    }

    public function actionExtensionMap()
    {

        $limit = 100;
        $offset = 0;
        $allModels = array();
        do {
            $models = User::model()->findAll('', array('limit' => $limit, 'offset' => $offset));
            $allModels = array_merge($allModels, $models);
            $offset = $offset + $limit;
        } while (count($models) != 0);

        $generator = new ExtensionMapPDFGenerator();
        $generator->init(__("PHONALISA_EXTENSION_OVERVIEW"), date("r"));
        $generator->generate($allModels);
    }

    /**
     * Creates a new model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     */
    public function actionCreate()
    {

        $model = new User('create');
        $model->password = $this->getDefaultPassword();
        $model->pin = $this->getDefaultPIN();

        // Uncomment the following line if AJAX validation is needed
        $this->performAjaxValidation($model);

        if (isset($_POST['User'])) {
            $model->attributes = $_POST['User'];
            if ($model->validate()) {
                $model->save(false);
                $this->actionUpdate($model->id);
            } else {
                Log::w("Can not save new data.", "phonalisa-webinterface");
                app()->end();
            }
        }
        $this->renderPartial(
                '_form', array(
            'model' => $model,
            'availableGroups' => Groups::model()->getNestedGroupList(),
            'availableAudiofiles' => AudioFile::model()->getAudioFileList(AudioFileUseCase::CALL_WAITING),
                ), false, true
        );
    }

    protected function getDefaultPassword()
    {
        $defaultPassword = cfg("DEFAULT_NEW_USER_PASSWORD");
        if (empty($defaultPassword)) {
            $defaultPassword = PasswordGenerator::generateUserPassword();
        }
        return $defaultPassword;
    }

    protected function getDefaultPIN()
    {
        $defaultPIN = cfg("DEFAULT_NEW_USER_PIN");
        if (empty($defaultPIN)) {
            $defaultPIN = PasswordGenerator::generateUserPIN();
        }
        return $defaultPIN;
    }

    public function saveSecretaries($model)
    {
        $SecretaryPost = array();
        if (isset($_POST['Secretary'])) {
            $SecretaryPost = $_POST['Secretary'];
        }
        $oldParams = $this->getSecretarys($model->id);
        $postedSecretaryIds = $this->getPostedSecretarysIds($SecretaryPost);
        if ($oldParams) {
            foreach ($oldParams as $oldParam) {
                if (!in_array($oldParam->secretaryId, $postedSecretaryIds) || $oldParam->secretaryId == null) {
                    $oldParam->delete();
                }
            }
        }
        foreach ($SecretaryPost as $attributes) {

            $attributes['bossId'] = $model->id;

            if (!$this->hasNoValues($attributes)) {
                $this->saveParameter($attributes);
            }
        }
    }

    public function paramExists($secretaryId, $bossId)
    {
        $param = Secretary::model()->findByAttributes(array('secretaryId' => $secretaryId, 'bossId' => $bossId));
        if (!$param) {
            return false;
        }
        return $param;
    }

    public function saveParameter($attributes)
    {

        $param = $this->paramExists($attributes['secretaryId'], $attributes['bossId']);

        if (!$param) {
            $newParameter = new Secretary();
            $newParameter->attributes = $attributes;

            if (!$newParameter->save()) {
//                dump($newParameter->errors);
//                die();
            }
        } else {

            $param->attributes = $attributes;

            if (!$param->save()) {
//                dump($param->errors);
//                die();
            }
        }
    }

    protected function hasNoValues($attributes)
    {
        $hasNoValues = true;
        foreach ($attributes as $attributeName => $attributeValue) {
            if ($attributeValue != '') {
                $hasNoValues = false;
            }
        }
        return $hasNoValues;
    }

    public function getPostedSecretarysIds($post)
    {
        $postedSecretaryIds = array();
        foreach ($post as $attributes) {
            $postedSecretaryIds[] = $attributes['secretaryId'];
        }
        return $postedSecretaryIds;
    }

    public function getSecretarys($modelId)
    {
        $oldParams = Secretary::model()->findAllByAttributes(array('bossId' => $modelId));
        if (empty($oldParams)) {
            return false;
        }
        return $oldParams;
    }

    public function renderSave($runValidation = true, $attributes = null)
    {
        if (!$runValidation || $this->validate($attributes)) {
            return $this->getIsNewRecord() ? $this->insert($attributes) : $this->update($attributes);
        } else {
            return false;
        }
    }

    /**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id the ID of the model to be updated
     */
    public function actionUpdate($id)
    {
        if (@$_POST['deleteRequest'] == 'true' && !isset($_POST['ajax'])) {
            $this->actionDelete($id);
        }

        $model = $this->loadModel($id);
        $model->oldName = $model->name;
        if (!isset($model->faxSendAllowed)) {
            $model->faxSendAllowed = User::FAX_SEND_INHERIT_FROM_GROUP;
        }

        if ($model->isSystemAdmin) {
            $model->scenario = "isSystemAdminUpdate";
        } else {
            $model->scenario = "adminUpdate";
        }

        $model->unsetAttributes(array('password'));

        // Uncomment the following line if AJAX validation is needed
        $this->performAjaxValidation($model);

        if (isset($_POST['User'])) {

            $userModel = app()->user->realUserInstance;
            if (!$userModel->isSystemAdmin) {
                unset($_POST["User"]["password"]);
                unset($_POST["User"]["isSystemAdmin"]);
            }
            if ($model->isSystemAdmin && isset($_REQUEST['User']['alert'])) {
                $userSettings = $model->getSettings();
                $userSettings->setAdminAlertSubscriptions($_REQUEST['User']['alert']);
            }

            $oldExtension = $model->extension;
            $model->attributes = $_POST['User'];

            $account = SipAccounts::model()->findByAttributes(
                    array(
                        'user_id' => $model->id,
                        'authname' => $oldExtension
                    )
            );

            if ($account) {
                $account->authname = $model->extension;
                $account->save();
            }

            $internAddress = $internAddress = Addresses::model()->findByPk($model->addressReferece);
            if (!$internAddress) {
                $model->addressReferece = $this->createInternAddress($model->attributes);
            }

            // Fix for redirect bug in initializer
            if ($model->scenario != 'firstUser') {
                if (($userModel != null) && ($userModel->id == $model->id)) {
                    $model->isSystemAdmin = $userModel->isSystemAdmin;
                }
            }

            if ($model->validate()) {
                $model->save(false);
                $this->saveSecretaries($model);
                $this->saveTiers($model->id);
                $this->saveExternalNumbers($model->id);

                //update the intern Addressbook entry from this user
                if ($internAddress) {
                    $this->updateInternAddress($model->attributes, $internAddress);
                }
            } else {
                throw new CHttpException(500, 'Can not save new data.');
            }
        }
        $this->renderPartial(
                '_form', array(
            'model' => $model,
            'availableGroups' => Groups::model()->getNestedGroupList(),
            'availableAudiofiles' => AudioFile::model()->getAudioFileList(AudioFileUseCase::CALL_WAITING),
                ), false, true
        );
    }

    public function saveExternalNumbers($modelId)
    {
        $postedAttributes = array();
        $oldParams = ExternalNumber::model()->findAllByAttributes(array('userId' => $modelId));
        $postedIds = array();
        foreach ($oldParams as $number) {
            $oldParams[$number->id] = $number;
        }


        if (isset($_POST['ExternalNumber'])) {

            foreach ($_POST['ExternalNumber'] as $post) {
                if (!is_array($post) || $post['pattern'] == '') {
                    continue;
                }
                $postedAttributes[] = $post;
            }

            foreach ($postedAttributes as $attributes) {

                if ($attributes['dataId'] == '') {
                    $number = new ExternalNumber();
                } else {
                    $number = $oldParams[$attributes['dataId']];
                    $postedIds[] = $attributes['dataId'];
                }
                $number->attributes = $attributes;
                $number->userId = $modelId;
                if (!$number->save()) {
                    dump($number->errors);
                    die('error, could not save $number');
                }
            }
            foreach ($oldParams as $id => $number) {
                if (!in_array($number->id, $postedIds)) {
                    $number->delete();
                }
            }
        } else {
            if (!empty($oldParams)) {
                foreach ($oldParams as $id => $number) {
                    $number->delete();
                }
            }
        }
    }

    public function saveTiers($modelId)
    {

        $postedAttributes = array();
        $oldParams = Tiers::model()->findAllByAttributes(array('userId' => $modelId));
        $postedIds = array();
        foreach ($oldParams as $tier) {
            $oldParams[$tier->id] = $tier;
        }


        if (isset($_POST['Tiers'])) {

            foreach ($_POST['Tiers'] as $post) {
                if (!isset($post['queueId']) || !is_array($post) || $post['queueId'] == '') {
                    continue;
                }
                $postedAttributes[] = $post;
            }
            foreach ($postedAttributes as $attributes) {
                if ($attributes['dataId'] == '') {
                    $tier = new Tiers();
                } else {
                    $tier = $oldParams[$attributes['dataId']];
                    $postedIds[] = $attributes['dataId'];
                }
                $tier->attributes = $attributes;
                $tier->userId = $modelId;
                $tier->type = TiersType::user;

                if (!$tier->save()) {
                    dump($tier->errors);
                    die('error, could not save tiers');
                }
            }
            foreach ($oldParams as $id => $tier) {
                if (!in_array($tier->id, $postedIds)) {
                    $tier->delete();
                }
            }
        } else {
            if (!empty($oldParams)) {
                foreach ($oldParams as $id => $tier) {
                    $tier->delete();
                }
            }
        }
    }

    public function createInternAddress($newAttributes)
    {
        //creating intern addressbook enty for this user
        $internAddressbook = Addressbook::model()->findByAttributes(array('type' => AddressbookType::intern));
        if ($internAddressbook) {
            $internAddress = new Addresses();
            if ($newAttributes['firstname'] . $newAttributes['lastname'] === "") {
                $internAddress->n_given = $newAttributes['name'];
            } else {
                $internAddress->n_given = $newAttributes['firstname'];
                $internAddress->n_family = $newAttributes['lastname'];
            }

            $internAddress->contact_owner = 'intern';
            $internAddress->contact_created = time();
            $internAddress->contact_email = $newAttributes['email'];
            $internAddress->contact_tid = $internAddressbook->id;
            $internAddress->tel_work = $newAttributes['extension'];
            $internAddress->source = AddressSourceType::SYSTEM;

            if (!$internAddress->save()) {
                $newAddress->errors;
            } else {
                return $internAddress->id;
            }
        }
    }

    public function updateInternAddress($newAttributes, $internAddress)
    {
        if ($internAddress) {
            $searchAttributes = array();

            if ($newAttributes['firstname'] . $newAttributes['lastname'] === "") {
                $searchAttributes['n_given'] = $newAttributes['name'];
            } else {
                $searchAttributes['n_given'] = $newAttributes['firstname'];
                $searchAttributes['n_family'] = $newAttributes['lastname'];
            }

            $searchAttributes['tel_work'] = $newAttributes['extension'];
            $searchAttributes['contact_email'] = $newAttributes['email'];
            $internAddress->attributes = $searchAttributes;
            $internAddress->save();
        }
    }

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'admin' page.
     * @param integer $id the ID of the model to be deleted
     */
    public function actionDelete($id)
    {
        if (Yii::app()->request->isPostRequest) {
            // we only allow deletion via POST request
            //die('[]');
            $this->loadModel($id)->delete();
            if ($this->id == app()->user->realUserId) {
                throw new CHttpException(400, Yii::t('err', __('USER_MODEL_ERROR_MESSAGE_CANT_DELETE_YOURSELF')));
                return false;
            }

            // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
            $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
        } else {
            throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.');
        }
    }

    /**
     * Lists all models.
     */
    public function actionIndex()
    {
        $this->actionAdmin();
    }

    public function actionSwitchUser()
    {
        
    }

    /**
     * Manages all models.
     */
    public function actionAdmin()
    {
        $model = new User('search');
        //   $model->unsetAttributes();  // clear any default values
        if (isset($_GET['User'])) {
            $model->attributes = $_GET['User'];
        }

        $dataProvider = null;
        if (isset($_GET['groupId'])) {
            $criteria = new CDbCriteria;
            $criteria->order = 'name';
            $criteria->condition = 'group=' . $_GET['groupId'];

            $dataProvider = new CPhonalisaDataProvider('User', array('criteria' => $criteria));
        } else {
            $dataProvider = $model->search();
        }

        $this->render('admin', array(
            'model' => $model,
            'dataProvider' => $dataProvider,
            "allUsersGroup" => Groups::model()->findByAttributes(array("parent" => "0"))
        ));
    }

    protected function renderPhoneState($model)
    {
        $indicatorId = 'extState_' . $model->extension;
        return '<span class="label" id="' . $indicatorId . '">Offline</span>';
    }

    public function actionExport()
    {
        $attributes = array(
            "name",
            "pin",
            "extension",
            "firstname",
            "lastname",
            "email"
        );
        $this->exportAllAsCsv("User", $attributes);
    }

    private function exportAllAsCsv($modelName, $attributes = array())
    {
        $limit = 1;
        $offset = 0;
        $this->setCsvHeaders();
        while ($models = $this->getModelsForExport($modelName, $limit, $offset)) {
            $csvData = array();
            if ($offset === 0) {
                $this->outputCsvHeader($attributes, $csvData);
            }

            foreach ($models as $model) {
                $this->createCsvDataFromModel($model, $csvData, $attributes);
            }
            if (!empty($csvData)) {
                $this->outputCsvData($csvData);
            }
            $offset = $offset + $limit;
        }
    }

    private function setCsvHeaders()
    {
        $fileName = "phonalisa_User_" . date('Y-m-d_G-i-s') . ".csv";
        header('Content-type: text/csv');
        header("Content-disposition: attachment; filename=$fileName");
        header("Pragma: no-cache");
        header("Expires: 0");
    }

    private function outputCsvHeader($attributes, &$csvData, $delimiter = ";")
    {
        if (!$attributes) {
            return;
        }
        $csvData[] = $attributes;
    }

    private function getModelsForExport($modelName, $limit, $offset)
    {
        $models = PhonalisaRecord::model($modelName)->find(array(), "id", $limit, $offset);
        if (empty($models)) {
            return false;
        }
        return $models;
    }

    private function createCsvDataFromModel($model, &$csvData, $attributes = array())
    {
        if (empty($attributes)) {
            $attributes = array_keys($model->attributes);
        }

        $modelData = array();
        foreach ($attributes as $attribute) {
            $modelData[$attribute] = $model->$attribute;
        }
        $csvData[] = $modelData;
    }

    private function outputCsvData($csvData, $delimiter = ";")
    {
        foreach ($csvData as $csvLineData) {
            echo implode($delimiter, $csvLineData) . "\n";
        }
    }

    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     * @param integer the ID of the model to be loaded
     */
    public function loadModel($id)
    {
        $model = User::model()->findByPk($id);
        if ($model === null) {
            throw new CHttpException(404, 'The requested page does not exist.');
        }
        return $model;
    }

    public function availableUserGroups()
    {
        return Groups::model()->findAll("type = 'user'");
    }

    /**
     * Performs the AJAX validation.
     * @param CModel the model to be validated
     */
    protected function performAjaxValidation($model)
    {
        if (isset($_POST['ajax']) && $_POST['ajax'] === 'user-form') {
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    }

    public function getTabularFormTabs($form, $model, $availableGroups, $availableAudiofiles)
    {
        $secretary = new Secretary();
        $alert = new Alert();

        $tabs = array();
        $count = 0;
        $translateKeys = array();

        $translateKeys['generalData'] = __('USER_MODEL_TAB_MENU_GENERAL_DATA');
        if (PhonalisaLicenseManager::routingQueuesMax()) {
            $translateKeys['queues'] = __('USER_MODEL_TAB_MENU_QUEUES');
        }
        $translateKeys['secretaryTab'] = __('USER_MODEL_TAB_SECRETARY');
        $translateKeys['callThrough'] = __('USER_MODEL_TAB_MENU_CALL_TROUGH');
        $translateKeys['additionalData'] = __('USER_MODEL_TAB_MENU_ADDITIONAL_DATA');

        if ($model->isSystemAdmin) {
            $translateKeys['alerts'] = __('USER_MODEL_TAB_MENU_ALERTS');
        }

        $secretaryUsersCount = count($this->getListDataForSecretaryDropdown($model));
        $queueCount = (int) Queue::model()->countAllByAttributes(array());

        foreach ($translateKeys as $view => $tabLabel) {
            if ($view == 'queues' && $queueCount == 0) {
                $content = $this->renderPartial('notFound', array('modelName' => 'Queue'), true);
            } else if ($view == 'secretaryTab' && $secretaryUsersCount == 0) {
                $content = $this->renderPartial('notFound', array('modelName' => 'User'), true);
            } else {
                $content = $this->renderPartialWithContextHelp(
                        $view, array(
                    'form' => $form,
                    'model' => $model,
                    'availableGroups' => $availableGroups,
                    'availableAudiofiles' => $availableAudiofiles,
                    'secretary' => $secretary,
                    'alert' => $alert
                        ), true
                );
            }

            $tabs[] = array(
                'active' => $count++ === 0,
                'label' => $tabLabel,
                'content' => $content
            );
        }
        return $tabs;
    }

    public function renderQueueInput($data, $row, $column)
    {
        $this->renderPartial('queueInput', array('data' => $data, 'row' => $row, 'column' => $column));
    }

    public function renderSecretaryDropDown($data, $row, $column)
    {
        $modelId = null;
        $modelId = @$_REQUEST['id'];

        $this->renderPartial(
                'secretaryDropDown', array(
            'data' => $data,
            'row' => $row,
            'column' => $column,
            'modelId' => $modelId
                )
        );
    }

    public function renderExternalNumberInput($data, $row, $column)
    {
        $this->renderPartial('externalNumberInput', array('data' => $data, 'row' => $row, 'column' => $column));
    }

    public function getListDataForSecretaryDropdown($model)
    {
        $secretary = new Secretary();
        $listData = array();

        $members = $secretary->getSecretarys($model->id);

        $availableUsers = User::model()->find(array(), 'name');
        foreach ($availableUsers as $key => $user) {
            if (array_key_exists($user->id, $members) || $user->id == $model->id) {
                unset($availableUsers[$key]);
            } else {
                $listData[$user->id] = getFormatedUsername($user);
            }
        }
        return $listData;
    }

    public function getQueueAttributeVisibility()
    {
        return Queue::model()->getVisibilityByLicense();
    }

    public function actionCheckUserLimitation()
    {
        $userAllowed = 'true';
        if (!User::model()->userLimitationAllowedMoreUsers()) {
            $userAllowed = 'false';
        }
        echo json_encode($userAllowed);
        Yii::app()->end();
    }
}
