<?php

/**
 * This is the model class for table "plate_list".
 *
 * The followings are the available columns in table 'plate_list':
 * @property integer $id
 * @property string $name
 * @property string $source
 * @property integer $code
 * @property integer $auto_import
 * @property string $import_folder
 * @property string $epoch
 * @property string $import_type
 * @property integer $editable
 * @property integer $visible
 * @property string $title
 * @property string $mode
 * @property DateTime $last_change
 * @property boolean $autoconfirm
 * @property string $autoconfirm_wait
 * @property string $image
 * @property string $mintime
 * @property string $maxtime
 * @property string $maxsize
 * @property integer import_default_gate_id
 * @property string import_default_gate_type
 * @property string import_status
 * @property DateTime import_last_update
 */
class PlateList extends ActiveRecord
{

  const MODE_BLACK_LIST = 'blacklist';

  const MODE_WHITE_LIST = 'whitelist';
  
  const IMPORT_STATUS_STARTING  ='starting';
  const IMPORT_STATUS_STARTED  ='started';
  const IMPORT_STATUS_COMPLETED  ='completed';
  const IMPORT_STATUS_FAILED  ='failed';
  
 
  
  public $editable = true;

  public $visible = true;

  public $downloadable = true;

  public $autoconfirm;

  public $autoconfirm_wait;

  public $image;

  /**
   * Returns the static model of the specified AR class.
   *
   * @param string $className
   *          active record class name.
   * @return PlateList 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 'plate_list';
  }

  public function scopes()
  {
    return array (
        'visible' => array (
            'condition' => "visible=true" 
        ),
    	'importRunning' => array (
    		'condition' => "import_status=:status_starting or import_status=:status_started",
    		'params' => array (
                ':status_starting' => self::IMPORT_STATUS_STARTING,
                ':status_started' => self::IMPORT_STATUS_STARTED 
            )
    	),
    );
  }

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

  /**
   *
   * @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 (
            'auto_import, editable, visible, downloadable, autoconfirm',
            'boolean',
            'trueValue' => 1,
            'falseValue' => 0 
        ),
        array (
            'code',
            'numerical',
            'integerOnly' => true,
            'min' => 0,
            'tooSmall' => t ( 'You must insert a value greater than 0' ) 
        ),
        array (
            'code',
            'unique' 
        ),
        array (
            'name, source, import_folder, title, mode',
            'length',
            'max' => 255 
        ),
        array (
            'name, source, code, mode',
            'required' 
        ),
        array (
            'import_type',
            'length',
            'max' => 250 
        ),
        array (
            'editable, visible, downloadable, autoconfirm',
            'default',
            'setOnEmpty' => true,
            'value' => 1 
        ),
        array (
            'epoch',
            'safe' 
        ),
        array (
            'autoconfirm_wait',
            'default',
            'setOnEmpty' => true,
            'value' => '00:00:00' 
        ),
        array (
            'image',
            'file',
            'types' => 'jpg, gif, png',
            'allowEmpty' => true,
            'on' => 'insert,update' 
        ),
        array (
            'image',
            'length',
            'max' => 255,
            'on' => 'insert,update' 
        ),
        // The following rule is used by search().
        // Please remove those attributes that should not be searched.
        array (
            'id, name, source, code, auto_import, import_folder, epoch, import_type, editable, visible, title, mode, downloadable, mintime, maxtime, maxsize',
            '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 (
        'owners' => array (
            self::HAS_MANY,
            'VehicleOwner',
            'list_code' 
        ),
        'vehicles' => array (
            self::HAS_MANY,
            'Vehicle',
            'list_code' 
        ),
        'periods' => array (
            self::HAS_MANY,
            'ValidityPeriod',
            'list_code' 
        ),
        'plate_auths' => array (
            self::HAS_MANY,
            'PlateAuthorization',
            'list_code' 
        ) 
    );
  }

  /**
   *
   * @return DateInterval
   */
  public function getMinimumDuration()
  {
    return DateIntervalEnhanced::recalculateStatic ( date_interval_create_from_date_string ( isEmptyOrWhitespace ( $this->mintime ) ? "0 seconds" : $this->mintime ) );
  }

  /**
   *
   * @return boolean
   */
  public function hasMinimumDuration()
  {
    return ! isEmptyOrWhitespace ( $this->mintime );
  }

  /**
   *
   * @return DateInterval
   */
  public function getMaximumDuration()
  {
    return DateIntervalEnhanced::recalculateStatic ( date_interval_create_from_date_string ( isEmptyOrWhitespace ( $this->maxtime ) ? "100 years" : $this->maxtime ) );
  }

  /**
   *
   * @return boolean
   */
  public function hasMaximumDuration()
  {
    return ! isEmptyOrWhitespace ( $this->maxtime );
  }

  /**
   *
   * @return integer
   */
  public function getMaximumSize()
  {
    return $this->maxsize == null || $this->maxsize <= 0 ? 0 : intval ( $this->maxsize );
  }

  /**
   *
   * @return array customized attribute labels (name=>label)
   */
  public function myAttributeLabels()
  {
    return array (
        'id' => t ( 'ID' ),
        'name' => t ( 'Name' ),
        'source' => t ( 'Source' ),
        'code' => t ( 'Code' ),
        'auto_import' => t ( 'Auto import' ),
        'import_folder' => t ( 'Import folder' ),
        'epoch' => t ( 'Epoch' ),
        'import_type' => t ( 'Import type' ),
        'editable' => t ( 'Editable' ),
        'visible' => t ( 'Visible' ),
        'title' => t ( 'Title' ),
        'mode' => t ( 'Mode' ),
        'downloadable' => t ( 'Downloadable' ),
        'autoconfirm' => t ( 'Autoconfirm' ),
        'autoconfirm_wait' => t ( 'Autoconfirm interval' ),
        'image' => t ( 'Image' ),
        'mintime' => t ( 'Minimum duration' ),
        'maxtime' => t ( 'Maximum duration' ),
        'maxsize' => t ( 'Maximum size' ) 
    );
  }

  /**
   * Retrieves a list of models based on the current search/filter conditions.
   *
   * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
   */
  public function search()
  {
    // Warning: Please modify the following code to remove attributes that
    // should not be searched.
    $criteria = new CDbCriteria ();
    
    $criteria->compare ( 'id', $this->id );
    $criteria->compare ( 'name', $this->name, true );
    $criteria->compare ( 'source', $this->source, true );
    $criteria->compare ( 'code', $this->code );
    $criteria->compare ( 'auto_import', $this->auto_import );
    $criteria->compare ( 'import_folder', $this->import_folder, true );
    $criteria->compare ( 'epoch', $this->epoch, true );
    $criteria->compare ( 'import_type', $this->import_type, true );
    $criteria->compare ( 'editable', $this->editable );
    $criteria->compare ( 'visible', $this->visible );
    $criteria->compare ( 'title', $this->title, true );
    $criteria->compare ( 'mode', $this->mode, true );
    
    return new CActiveDataProvider ( $this, array (
        'criteria' => $criteria 
    ) );
  }

  /**
   * Retrieves a list of models based on the current search/filter conditions.
   *
   * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
   */
  public function searchAll()
  {
    $criteria = new CDbCriteria ();
    return new CActiveDataProvider ( $this, array (
        'criteria' => $criteria 
    ) );
  }

  /**
   *
   * @return CActiveDataProvider
   */
  public function searchVisible()
  {
    $dataProvider = new CActiveDataProvider ( PlateList::model ()->visible () );
    $dataProvider->pagination = false;
    return $dataProvider;
  }

  /**
   *
   * @return PlateList[]
   */
  public static function getAllLists()
  {
    return PlateList::model ()->findAll ( array (
        'order' => 'name' 
    ) );
  }

  /**
   *
   * @param integer $code          
   * @return PlateList
   */
  public static function findByCode($code)
  {
    return PlateList::model ()->find ( 'code=:cd', array (
        ':cd' => $code 
    ) );
  }

  public static function getModeList()
  {
    $list [self::MODE_BLACK_LIST] = t ( 'Blacklist' );
    $list [self::MODE_WHITE_LIST] = t ( 'WhiteList' );
    
    return $list;
  }

  public static function getImportType()
  {
    $list ['default'] = t ( 'Default' );
    
    return $list;
  }

  /**
   *
   * @return boolean
   */
  public function userHasAccess()
  {
    return user ()->checkAccess ( 'plate_list_' . $this->code ) || user ()->checkAccess ( 'plate_list_view_all');
  }

  /**
   *
   * @return boolean
   */
  public function userHasAccessCheckAll()
  {
    if (user ()->checkAccess ( 'plate_list_management' ) || $this->userHasAccess ())
    {
      if (($this->isBlacklist () && user ()->checkAccess ( 'blacklist_visibility' )) || $this->isWhitelist () && user ()->checkAccess ( 'whitelist_visibility' ))
        return true;
    }
    return false;
  }

  /**
   *
   * @return boolean
   */
  public function userCanSeeList()
  {
    if ($this->visible || user ()->checkAccess ( 'view_hidden_plate_list' ))
    {
      if (($this->isBlacklist () && user ()->checkAccess ( 'blacklist_visibility' )) || $this->isWhitelist () && user ()->checkAccess ( 'whitelist_visibility' ))
        return true;
    }
    return false;
  }

  /**
   *
   * @return boolean
   */
  public function isWhitelist()
  {
    return $this->mode == self::MODE_WHITE_LIST;
  }

  /**
   *
   * @return boolean
   */
  public function isBlacklist()
  {
    return $this->mode == self::MODE_BLACK_LIST;
  }

  /**
   *
   * @return PlateList[]
   */
  public static function getCurrentUserLists()
  {
    $u = user ();
    
    $isListAdmin = $u->checkAccess ( 'plate_list_management' );
    $canSeeWhitelists = $u->checkAccess ( 'whitelist_visibility' );
    $canSeeBlacklists = $u->checkAccess ( 'blacklist_visibility' );
    $canSeeHidden = $u->checkAccess ( 'view_hidden_plate_list' );
    
    $liste = array ();
    
    foreach ( self::getAllLists () as $pl )
    {
      if (! $canSeeHidden && ! $pl->visible)
        continue;
      if (! $canSeeWhitelists && $pl->isWhitelist ())
        continue;
      if (! $canSeeBlacklists && $pl->isBlacklist ())
        continue;
      if (! $isListAdmin && ! $pl->userHasAccess ())
        continue;
      $liste [] = $pl;
    }
   
    return $liste;
  }

  /**
   *
   * @return PlateList[]
   */
  public static function getCurrentUserWhiteLists()
  {
    $plateLists = array ();
    foreach ( self::getCurrentUserLists () as $pl )
      if ($pl->isWhitelist ())
        $plateLists [] = $pl;
    return $plateLists;
  }

  /**
   *
   * @return PlateList[]
   */
  public static function getCurrentUserBlackLists()
  {
    $plateLists = array ();
    foreach ( self::getCurrentUserLists () as $pl )
      if ($pl->isBlacklist ())
        $plateLists [] = $pl;
    return $plateLists;
  }

  public function createAccessRules()
  {
    $this->userHasAccess ();
  }

  public function deleteAccessRules()
  {
    AuthItem::deleteItem ( 'plate_list_' . $this->code );
  }

  public function getImagePath($default = null)
  {
    if (! empty ( $this->image ))
    {
      $path = dirname ( Yii::app ()->basePath ) . '/images/plate_lists/';
      if (! file_exists ( $path ))
        mkdir ( $path );
      return $path . $this->image;
    }
    if (! empty ( $default ))
    {
      $path = dirname ( Yii::app ()->basePath ) . '/images/plate_lists/' . $default;
      return $path;
    }
    return null;
  }

  public function getImageUrl($default = null)
  {
    if (! empty ( $this->image ))
    {
      return Yii::app ()->createAbsoluteUrl ( '/images/plate_lists/' . $this->image );
    }
    if (! empty ( $default ))
    {
      return Yii::app ()->createAbsoluteUrl ( $default );
    }
    return null;
  }

  public function getListType()
  {
    if ($this->mode == PlateList::MODE_BLACK_LIST)
      return t ( 'Black list' );
    if ($this->mode == PlateList::MODE_WHITE_LIST)
      return t ( 'White list' );
    return t ( 'Unknown' );
  }

  public function getListTitleComplete()
  {
    return $this->getListType () . ' ' . $this->getListTitle ();
  }

  public function getListTitle()
  {
    if (! empty ( $this->title ))
      return $this->title;
    if (! empty ( $this->name ))
      return $this->name;
    return $this->code;
  }

  /**
   *
   * @param mixed $id          
   * @param boolean $idIsCode          
   * @param boolean $throwOnFail
   *          default true
   * @throws CHttpException
   * @return PlateList
   */
  public static function load($id, $idIsCode, $throwOnFail = true)
  {
    if ($idIsCode)
      $model = PlateList::findByCode ( $id );
    else
      $model = PlateList::model ()->findByPk ( $id );
    if ($model === null)
      if ($throwOnFail)
        throw new CHttpException ( 404, 'The requested page does not exist.' );
      else
        return null;
    //if (! user ()->checkAccess ( 'plate_list_management' ) && ! user ()->checkAccess ( 'plate_list_' . $model->code ))
      //access_denied_check ( null, true );
      /*Mod. Comune di Amalfi, integrazione ZTL User Widget 02/04/2019 Ng*/
    if (!user ()->checkAccess ( 'plate_list_management' ) && !user ()->checkAccess ( 'plate_list_' . $model->code ) && (!isset($_ENV['token']) || !$model->source === 'ZtlWidget'))
       access_denied_check ( null, true );
    
    return $model;
  }

  
  public function getPlateAuthsStats()
  {
    $stats = array ();
    
    $stats ['to_be_confirmed'] = PlateAuthorization::model ()->count ( 'to_be_confirmed=1  AND list_code=:lc', array (
        ':lc' => $this->code 
    ) );
    $stats ['enabled'] = PlateAuthorization::model ()->count ( 'to_be_confirmed<>1 AND enabled=1 AND list_code=:lc', array (
        ':lc' => $this->code 
    ) );
    $stats ['disabled'] = PlateAuthorization::model ()->count ( 'to_be_confirmed<>1 AND enabled<>1 AND list_code=:lc', array (
        ':lc' => $this->code 
    ) );
   
    $stats ['valid'] = PlateAuthorization::model ()->byValidity ()
      ->count ( 't.list_code=:lc', array (
        ':lc' => $this->code 
    ) );
    $stats ['total'] = PlateAuthorization::model ()->count ( 'list_code=:lc', array (
        ':lc' => $this->code 
    ) );
    
    return $stats;
  }
}