<?php
/**
 * IMPORTANT NOTE
 * The code of this system is closed and a private proprietary of Flex Solutions.
 * A written authorization/license from Flex Solutions is required before using or modifying this code.
 * Email: sales@flexsolution.biz, Phone: +962795342585, Website: http://www.flexsolutions.biz
 */
 
/**
 * PobActiveRecord Model which all other Models extend from it
 *
 * @version 0.1
 * @author Amaney
 * @package application.models
 * 
 */
abstract class TidansActiveRecord extends CActiveRecord {

    public function behaviors() {
	return array(
	    'LoggableBehavior' => array(
		'class' => 'application.modules.auditTrail.behaviors.LoggableBehavior',
		'ignored' => array(
		    'created_date',
		    'last_edited_by',
		    'last_edited_date',
		    'created_by',
		    'id'
		),
		'ignored_class' => array(
		    'DocumentTypeTid',
		    //'AssetStatus',
		    //'TidansActiveRecord',
		    // 'Document',
		    'AuditTrail'
		),
	    ),
	    'UpdateDashboard' => array(
		'class' => 'application.models.DashboardUpdater',
		'allowedClasses' => array(
		    'Asset',
		    'AssetStatus',
		    'Segment',
		    'TidStatus',
		    'Tid',
		    'RenewalStage'
		),
	    )
	);
    }

    function yiiparam($name, $default = null) {
	if (isset(Yii::app()->params[$name]))
	    return Yii::app()->params[$name];
	else
	    return $default;
    }

    /**
     * Prepares create_time, create_user_id, update_time and update_user_id attributes before performing validation.
     */
    protected function beforeValidate() {

	if ($this->isNewRecord) {
	    //  set the create date, last updated date and the user doing the creating
	    $this->created_date = $this->last_edited_date = date("Y-m-d H:i:s");
	    if (Yii::app()->user->isGuest) {
		$this->created_by = $this->last_edited_by = 0;
	    } else {
		$this->created_by = $this->last_edited_by = Yii::app()->user->id;
	    }
	} else {
	    ////not a new record, so just set the last updated time and last updated user id
	    $this->last_edited_date = date("Y-m-d H:i:s");
	    if (Yii::app()->user->isGuest) {
		$this->last_edited_by = 0;
	    } else {
		$this->last_edited_by = Yii::app()->user->id;
	    }
	}

	return parent::beforeValidate();
    }

    /**
     * @return array contains label popover value
     */
    protected function attributeLabelsPopover() {
	return array();
    }

    /**
     * @return array scopes.
     */
    public function scopes() {
	return array(
	    'active' => array(
		'condition' => 'status=\'Active\'',
	    ),
	);
    }

    /**
     * Export data to excel file
     *
     * @param string $name the name of the excel file
     * @param tidansActiveRecord $model the model the we need to export its info to excel file
     * @param string $header the header columns
     * @param string $columns the selected columns in the query
     * @param Criteria $criteria_real the customized criteria or null to use default criteria
     */
    public function exportToExcel($name, $model, $header, $column, $criteria_real = null) {
	$criteria = ($criteria_real != null) ? $criteria_real : new CDbCriteria;
	$criteria->select = $column;
	$data = $model->commandBuilder->createFindCommand(
			$model->tableName(), $criteria)->queryAll();
	array_unshift($data, $header);
	Yii::import('application.extensions.jphpexcel.JPhpExcel');
	$xls = new JPhpExcel('UTF-8', false, $name);
	$xls->addArray($data);
	$xls->generateXML($name);
    }

    /**
     * @return String the identifier of the current model (like the name of segment, the tid_no of tid...)
     */
    public function getModelIdentifierValue() {

	if ($this instanceof Cca)
	    return $this->full_name . ' (' . $this->id . ')';
	if ($this instanceof Tid)
	    return $this->tid_no . ' (' . $this->id . ')';

	if ($this instanceof Invoice)
	    return $this->number . ' (' . $this->id . ')';

	if ($this instanceof User)
	    return $this->username . ' (' . $this->id . ')';

	if ($this instanceof Asset)
	    return $this->asset_number . ' (' . $this->id . ')';

	if ($this instanceof AssetStatus)
	    return $this->asset->asset_number." (".$this->asset_id.", ". $this->id.")";
	
	if ($this instanceof TidStatus)
	    return $this->tid->tid_no ." (".$this->tid_id.", ". $this->id.")";

	try {
	    return $this->name . ' (' . $this->id . ')';
	} catch (Exception $e) {
	    $pk = $this->getPrimaryKey();
	    return is_array($pk) ? json_encode($pk) : $pk;
	}
    }

    /**
     * Get the difference in days between two date
     * @param string $date1 the first date
     * @param string $date2 the second date
     * @return Integer the difference in days between two date
     */
    public static function dateDiff($date1, $date2) {
	$diff = strtotime($date1) - strtotime($date2);
	if ($diff < 0) {
	    $diff = abs($diff);
	    $years = floor($diff / (365 * 60 * 60 * 24));
	    $months = floor(($diff - $years * 365 * 60 * 60 * 24) / (30 * 60 * 60 * 24));
	    $days = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24) / (60 * 60 * 24));
	    return $days;
	}
	return 0;
    }

    /**
     * Inserts a row into the table based on this active record attributes.
     * If the table's primary key is auto-incremental and is null before insertion,
     * it will be populated with the actual value after insertion.
     * Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
     * After the record is inserted to DB successfully, its {@link isNewRecord} property will be set false,
     * and its {@link scenario} property will be set to be 'update'.
     * @param array $attributes list of attributes that need to be saved. Defaults to null,
     * meaning all attributes that are loaded from DB will be saved.
     * @return boolean whether the attributes are valid and the record is inserted successfully.
     * @throws CDbException if the record is not new
     */
    public function insert($attributes=null) {
	if (!$this->getIsNewRecord())
	    throw new CDbException(Yii::t('yii', 'The active record cannot be inserted to database because it is not new.'));
	if ($this->beforeSave()) {
	    Yii::trace(get_class($this) . '.insert()', 'system.db.ar.CActiveRecord');
	    $builder = $this->getCommandBuilder();
	    $table = $this->getMetaData()->tableSchema;
	    $command = $builder->createInsertCommand($table, $this->getAttributes($attributes));
	    if ($command->execute()) {
		$primaryKey = $table->primaryKey;
		if ($table->sequenceName !== null) {
		    if (is_string($primaryKey) && $this->$primaryKey === null)
			$this->$primaryKey = $builder->getLastInsertID($table);
		    elseif (is_array($primaryKey)) {
			foreach ($primaryKey as $pk) {
			    if ($this->$pk === null) {
				$this->$pk = $builder->getLastInsertID($table);
				break;
			    }
			}
		    }
		}
		$this->_pk = $this->getPrimaryKey();
		if (!$this->afterSave())
		    return false;
		$this->setIsNewRecord(false);
		$this->setScenario('update');
		return true;
	    }
	}
	return false;
    }

    /**
     * Updates the row represented by this active record.
     * All loaded attributes will be saved to the database.
     * Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
     * @param array $attributes list of attributes that need to be saved. Defaults to null,
     * meaning all attributes that are loaded from DB will be saved.
     * @return boolean whether the update is successful
     * @throws CDbException if the record is new
     */
    public function update($attributes=null) {
	if ($this->getIsNewRecord())
	    throw new CDbException(Yii::t('yii', 'The active record cannot be updated because it is new.'));
	if ($this->beforeSave()) {
	    Yii::trace(get_class($this) . '.update()', 'system.db.ar.CActiveRecord');
	    if ($this->getOldPrimaryKey() === null)
		$this->setOldPrimaryKey($this->getPrimaryKey());
	    $this->updateByPk($this->getOldPrimaryKey(), $this->getAttributes($attributes));
	    $this->_pk = $this->getPrimaryKey();
	    if (!$this->afterSave())
		return false;
	    return true;
	}
	else
	    return false;
    }

    /**
     * Deletes the row corresponding to this active record.
     * @throws CDbException if the record is new
     * @return boolean whether the deletion is successful.
     */
    public function delete() {
	if (!$this->getIsNewRecord()) {
	    Yii::trace(get_class($this) . '.delete()', 'system.db.ar.CActiveRecord');
	    if ($this->beforeDelete()) {
		$result = $this->deleteByPk($this->getPrimaryKey()) > 0;
		if (!$this->afterDelete())
		    return false;
		return $result;
	    }
	    else
		return false;
	}
	else
	    throw new CDbException(Yii::t('yii', 'The active record cannot be deleted because it is new.'));
    }

    protected function afterSave() {
	if ($this->hasEventHandler('onAfterSave'))
	    $this->onAfterSave(new CEvent($this));
	if (!$this->hasErrors())
	    return true;
	return false;
    }

    protected function afterDelete() {
	if ($this->hasEventHandler('onAfterDelete'))
	    $this->onAfterDelete(new CEvent($this));
	if (!$this->hasErrors())
	    return true;
	throw new Exception(Yii::t('yii', CHtml::errorSummary($this)));
    }

    /**
     * Send notifications for all logistic admin users about expired assets or tids
     * @param String $subject the subject of the notification
     */
    public static function SendNotification($subject, $body, $user_role = null, $attachment_path = null) {
	if ($user_role != null)
	    $users = User::model()->active()->findAllByAttributes(array(), $condition = 'role ="' . $user_role . '"');
	else
	    $users = User::model()->active()->findAll();

	IF ($users != null) {
	    foreach ($users as $user) {
		if ($user->email != null && $user->email != '')
		    TIDANSMail::sendMail($subject, 'Dear ' . $user->username . "," . $body, $user->email, null, $attachment_path);
	    }
	}
    }

    /**
     * The following function is called when the system check if the expiry date of tid and asset to change tid status
     * And then notifiy concerned people
     */
    public static function UpdateTidAndAssetStatues() {
	$update_process_date = Setting::model()->findByAttributes(array('name' => 'update_process_last_run_date'));

	if ($update_process_date != null) {
	    $update_process_date->value = date("Y-m-d");
	    $update_process_date->save();
	} else {
	    $setting = new Setting();
	    $setting->name = 'update_process_last_run_date';
	    $setting->value = date("Y-m-d");
	    $setting->save();
	}

	Tid::UpdateTIDStatusAndSendEmails();
	Asset::UpdateAssetStatusAndSendEmails();
    }

    /**
     * a functoin to convert from camel case to string sepreated by space using regular expression
     * e.g. NonLDAPPerson ==> Non LDAP Person
     * @param string $model model name
     *
     * @return model after formatting
     */
    public static function ConvertCamelCasetoSpaces($model) {
	if ($model == 'RenewalStage')
	    $model = 'ProcessingStage';
	$parts = preg_split("/((?<=[a-z])(?=[A-Z])|(?=[A-Z][a-z]))/", $model);
	if ($parts != null)
	    for ($i = 0; $i < count($parts); $i++) {
		if ($parts[$i] == "Of")
		    $parts[$i] = "of";
	    }
	$model = implode(" ", $parts);
	return $model;
    }

}
