<?php

/**
 * This is the model class for table "work_periods".
 *
 * The followings are the available columns in table 'work_periods':
 * @property integer $id
 * @property integer $id_user
 * @property string $login_at
 * @property string $last_action_at
 * @property integer $closed
 * @property string $report_generation_date
 * @property integer $events_count
 * @property string $events_ids
 
 * @property User user
 * 
 * @property WorkPeriod open [scope]
 * @property WorkPeriod closed [scope]
 * @property WorkPeriod recently [scope] last 5
 */
class WorkPeriod extends ActiveRecord
{

  /**
   *
   * @param string $className          
   * @return WorkPeriod
   */
  public static function model($className = __CLASS__)
  {
    return parent::model ( $className );
  }

  public function tableName()
  {
    return 'work_periods';
  }

  public function rules()
  {
    return array (
        array (
            'id_user, login_at',
            'required' 
        ),
        array (
            'closed',
            'default',
            'value' => 0 
        ),
        
        array (
            'last_action_at',
            'safe' 
        ) 
    );
  }

  public function scopes()
  {
    return array (
        'open' => array (
            'condition' => 'closed = 0 OR closed IS NULL' 
        ),
        'closed' => array (
            'condition' => 'closed = 1' 
        ),
        'recently' => array (
            'order' => 'last_action_at DESC',
            'limit' => 5 
        ) 
    );
  }

  /**
   *
   * @param User $user          
   * @return WorkPeriod
   */
  public function byUser($user)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'id_user = :user_id',
        'params' => array (
            ':user_id' => $user->id 
        ) 
    ) );
    return $this;
  }

  /**
   *
   * @return WorkPeriod
   */
  public function notGenerated()
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'report_generation_date IS NULL' 
    ) );
    return $this;
  }

  /**
   *
   * @return WorkPeriod
   */
  public function withEvents()
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'with' => 'report_generation_date IS NULL' 
    ) );
    return $this;
  }

  /**
   *
   * @return WorkPeriod
   */
  public function orderByLoginTime()
  {
    $this->getDbCriteria ()->order = 'login_at DESC';
    return $this;
  }

  public function getEventsCount()
  {
    return count ( $this->events );
  }

  /**
   *
   * @return DateTimeEx
   */
  public function getLoginAt()
  {
    return new DateTimeEx ( $this->login_at );
  }

  public function getConditionForEvents()
  {
    return "ValidationTime BETWEEN '{$this->LoginAt}' AND '{$this->LastActionAt}'";
  }

  /**
   *
   * @return DateTimeEx
   */
  public function getLastActionAt()
  {
    return new DateTimeEx ( $this->last_action_at );
  }

  public function relations()
  {
    return array (
        'user' => array (
            self::BELONGS_TO,
            'User',
            'id_user' 
        ) 
    ); /*
        * 'events' => array (
        * self::HAS_MANY,
        * 'Event',
        * array (
        * 'id_validate_user' => 'id_user'
        * ),
        * 'condition' => $this->getConditionForEvents ()
        * )
        */
    
    // 'eventsCount' => array(self::STAT, 'Event', '', 'join' => 'left join work_periods on id_validate_user = id_user'),
    
    // 'events' => array(self::HAS_MANY, 'Event', array('id_user' => 'events.id_validate_user'), 'condition'=>'ValidationTime BETWEEN login_at AND last_action_at'),
    // 'eventsCount' => array(self::STAT, 'Event', array('id_user' => 'eventsCount.id_validate_user'), 'condition'=>'ValidationTime BETWEEN login_at AND last_action_at'),
    // 'eventsReadyToTagCount' => array(self::STAT, 'Event', '', 'join' => 'left join work_periods on id_validate_user = id_user'
    // 'eventsReadyToTagCount' => array(self::STAT, 'Event', array('id_user' => 'id_validate_user'),
    // 'condition' => "validation_result = 'approved'",
    // 'params' => array(':result' => Event::VALIDATION_RESULT_APPROVED),
    // ),
  }

  public function behaviors()
  {
    return array (
        'edatetimebehavior' => array (
            'class' => 'ext.EDateTimeBehavior' 
        ) 
    );
  }

  public function start($user, DateTime $startDateTime = null)
  {
    $this->closeStale ( $user );
    $this->id_user = $user->id;
    if (! isset ( $startDateTime ))
      $startDateTime = new Datetime ();
    
    $startDateTime->modify ( '+1 second' ); // ensure at least 1 second span between periods
    $this->login_at = $startDateTime;
    return $this->save ();
  }

  public function refresh(DateTime $refreshDateTime = null)
  {
    if (! isset ( $refreshDateTime ))
      $refreshDateTime = new DateTime ();
    
    $this->last_action_at = $refreshDateTime;
    return $this->save ();
  }

  public function getEventsReadyToTagCount()
  {
    return Report::numOfEventsToBeTagged ( $this );
  }

  public function getEventsApproved()
  {
    return Report::numOfEventsApproved ( $this );
  }

  public function getEventsInvalid()
  {
    return Report::numOfEventsInvalid ( $this );
  }

  public function getEventsManaged()
  {
    return PaySlip::numOfEventsManaged ( $this );
  }

  public function stop(DateTime $stopDateTime = null)
  {
    if (! isset ( $this->last_action_at ))
      $this->refresh ( $stopDateTime );
    
    $this->closed = 1;
    return $this->save ();
  }

  public function closeStale($user, DateTime $stopDateTime = null)
  {
    $periods = WorkPeriod::model ()->byUser ( $user )
      ->open ()
      ->findAll ();
    foreach ( $periods as $period )
      if (! $period->stop ( $stopDateTime ))
        throw new CException ( Yii::t ( 'app', 'Cannot close old user work periods.' ) );
  }

  public function getDuration()
  {
    $at = new DateTimeEx ( $this->last_action_at );
    $at = $at->toDateTime ();
    return $this->login_at->diff ( $at );
  }
}
