<?php

/**
 * This is the model class for table "storicotable".
 *
 * The followings are the available columns in table 'storicotable':
 * @property string  $ID
 * @property integer $UserID        da mettere a default 1. si può togliere
 * @property string  $EventType     "FILTER","OUT","CHECK","FOLLOW","PASS","IN/OUT","TRAJECTORY","FILTER","BLACKLIST","INTERESTINGEVENTS"
 *                    vedi Gate
 *                    se l'evento ha un transit type definito questo viene inserito nel database.
 *                    altrimenti sia ttiva una ricerca di corrispondenza tra la direzione rilevata dal dispositivo e le direzioni configurate
 *                    nel database nella tabella gatedirections. l'obiettivo è quello di identificare l'evento come ingresso o uscita da un certo varco.
 *                    Se un evento ha direzione con ID=1 e per il varco è configurata una direzione con medesimo ID e verso IN allora l'evento è
 *                    marcato come IN se la direzione è stata rilevata come verso FORWARD o come OUT in caso contrario. se non esiste una direzione
 *                    configurata per il varco, il ragionamento è fatto usando il type del varco stesso.
 *                    se il varco non è IN o OUT, se l'evento non ha una direzione, l'eneto mantiene il type del varco
 * @property string  $EventMode         mettere a default "". contiene la stringa concatenata conseparatore ';' di tutti i tg che identificano il comportamnto del veicolo
 *
 *
 *
 * @property string  $ModifiedBy    nome utente di chi ha effettuato la modifica
 * @property string  $EventValid    "VALID" mettere a default. nel caso di T-EXSPEED è una stringa composta da SN dispositivo_NumeroProgressivoViolazione es 2004_0000000234
 * @property integer $id_validate_user   id dell'utente che ha validato
 * @property string  $ValidatedBy   nome dell'utente che ha validato
 *                    può però assumere anche i segueti valori
 *                    "STANDBY": un evento in standby non può essere validato dall'utente. viene rimosso da standby dopo un periodo configurato
 *                    "YellowFilter": evento con tempo giallo fuori parametri. associato a protocol NO_MULTA
 *                    "PREVALIDATION": non usato
 *                    "AUTOVALIDATION": validato in modo automatco dal sistema.
 *                    "double_gate": associato a NO_MULTA. in una catena di varchi solo il passaggio dal primo viene multato. gli altri diventano NO_MULTA
 
 *
 * @property string  $ValidationTime    data e ora di validazione
 * @property string  $Protocol      numero di protocollo generato all'esportazione. NO_MULTA se non va esportato l'evento
 * @property integer $NextID        id evento successivo. mettere default a 0
 * @property integer $PreviousID      id evento successivo. mettere default a 0
 * @property integer $TicketID      default 0, numero biglietto per applicazioni parcheggio
 * @property string  $Ticket        default "", stringa identificativo biglietto per applicazioni parcheggio
 *                    per applicazioni T-EXSPEED usato come seriale Unità di elaborazione. meglio aggiungere un campo
 * @property integer $AreaID        id area di appartenenza in areatale
 * @property integer $PositionID      0, non usato
 * @property integer  $Direction      ID Direzione
 * @property double  $Speed       Velocità in Km/H
 * @property string  $Classe        Classe Veicolo
 * @property double  $Height        altezza veicolo in metri
 * @property double  $Width       larghezza veicolo in meri
 * @property double  $Length        lunghezza veicolo in metri
 * @property integer $LaneID        Corsia di appartenenza veicolo, -1 se non definita
 * @property boolean $IsBoxComputed   1 se sono state calcolate la dimensioni del veicolo
 * @property integer $Gate        varco corrispondente
 * @property string  $StartTime     Data/Ora inizio transito
 * @property string  $EndTime     Data/Ora fine transito
 * @property string  $Plate       Targa letta per il veicolo e poi eventualmente corretta a mano
 * @property string  $ExtPlate      Se la targa è stata corretta l'originale è scritto in questo campo
 * @property string  $Nationality   Nazionalità espresso come NNN-xxxxx = NNN->Nazione xxxx->descrizione Layout
 * @property string  $custom_nationality
 * @property string  $NetworkID     Identificativo numerico del tipo di targa
 * @property string  $Image       Binario Immagine
 * @property integer $ImageLength   dimensione binario immagine
 * @property string  $Comments      Commento da parte di chi valida sull'eventuale validazione o sul motivo dello scarto
 * @property string  $ExtraData     Binario con dati aggiuntivi
 * @property integer $ExtraDataLength Dimensione binario dati aggiuntivi
 * @property string  $Signature     binario Firma Elettronica messaggio
 * @property integer $SignatureLength lunhezza binario Firma Elettronica messaggio
 * @property string  $UUID        Identificativo univoco del transito
 * @property integer $ExtraInfoID   Chiave esterna che va si transitextrainfo.ID e su teb_table.EvenID
 * @property double  $MatchMeasure    numero da 0 a 100 che indica l'affidabilità della lettura OCR
 * @property string  $epoch       data inserimento transito
 * @property string  $validation_result
 * @property string  $ext_code
 * @property double  $ocr_quality
 public function actionSuspend($id)
 {
 $event = $this->loadModel($id);
 
 
 }
 * @property integer $id_run ID del servizio associato
 * @property string  $GateDescription Descrizione del varco (località)
 * @property string  $TransitComments contiene un commento sull'esito del check di white/black List
 * @property string  $GateType      tipo di dispositivo
 *                    "TRED"  T-RED
 *                    "TID"   T-ID
 *                    "TRS"   T-EXSPEED
 *                    "NONE"  non definito
 * @property string $Kemler       Targa merce pericolosa. "" se non presente
 * @property string $PlateCheck     se 1 indica che quel transito è stato veriicato dal sistema e può essere visionato dall'utente
 *                    se l'utente modifica la targa il transito, quando attiva la verifica di whitelist, PlateCheck deve essere messo a zero perchè
 *                    il sistema lo riprocessi. non può essere quindi validato
 * @property string $BlobFileName   Nome file dell'immagine se è attivo l'export delle immagini da database a disco
 * @property Gate gate
 * @property GateGroup gateGroup
 * @property Service service
 * @property EventBehavior[] eventBehaviors
 * @property EventBehavior[] eventBehaviorsToValidate
 * @property Behavior[] behaviors
 * @property MediaAttachment[] photos
 * @property MediaAttachment[] videos
 * @property VehicleColor colorSet
 * @property EventBehavior[] newEventBehaviors
 * @property EventBehavior[] approvedEventBehaviors
 * @property EventBehavior[] pendingEventBehaviors
 * @property EventBehavior[] voidEventBehaviors
 * @property EventBehavior[] invalidEventBehaviors
 * @property EventBehavior[] toBeManagedEventBehaviors
 * @property Alert alert
 * 
 * SCOPES:
 * @property Event new [scope]
 * @property Event void [scope]
 * @property Event unvoid [scope]
 * @property Event examined [scope]
 * @property Event validated [scope]
 * @property Event exported [scope]
 * @property Event notClosedYet [scope]
 * @property Event examinedNotClosedYet [scope]
 * @property Event pendingNotClosedYet [scope]
 * @property Event notClosedYetNotPending [scope]
 * @property Event examinedNotClosedYetNotPending [scope]
 * @property Event approved [scope]
 * @property Event invalid [scope]
 * @property Event pending [scope]
 * @property Event approvedOrInvalid [scope]
 */
class Event extends ActiveRecord implements IBookmarkObject, IVehicleEvent
{

  const STATUS_NEW = "new";

  const STATUS_EXAMINED = "examined";

  const STATUS_VALIDATED = "validated";

  const STATUS_VOID = "void";

  const VALIDATION_RESULT_APPROVED = "approved";

  const VALIDATION_RESULT_INVALID = "invalid";

  const VALIDATION_RESULT_PENDING = "pending";

  const VALIDATION_RESULT_VOID = "void";

  const VALIDATION_RESULT_NO_VALIDATION = "no_validation";

  const SQL_TO_BE_MANAGED = "validation_result is null or validation_result <> 'no_validation'";

  const SQL_NEW_CONDITION = "ValidatedBy = '' AND data_check = 0 AND (validation_result is null or validation_result <> 'no_validation')";

  const SQL_EXAMINED_CONDITION = "data_check = 1";

  const SQL_VALIDATED_CONDITION = "validation_result <> '' and validation_result <> 'no_validation'";

  const SQL_APPROVED_CONDITION = "validation_result = 'approved'";

  const SQL_INVALID_CONDITION = "validation_result = 'invalid'";

  const SQL_PENDING_CONDITION = "validation_result = 'pending'";

  const SQL_VOID_CONDITION = "validation_result = 'void'";

  const SQL_UNVOID_CONDITION = "validation_result <> 'void'";
  
  const SQL_VALIDATED_NOT_CONFIRMED = "validation_result <> '' and validation_result <> 'no_validation' and (ext_code IS NULL or ext_code ='')";

  const SQL_QUEUED_FOR_EXPORT_CONDITION = "ext_code IS NOT  NULL and ext_code != ''  and ext_code != '-'";

  const SQL_EXPORTED_CONDITION = "Protocol != '' and Protocol != 'NO_MULTA'";

  const SQL_NOT_CLOSED_YET_CONDITION = "(ext_code IS NULL  or ext_code = '') AND (validation_result is null or validation_result <> 'no_validation')";

  const SQL_EXAMINED_NOT_CLOSED_YET_CONDITION = "data_check = 1 AND  (ext_code  IS NULL OR ext_code = '')";

  const SQL_PENDING_NOT_CLOSED_YET_CONDITION = "validation_result = 'pending' AND (ext_code  IS NULL OR ext_code = '')";

  const SQL_NOT_CLOSED_YET_NOT_PENDING_CONDITION = "ext_code IS NULL AND (validation_result IS NULL OR validation_result != 'pending')";

  const SQL_EXAMINED_NOT_CLOSED_YET_NOT_PENDING_CONDITION = "data_check = 1 AND ext_code IS NULL AND (validation_result IS NULL OR validation_result != 'pending')";
  
  const SQL_PLATE_CHANGED = "ExtPlate != '' and ExtPlate != Plate";
  
  const SQL_CLASS_CHANGED = "custom_vehicle_type != '' adn custom_vehicle_type is not null and custom_vehicle_type != Classe";
  
  const OCR_QUALITY_LABEL_BAD = 'bad';
  
  const OCR_QUALITY_LABEL_MID = 'mid';
  
  const OCR_QUALITY_LABEL_GOOD = 'good';

  public $event_date_start;

  public $event_date_end;

  public $kemlerSearchString;

  public $search_speed_start;

  public $search_speed_end;

  public $minStartTime;

  public $maxStartTime;
  
  // fields for the admin search - BEGIN
  public $searchColor = null;

  public $searchBookmarked = false;

  public $searchByResult = null;
  // fields for the admin search - END
  
  /**
   *
   * @param string $className          
   * @return Event event's model
   */
  public static function model($className = __CLASS__)
  {
    return parent::model ( $className );
  }

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

  public function myAttributeLabels()
  {
    return array (
        'id_run' => Yii::t ( 'app', 'Service' ),
        'Plate' => Yii::t ( 'app', 'Lic. Plate' ),
        'custom_vehicle_type' => Yii::t ( 'app', 'Class' ),
        'custom_nationality' => Yii::t ( 'app', 'Nationality' ),
        'Kemler' => Yii::t ( 'app', 'Dangerous goods' ),
        'custom_plate_type' => Yii::t ( 'app', 'Lic. plate type' ),
        'custom_property_type' => Yii::t ( 'app', 'Sub-class' ),
        'kemlerSearchString' => t ( 'Kemler-ONU' ),
        'alert' => t ( 'Alert' ),
        'Nationality' => t ( 'Country' ),
        'LaneID' => t ( 'Lane' ),
        'Speed' => t ( 'Km/h' ),
        'GateID' => t ( 'Gate' ),
        'StartDate' => t ( 'Date' ),
        'StartTime' => t ( 'Time' ),
        'Kemler-ONU' => t ( 'Kemler-ONU' ) 
    );
  }

  public static function getLastServices($lastN = null)
  {
    if ($lastN != null && $lastN > 0)
      $reader = queryReader ( "SELECT DISTINCT id_run FROM storicotable ORDER BY id_run DESC LIMIT {$lastN}" );
    else
      $reader = queryReader ( "SELECT DISTINCT id_run FROM storicotable ORDER BY id_run DESC" );
    $services = array ();
    foreach ( $reader as $row )
    {
      $service = Service::findById ( $row ['id_run'], false );
      if ($service != null)
        $services [$service->ID] = $service;
    }
    return $services;
  }

  public function elimina()
  {
    $basePath = Yii::app ()->params ['photoBasePath'];
    // extrainfo record
    $teit = EventInfo::model ()->findByPk ( $this->ExtraInfoID );
    if ($teit != null)
      $teit->delete ();
      // color record
    $color = VehicleColor::model ()->findByPk ( $this->id_vehicle_color );
    if ($color != null)
      $color->delete ();
      // teb file + record
    $tebs = MediaAttachment::model ()->findAll ( 'EventID=:eid', array (
        ':eid' => $this->ExtraInfoID 
    ) );
    if (count ( $tebs ) > 0)
      foreach ( $tebs as $teb )
        if ($teb instanceof MediaAttachment)
        {
          $filename = pathCombine ( $basePath, $teb->BlobFileName );
          if (fileExists ( $filename ))
            unlink ( $filename );
          $teb->delete ();
        }
      // event behaviors
    foreach ( $this->eventBehaviors as $eb )
      if ($eb instanceof EventBehavior)
      {
        // event behavior violation documents
        $vdocs = ViolationDocument::model ()->findAll ( 'id_event_behavior=:eb', array (
            ':eb' => $eb->ID 
        ) );
        foreach ( $vdocs as $vd )
          if ($vd instanceof ViolationDocument)
          {
            $vddf = pathCombine ( $basePath, $vd->document_filename );
            if (fileExists ( $vddf ))
              unlink ( $vddf );
            $vddef = pathCombine ( $basePath, $vd->document_ext_filename );
            if (fileExists ( $vddef ))
              unlink ( $vddef );
            $vd->delete ();
          }
      }
      // event reportings
    $evreps = Alert::model ()->findAll ( "event_id=:eid AND event_table_name='storicotable'", array (
        ':eid' => $this->ID 
    ) );
    foreach ( $evreps as $er )
      if ($er instanceof Alert)
        $er->delete ();
    $bfn = pathCombine ( $basePath, $this->BlobFileName );
    if (fileExists ( $bfn ))
      unlink ( $bfn );
      // storicotable
    $this->delete ();
  }

  public function rules()
  {
    $rules = array (
        array (
            'Plate, custom_vehicle_type',
            'requiredIfBehaviorsAreNotInvalid' 
        ),
        array (
            'Plate, ExtPlate, Kemler',
            'default',
            'value' => '' 
        ),
        array (
            'Plate, LaneID, Gate, StartTime, Nationality, Classe, custom_nationality, custom_vehicle_type, Kemler, custom_plate_type, custom_property_type, event_date_start, event_date_end, kemlerSearchString, search_speed_start, search_speed_end',
            'safe' 
        ),
        array (
            'Plate, LaneID, Gate, StartTime, Nationality, Classe, custom_nationality, custom_vehicle_type, Kemler, custom_plate_type, custom_property_type, event_date_start, event_date_end, kemlerSearchString, search_speed_start, search_speed_end',
            'safe',
            'on' => 'search' 
        ) 
    );
    if (paramdeep ( 'events', 'nationality', 'required' ))
      $rules [] = array (
          'custom_nationality',
          'requiredIfBehaviorsAreNotInvalid' 
      );
    return $rules;
  }

  public function requiredIfBehaviorsAreNotInvalid($attribute, $params)
  {
    if (($this->validation_result != self::VALIDATION_RESULT_INVALID) && ($this->$attribute == ''))
      $this->addError ( $attribute, Yii::t ( 'yii', '{attribute} cannot be blank.', array (
          '{attribute}' => $this->getAttributeLabel ( $attribute ) 
      ) ) );
  }

  public function scopes()
  {
  	
  	return array (
        'new' => array (
            'condition' => self::SQL_NEW_CONDITION 
        ),
        'void' => array (
            'condition' => self::SQL_VOID_CONDITION 
        ),
        'unvoid' => array (
            'condition' => self::SQL_UNVOID_CONDITION 
        ),
        'examined' => array (
            'condition' => self::SQL_EXAMINED_CONDITION 
        ),
        'validated' => array (
            'condition' => self::SQL_VALIDATED_CONDITION 
        ),
        'exported' => array (
            'condition' => self::SQL_EXPORTED_CONDITION 
        ),
        'notClosedYet' => array (
            'condition' => self::SQL_NOT_CLOSED_YET_CONDITION 
        ),
        'examinedNotClosedYet' => array (
            'condition' => self::SQL_EXAMINED_NOT_CLOSED_YET_CONDITION 
        ),
        'pendingNotClosedYet' => array (
            'condition' => self::SQL_PENDING_NOT_CLOSED_YET_CONDITION 
        ),
        
        'notClosedYetNotPending' => array (
            'condition' => self::SQL_NOT_CLOSED_YET_NOT_PENDING_CONDITION 
        ),
        'examinedNotClosedYetNotPending' => array (
            'condition' => self::SQL_EXAMINED_NOT_CLOSED_YET_NOT_PENDING_CONDITION 
        ),
        
        'approved' => array (
            'condition' => 'validation_result = :result',
            'params' => array (
                ':result' => self::VALIDATION_RESULT_APPROVED 
            ) 
        ),
        'invalid' => array (
            'condition' => 'validation_result = :result',
            'params' => array (
                ':result' => self::VALIDATION_RESULT_INVALID 
            ) 
        ),
        'pending' => array (
            'condition' => 'validation_result = :result',
            'params' => array (
                ':result' => self::VALIDATION_RESULT_PENDING 
            ) 
        ),
        'approvedOrInvalid' => array (
            'condition' => 'validation_result = :resultApp or validation_result = :resultInv',
            'params' => array (
                ':resultApp' => self::VALIDATION_RESULT_APPROVED,
                ':resultInv' => self::VALIDATION_RESULT_INVALID 
            ) 
        ),
    		
    	'withPlateModified' => array ('condition' => self::SQL_PLATE_CHANGED),
    	'withClassModified' => array ('condition' => self::SQL_CLASS_CHANGED)

    );
  }

  public function getBookmarkData()
  {
    $a = $this->alert;
    $e = $this;
    $v = null;
    
    $bd = new CArray ();
    
    $bd->has_alert = $a != null;
    if ($a != null)
    {
      $v = $a->vehicleTrace;
      $bd->alert_id = $a->id;
      $bd->alert_book = Bookmark::model ()->find ( "id_user=:usr AND id_reference=:ref AND type=:typ", array (
          ':usr' => user ()->id,
          ':ref' => $bd->alert_id,
          ':typ' => Bookmark::TYPE_ALERT 
      ) );
    }
    
    $bd->has_event = $e != null;
    if ($e != null)
    {
      $bd->event_id = $e->ID;
      $bd->event_book = Bookmark::model ()->find ( "id_user=:usr AND id_reference=:ref AND type=:typ", array (
          ':usr' => user ()->id,
          ':ref' => $bd->event_id,
          ':typ' => Bookmark::TYPE_EVENT 
      ) );
    }
    
    $bd->has_trace = $v != null;
    if ($v != null)
    {
      $bd->trace_id = $v->ID;
      $bd->trace_book = Bookmark::model ()->find ( "id_user=:usr AND id_reference=:ref AND type=:typ", array (
          ':usr' => user ()->id,
          ':ref' => $bd->trace_id,
          ':typ' => Bookmark::TYPE_VEHICLE_TRACE 
      ) );
    }
    
    $bd->self_id = $this->ID;
    $bd->self_type = Bookmark::TYPE_EVENT;
    $bd->self_book = $bd->event_book;
    
    return $bd;
  }

  /**
   *
   * @param DateTime $begin          
   * @param DateTime $end          
   * @return Event
   */
  public function examinedBetween($begin, $end)
  {
    $begin = new DateTimeEx ( $begin );
    $end = new DateTimeEx ( $end );
    
    $interval = new CDbCriteria ();
    $interval->addBetweenCondition ( 'data_check_time', $begin->toString (), $end->toString () );
    $this->getDbCriteria ()
      ->mergeWith ( $interval );
    return $this;
  }

  /**
   *
   * @param DateTime $begin          
   * @param DateTime $end          
   * @return Event
   */
  public function validatedBetween($begin, $end)
  {
    $begin = new DateTimeEx ( $begin );
    $end = new DateTimeEx ( $end );
    
    $interval = new CDbCriteria ();
    $interval->addBetweenCondition ( 'ValidationTime', $begin->toString (), $end->toString () );
    $this->getDbCriteria ()
      ->mergeWith ( $interval );
    return $this;
  }
  
  public function validatedAfter($dateTime)
  {
  	$this->getDbCriteria()
  		->mergeWith(array(
  			'condition' => 'ValidationTime >= :startDateTime',
  			'params' => array(
  				':startDateTime' => DateHelper::formatISO9075DateTime($dateTime)
  			)
  		)
  	);
  	return $this;
  }
  
  public function validatedBefore($dateTime)
  {
  	$this->getDbCriteria()
  		->mergeWith(array(
  			'condition' => 'ValidationTime <= :endDateTime',
  			'params' => array(
  				':endDateTime' => DateHelper::formatISO9075DateTime($dateTime)
  			)
  		)
  	);
  	return $this;
  }

  public function withBookmark(CDbCriteria $criteria = null)
  {
    if ($criteria == null)
      $criteria = $this->getDbCriteria ();
    
    $criteria->with [] = 'bookmark';
    
    return $this;
  }

  public function byExaminer($user)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'id_data_check_user = :user_id',
        'params' => array (
            ':user_id' => $user->id 
        ) 
    ) );
    return $this;
  }

  public function byValidator($user)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'id_validate_user = :user_id',
        'params' => array (
            ':user_id' => $user->id 
        ) 
    ) );
    return $this;
  }

  public function byService($serviceId)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'id_run = :run_id',
        'params' => array (
            ':run_id' => $serviceId 
        ) 
    ) );
    return $this;
  }
  
  public function bySpeedRange($minSpeed, $maxSpeed)
  {
  	$this->getDbCriteria ()
  	->mergeWith ( array (
  			'condition' => 'Speed >= :min_speed and Speed <= :max_speed',
  			'params' => array (
  					':min_speed' => $minSpeed,
  					':max_speed' => $maxSpeed,
  			)
  	) );

  	return $this;
  	
  }

  /**
   *
   * @param integer $seconds          
   * @param string $datetimeField
   *          default='StartTime'
   * @return Event
   */
  public function recently($seconds, $datetimeField = 'StartTime')
  {
    if (isEmpty ( $datetimeField ) || ! $this->hasAttribute ( $datetimeField ))
      $datetimeField = 'StartTime';
    
    $interval = new DateInterval ( "PT{$seconds}S" );
    $past = new DateTime ();
    $past->sub ( $interval );
    
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => "$datetimeField >= :pasteDateTime",
        'params' => array (
            ':pasteDateTime' => DateHelper::formatISO9075DateTime ( $past ) 
        ) 
    ) );
    return $this;
  }

  public function byGate($gate)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'Gate = :gate_id',
        'params' => array (
            ':gate_id' => $gate->Gate 
        ) 
    ) );
    return $this;
  }

  public function byStatus($status)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'condition' => 'Gate = :gate_id',
        'params' => array (
            ':gate_id' => $gate->Gate 
        ) 
    ) );
    return $this;
  }
  
  
  public function byPlate($plate)
  {
  	$this->getDbCriteria ()
  	->mergeWith ( array (
  			'condition' => "MATCH(Plate) AGAINST('*".$plate."*' IN BOOLEAN MODE)" 
  			)
  	 );
  	return $this;
  	
 	
  }
  
  public function withNationalityChanged()
  {
  	$this->getDbCriteria ()->addCondition("custom_nationality != '' and custom_nationality is not null and iso_code != custom_nationality");

  	return $this;
  }
  
  public function byGates($gates)
  {
  	$alias = $this->getTableAlias(false, false);
  	
  	if (!is_array($gates))
  		$gates = array($gates);

  	$this->getDbCriteria()->addInCondition($alias . '.Gate', $gates);
  	
  	return $this;
  }
  
  public function byGatesId($gatesId)
  {
  	
  	if (!is_array($gatesId))
  		$gatesId = array($gatesId);
  	
  	$gates = Gate::model()->findAllByPk($gatesId);
  	
  	$gateNumbers = array();
  	foreach ($gates as $gate) {
  		$gateNumbers[] = $gate->Gate;
  	}
  	
  	$this->byGates($gateNumbers);
  	
  	return $this;
  }
  
  public function byVehicleClass($vehiclesClass)
  {
  	if (!is_array($vehiclesClass))
  		$vehiclesClass = array($vehiclesClass);
  

  		
  		$tags = array();
  		
  		
  		$cNats= new CDbCriteria;
  		 
  		foreach ($vehiclesClass as $class)
  		{
  			$cNat = new CDbCriteria;
  			$cNat->addCondition("t.custom_vehicle_type = '". $class."'");
  		
  			$cNat2 = new CDbCriteria;
  			$cNat2->addCondition("t.custom_vehicle_type = '' or t.custom_vehicle_type is null");
  		
  			$cNat2->addCondition ( "t.Classe = '". $class."'");
  		
  		
  			$cNat->addCondition($cNat2->condition, 'OR');
  			$cNat->params += $cNat2->params;
  		
  			$cNats->addCondition($cNat->condition, 'OR');
  			$cNats->params += $cNat->params;
  		}
  		 
  		
  		$this->getDbCriteria()->addCondition($cNats->condition);
  		$this->getDbCriteria()->params += $cNats->params;
  		
  		
  		
  		return $this;  		
  }
  
  function byDateTimeBoundaries($startTimestamp, $startTime, $endTimestamp, $endTime)
  {
  	if (isset($startTimestamp))
  	{
  		$startDateTime = new DateTime();
  		$startDateTime->setTimestamp($startTimestamp);

  		
  		if (isset($startTime))
  		{
  			$startTime = $theStartTime = DateTime::createFromFormat(Yii::app()->params['timeselect_format'][Yii::app()->language]['php'], $startTime);
			
  	
  			$startDateTime->setTime(intval($startTime->format('H')), intval($startTime->format('i')));
  		}
  		
  		$startDT = DateHelper::formatISO9075DateTime ( $startDateTime );
  		//echo "<$startDT>";

  		$this->getDbCriteria()->addCondition ( "t.StartTime >= '$startDT'" );
  	}
  
  	if (isset($endTimestamp))
  	{
  		$endDateTime = new DateTime();
  		$endDateTime->setTimestamp($endTimestamp);
  		//echo DateHelper::formatISO9075DateTime ( $endDateTime );;
  		
  		if (isset($endTime))
  		{
  			$endTime = $theStartTime = DateTime::createFromFormat(Yii::app()->params['timeselect_format'][Yii::app()->language]['php'], $endTime);
  			$endDateTime->setTime(intval($endTime->format('H')), intval($endTime->format('i')));
  		}
  	}
  
  	$endDT = DateHelper::formatISO9075DateTime ( $endDateTime );
  	//echo "<$endDT>";
  	$this->getDbCriteria()->addCondition ( "t.StartTime <= '$endDT'" );
  
  
  	return $this;
  }
  
  public function startDateAfter($dateTime)
  {
  	$this->getDbCriteria()
  		->mergeWith(array(
  			'condition' => 'StartTime >= :startDateTime',
  			'params' => array(
  				':startDateTime' => DateHelper::formatISO9075DateTime($dateTime)
  			)
  		)
  	);
  	return $this;
  }
  
  public function startDateBefore($dateTime)
  {
  	$this->getDbCriteria()
  		->mergeWith(array(
  			'condition' => 'StartTime <= :endDateTime',
  			'params' => array(
  				':endDateTime' => DateHelper::formatISO9075DateTime($dateTime)
  			)
  		)
  	);
  	return $this;
  }
  
  public function startTimeAfter($time)
  {
  	$this->getDbCriteria()
  		->mergeWith(array(
  			'condition' => 'TIME(StartTime) >= :startTimeSlot',
  			'params' => array(
  				':startTimeSlot' => DateHelper::formatISO9075Time($time)
  			)
  		)
  	);
  	return $this;
  }
  
  public function startTimeBefore($time)
  {
  	$this->getDbCriteria()
  		->mergeWith(array(
  			'condition' => 'TIME(StartTime) <= :endTimeSlot',
  			'params' => array(
  				':endTimeSlot' => DateHelper::formatISO9075Time($time)
  			)
  		)
  	);
  	return $this;
  }
  
  public function byNationalities($nationalities)
  {
  	if (!is_array($nationalities))
  		$nationalities = array($nationalities);
  
  	$tags = array();
  		

  	$cNats = new CDbCriteria;
  	
  	foreach ($nationalities as $nat)
  	{
  		$cNat = new CDbCriteria;
  		$cNat->addCondition("t.custom_nationality = '". strtoupper($nat)."'");
  		
  		$cNat2 = new CDbCriteria;
  		$cNat2->addCondition("t.custom_nationality = '' or t.custom_nationality is null");
  		
  		$cNat2->addInCondition ( 't.Nationality', PlateCountry::getPossibleTag( $nat));
  				
  		
  		$cNat->addCondition($cNat2->condition, 'OR');
  		$cNat->params += $cNat2->params;
  				
  		$cNats->addCondition($cNat->condition, 'OR');
  		$cNats->params += $cNat->params;
  	}
  	

  	$this->getDbCriteria()->addCondition($cNats->condition);
  	$this->getDbCriteria()->params += $cNats->params;
  		
  		

  		return $this;
  }
  

  public function defaultScope()
  {
    $alias = $this->getTableAlias ( false, false );
    
    return array (
        'order' => "$alias.StartTime DESC" 
    );
  }

  /**
   *
   * @param string $orderBy          
   * @return Event
   */
  public function setOrderBy($orderBy)
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'order' => $orderBy 
    ) );
    return $this;
  }

  public function relations()
  {
  	
  	$t = $this->getTableAlias(false);
  	
    return array (
        'gate' => array (
            self::BELONGS_TO,
            'Gate',
            array (
                'Gate' => 'Gate' 
            ) 
        ),
        'gateGroup' => array (
            self::HAS_ONE,
            'GateGroup',
            array (
                'id_group' => 'ID' 
            ),
            'through' => 'gate' 
        ),
        'service' => array (
            self::BELONGS_TO,
            'Service',
            'id_run' 
        ),
        
        'eventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event' 
        ),
        'eventBehaviorsToValidate' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'scopes' => array (
                'toValidate' 
            ) 
        ),
        'behaviors' => array (
            self::HAS_MANY,
            'Behavior',
            array (
                'id_behavior' => 'ID' 
            ),
            'through' => 'eventBehaviors' 
        ),
        'photos' => array (
            self::HAS_MANY,
            'MediaAttachment',
            array (
                'EventID' => 'ExtraInfoID' 
            ),
            'scopes' => array (
                'photo' 
            ) 
        ),
    	'photosAll' => array (
    		self::HAS_MANY,
    		'MediaAttachment',
    		array ('EventID' => 'ExtraInfoID'),
			'scopes' => array( 'resetScope' )
    	),

        'video_bw' => array (
            self::HAS_ONE,
            'MediaAttachment',
            array (
                'EventID' => 'ExtraInfoID' 
            ),
            'scopes' => array (
                'video_bw' 
            ) 
        ),
        'video_col' => array (
            self::HAS_ONE,
            'MediaAttachment',
            array (
                'EventID' => 'ExtraInfoID' 
            ),
            'scopes' => array (
                'video_col' 
            ) 
        ),
        'videos' => array (
            self::HAS_MANY,
            'MediaAttachment',
            array (
                'EventID' => 'ExtraInfoID' 
            ),
            'scopes' => array (
                'video' 
            ) 
        ),
        
        'colorSet' => array (
            self::BELONGS_TO,
            'VehicleColor',
            'id_vehicle_color' 
        ),
        
        'newEventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'condition' => 'validation_result = "" or validation_result IS NULL' 
        ),
        'approvedEventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'condition' => "validation_result = :result",
            'params' => array (
                ':result' => EventBehavior::STATUS_APPROVED 
            ) 
        ),
        'pendingEventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'condition' => 'validation_result = :result',
            'params' => array (
                ':result' => EventBehavior::STATUS_PENDING 
            ) 
        ),
        'voidEventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'condition' => 'validation_result = :result',
            'params' => array (
                ':result' => EventBehavior::STATUS_VOID 
            ) 
        ),
        'invalidEventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'condition' => 'validation_result = :result',
            'params' => array (
                ':result' => EventBehavior::STATUS_INVALID 
            ) 
        ),
        'toBeManagedEventBehaviors' => array (
            self::HAS_MANY,
            'EventBehavior',
            'id_event',
            'condition' => 'validation_result != :result',
            'params' => array (
                ':result' => EventBehavior::STATUS_NO_VALIDATION 
            ) 
        ),
        
        'alert' => array (
            self::BELONGS_TO,
            'Alert',
            array (
                'UUID' => 'event_uuid' 
            ) 
        ),
        'bookmark' => array (
            self::HAS_ONE,
            'Bookmark',
            'id_reference',
            'condition' => "bookmark.type='event' AND id_user=" . user ()->id 
        ),
    	'recognized_nation' => array (
    				self::HAS_ONE,
    				'PlateCountry',
    				array('label' => 'Nationality')
    	),
		'vehicle' => array (
    				self::HAS_ONE,
    				'Vehicle',
    				array('source' => 'UUID')
    	)
    		
    );
  }

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

  public function search(array $params = null)
  {
    $criteria = new CDbCriteria ();
    // $criteria->compare('Plate', $params['query'], true);
    
    if (Yii::app ()->user->checkAccess ( 'license_plate_visibility' ))
      $criteria->addCondition ( "MATCH(Plate) AGAINST('*" . $params ['query'] . "*' IN BOOLEAN MODE)" );
    $criteria->compare ( 'ext_code', $params ['query'], true, 'OR' );
    
    if (in_array ( 'ext_code_only', $params ))
      $criteria->addCondition ( "ext_code<>''" );
    
    $criteria->addBetweenCondition ( 'StartTime', $params ['start']->format ( "Y-m-d H:i:s" ), $params ['end']->format ( "Y-m-d H:i:s" ) );
    if(count($params ['gates']) > 0)
    	$criteria->addInCondition ( 'Gate', $params ['gates'] );
    $count = $this->count ( $criteria );
    
    $pagination = new CPagination ( $count );
    $pagination->pageSize = 10;
    $pagination->applyLimit ( $criteria );
    
    $dataProvider = new CActiveDataProvider ( 'Event' );
    $dataProvider->criteria = $criteria;
    $dataProvider->pagination = $pagination;
    
    return $dataProvider;
  }

  public function isNew()
  {
    return (isset ( $this->ValidatedBy ) && ($this->ValidatedBy == '') && ! $this->isExamined ());
  }

  public function isExamined()
  {
    return (isset ( $this->data_check ) && $this->data_check == 1);
  }

  public function isValidated()
  {
    return ($this->isApproved () || $this->isInvalid () || $this->isPending ());
  }

  public function hasCorrectedPlate()
  {
  	return (!empty($this->ExtPlate) && $this->Plate != $this->ExtPlate);
  }

  /**
   * say if Plate has []?
   *
   * @return boolean
   */
  public function hasWildcardPlate()
  {
    return containsStr ( $this->Plate, "[" ) || containsStr ( $this->Plate, "]" ) || containsStr ( $this->Plate, "?" );
  }

  /**
   * say if ExtPlate has []?
   *
   * @return boolean
   */
  public function hasWildcardExtPlate()
  {
    return containsStr ( $this->ExtPlate, "[" ) || containsStr ( $this->ExtPlate, "]" ) || containsStr ( $this->ExtPlate, "?" );
  }

  /**
   *
   * @return CArray with fields exists,levenshtein,btlfsa,similar_text
   */
  public function getPlateCorrectionError()
  {
    $error = plate_error_calc ( $this->Plate, $this->ExtPlate );
    return $error;
  }

  public function isApproved()
  {
    return ($this->validation_result == self::VALIDATION_RESULT_APPROVED);
  }

  public function isVoid()
  {
    return ($this->validation_result == self::VALIDATION_RESULT_VOID);
  }

  public function getIsRed()
  {
    foreach ( $this->behaviors as $beh )
      if ($beh->isRed)
        return true;
    return false;
  }

  public function isInvalid()
  {
    return ($this->validation_result == self::VALIDATION_RESULT_INVALID);
  }

  public function isPending()
  {
    return ($this->validation_result == self::VALIDATION_RESULT_PENDING);
  }

  public function isQueuedForExport()
  {
    return (isset ( $this->ext_code ) && $this->ext_code != '');
  }

  public function isExported()
  {
    return (isset ( $this->Protocol ) && $this->Protocol != '' && $this->Protocol != 'NO_MULTA' && $this->Protocol != '-');
  }

  public function updateStatus()
  {
    if (count ( $this->newEventBehaviors ) > 0)
      $result = '';
    
    else if (count ( $this->pendingEventBehaviors ) > 0)
      $result = self::VALIDATION_RESULT_PENDING;
    
    else if (count ( $this->approvedEventBehaviors ) > 0)
      $result = self::VALIDATION_RESULT_APPROVED;
    
    else if (count ( $this->invalidEventBehaviors ) == count ( $this->toBeManagedEventBehaviors ))
      $result = self::VALIDATION_RESULT_INVALID;
    
    $this->validation_result = $result;
    $this->Protocol = '';
    $this->ext_code = '';
    
    return $this->save ();
  }

  /**
   *
   * @param AuthWebUser $webUser          
   * @return boolean
   */
  public function assignUser(AuthWebUser $webUser)
  {
    $now = new DateTime ();
    
    $this->assignValidator ( $webUser, $now );
    $this->assignExaminer ( $webUser, $now );
    return $this->save ();
  }

  public function getKemler()
  {
    $Kem = $this->getAttribute ( 'Kemler' );
    if (strlen ( $Kem ) <= 0)
      return '';
    
    $pos = strrpos ( $Kem, ";" );
    if ($pos === false)
    {
      $pos = strrpos ( $Kem, "-" );
      if ($pos === false)
      {
        $offset = strlen ( $Kem ) - 4;
        $part1 = substr ( $Kem, 0, $offset );
        $part2 = substr ( $Kem, $offset );
        
        $part1 = $part1 . "-";
        $whole = $part1 . $part2;
        
        return $whole;
      }
    }
    
    return str_replace ( ';', '-', $Kem );
  }

  public function getCustom_nationality()
  {
    $custom_nationality = $this->getAttribute ( 'custom_nationality' );
    if (isset ( $custom_nationality ) && $custom_nationality != '')
      return $custom_nationality;
    else
    {
      $kriaPlate = PlateCountry::model ()->findByAttributes ( array (
          'label' => $this->Nationality 
      ) );
      if (isset ( $kriaPlate ))
        return $kriaPlate->iso_code;
    }
  }

  public function getNationalityCode()
  {
    return $this->custom_nationality;
  }

  public function getCustom_plate_type()
  {
    $custom_plate_type = $this->getAttribute ( 'custom_plate_type' );
    if (isset ( $custom_plate_type ) && $custom_plate_type != '')
      return $custom_plate_type;
    else
    {
      $plateType = CustomPlateType::model ()->findByAttributes ( array (
          'is_default' => 1 
      ) );
      if (isset ( $plateType ))
        return $plateType->type;
    }
  }

  public function getCustom_property_type()
  {
    $custom_property_type = $this->getAttribute ( 'custom_property_type' );
    if (isset ( $custom_property_type ) && $custom_property_type != '')
      return $custom_property_type;
    else
    {
      $propertyType = CustomPropertyType::model ()->findByAttributes ( array (
          'is_default' => 1 
      ) );
      if (isset ( $propertyType ))
        return $propertyType->type;
    }
  }

  public function getCustom_vehicle_type()
  {
    $custom_vehicle_type = $this->getAttribute ( 'custom_vehicle_type' );
    $kria_vehicle_type = $this->getAttribute ( 'Classe' );
    if (isset ( $custom_vehicle_type ) && $custom_vehicle_type != '')
      return $custom_vehicle_type;
    else
      return VehicleTypes::getFromDeviceClass ( $kria_vehicle_type );
    // return $kria_vehicle_type;
  }

  public function getVehicleClass()
  {
    return $this->custom_vehicle_type;
  }

  public function getEventDateTime()
  {
    return $this->StartTime;
  }

  public function setPlate($newPlate)
  {
  	$newPlate = strtoupper($newPlate);
  	
    if ($this->ExtPlate == '' && $newPlate != $this->getAttribute ( 'Plate' ))
      $this->ExtPlate = $this->getAttribute ( 'Plate' );
    $this->setAttribute ( 'Plate', $newPlate );
  }

  public function tagged()
  {
    return isset ( $this->ext_code ) && strlen ( $this->ext_code ) > 0;
  }

  public function tag($code)
  {
    $this->ext_code = $code;
    $this->ext_code_time = new DateTime ();
    
    return $this->save ();
  }

  public function last($numOfItems)
  {
	  	
   $this->getDbCriteria ()->limit = $numOfItems;
   $this->getDbCriteria ()->order = 'StartTime DESC';
    
    return $this;
  }

  public function first($numOfItems)
  {
 	
   $this->getDbCriteria ()->limit = $numOfItems;
   $this->getDbCriteria ()->order = 'StartTime ASC';
    
    
    return $this;
  }

  public function getViolationCodes()
  {
    return array_map ( function ($eb)
    {
      return $eb->violation_code;
    }, $this->eventBehaviors );
  }

  public function suspend()
  {
    foreach ( $this->eventBehaviors as $eventBehavior )
      $eventBehavior->suspend ();
    
    $this->validation_result = self::VALIDATION_RESULT_PENDING;
    return $this->save ();
  }

  /**
   *
   * @param AuthWebUser $user          
   * @return boolean
   */
  public function approve(AuthWebUser $user)
  {
    foreach ( $this->eventBehaviors as $eventBehavior )
      $eventBehavior->approve ();
    
    $this->assignUser ( $user );
    
    $this->ValidatedBy = $user->name;
    $this->validation_result = self::VALIDATION_RESULT_APPROVED;
    
    if (empty ( $this->custom_nationality ))
      $this->custom_nationality = "IT";
    
    if (! $this->save ())
    {
      return false;
    }
    
    return true;
  }

  public function howMany()
  {
    return Event::model ()->count ( $this->getDbCriteria () );
  }

  /**
   *
   * @return MediaAttachment
   */
  public function getPreviewPhoto()
  {
    if (! Yii::app ()->user->checkAccess ( 'media_view_photo' ))
      return null;
    $media = MediaAttachment::model ();
    if ($this->Direction == - 1)
      $media->setSignificantPhotoBlobIdBw ( 1001 );
    
    if ($this->getGateType () == Gate::GT_T_RED)
      $media->setSignificantPhotoColumn ( 'BlobIDSelected' );
    
      
      
    $media->byEventIds ( $this->ExtraInfoID );
    $media->photo ();
    $media->preview ();
    return $media->find ();
  }

  /**
   *
   * @return string
   */
  public function getPreviewPhotoUrl()
  {
    if (! Yii::app ()->user->checkAccess ( 'media_view_photo' ))
      return access_denied_png_url ();
    $photo = $this->getPreviewPhoto ();
    if (isset ( $photo ))
      return $photo->url;
    return null;
  }

  /**
   *
   * @return MediaAttachment
   */
  public function getPreviewColorPhoto()
  {
    if (! Yii::app ()->user->checkAccess ( 'media_view_photo' ))
      return null;
    $media = MediaAttachment::model ();
    if ($this->Direction == - 1)
      $media->setSignificantPhotoBlobIdCol ( 3001 );
    if ($this->getGateType () == Gate::GT_T_RED)
      $media->setSignificantPhotoColumn ( 'BlobIDSelected' );
    $media->byEventIds ( $this->ExtraInfoID );
    $media->previewColor ();
    return $media->find ();
  }

  /**
   *
   * @return string
   */
  public function getPreviewColorPhotoUrl()
  {
    if (! Yii::app ()->user->checkAccess ( 'media_view_photo' ))
      return access_denied_png_url ();
    $photo = $this->getPreviewColorPhoto ();
    if (isset ( $photo ))
      return $photo->url;
    return null;
  }
  
  public function getPreviewExtraCameraPhoto()
  {
  	if (! Yii::app ()->user->checkAccess ( 'media_view_photo' ))
  		return null;

  	$media = MediaAttachment::model ();

  	$media->byEventIds ( $this->ExtraInfoID );
  	$media->extraCameraPhotos();
  	return $media->findAll ();
  }

  /**
   *
   * @param AuthWebUser $webUser          
   * @param DateTime $time          
   */
  private function assignValidator(AuthWebUser $webUser, DateTime $time)
  {
    if ($webUser->checkAccess ( 'edit_event_behaviors' ))
    {
      $this->id_validate_user = $webUser->id;
      $this->ValidationTime = $time->format ( DateHelper::ISO9075_DATETIME );
    }
  }

  /**
   *
   * @param AuthWebUser $webUser          
   * @param DateTime $time          
   */
  private function assignExaminer(AuthWebUser $webUser, DateTime $time)
  {
    if ($this->id_data_check_user == null || $this->id_data_check_user == 0)
    {
      $this->id_data_check_user = $webUser->id;
      $this->data_check_time = $time->format ( DateHelper::ISO9075_DATETIME );
      $this->ValidatedBy = $webUser->id;
      $this->data_check = 1;
    }
  }

  public function getGateType()
  {
    return $this->gate->GateType;
  }

  public function getGateLabel()
  {
    return $this->gate->Descrizione;
  }

  public function getGateShortLabel()
  {
    return $this->gate->short_name;
  }

  public function getVehicleSpeed()
  {
  	
  	if ($this->measured_speed > 0)
  		return $this->measured_speed;
  	
    if ($this->Speed > 0)
      return $this->Speed;
     
    return - 1;
  }

  public function getSpeedLimitSignList()
  {
    if (is_null ( $this->speed_limit_signs ) or strlen ( $this->speed_limit_signs ) <= 0)
      return null;
    
    $signs = explode ( ';', $this->speed_limit_signs );
    
    sort ( $signs, SORT_NUMERIC );
    
    return $signs;
  }

  public function getYellowBarType()
  {
    return null;
  }

  /**
   *
   * @param boolean $searchForCsv
   *          default=false
   * @return CActiveDataProvider
   */
  public function searchAll($searchForCsv = false)
  {
    // Warning: Please modify the following code to remove attributes that
    // should not be searched.
    $criteria = new CDbCriteria ();
    
    if (! empty ( $this->Plate ))
      $criteria->addCondition ( "MATCH(t.Plate) AGAINST('*" . $this->Plate . "*' IN BOOLEAN MODE)" );
    
    if (! empty ( $this->Classe ))
    {
      $conditionVClass = "t.custom_vehicle_type = '" . $this->Classe . "' OR (t.custom_vehicle_type is null AND t.Classe = '" . $this->Classe . "')";
      $criteria->addCondition ( $conditionVClass );
    }
    
    $criteria->compare ( 't.Gate', $this->Gate );
    
    // kemler
    $kemlerStr = $this->kemlerSearchString;
    if (! empty ( $kemlerStr ))
      if ($kemlerStr == "*")
      {
        $criteria->addCondition ( "(t.Kemler is not null AND t.Kemler != '')" );
      }
      else
      {
        $kemlerStr = str_replace ( "-", "", $kemlerStr );
        $criteria->addCondition ( "MATCH(t.Kemler) AGAINST('*" . $kemlerStr . "*' IN BOOLEAN MODE)" );
      }
    
    if ($this->searchBookmarked)
    {
      $this->withBookmark ( $criteria );
    }
    
    $criteria->compare ( 't.LaneID', $this->LaneID );
    
    if (! empty ( $this->id_run ))
      $criteria->addCondition ( "t.id_run={$this->id_run}" );
    
    if (! empty ( $this->searchByResult ))
      $criteria->addCondition ( "t.validation_result='{$this->searchByResult}'" );
    
    if (! empty ( $this->ValidatedBy ))
      $criteria->addCondition ( "t.ValidatedBy={$this->ValidatedBy}" );
    
    if (! empty ( $this->Nationality ))
      $criteria->addInCondition ( 't.Nationality', PlateCountry::getPossibleTag ( $this->Nationality ) );
    
    if (! empty ( $this->event_date_start ))
    {
      $theStartTime = DateTime::createFromFormat ( Yii::app ()->params ['datetimeselect_format'] [Yii::app ()->language] ['php'], $this->event_date_start );
      $startDT = DateHelper::formatISO9075DateTime ( $theStartTime );
      
      $criteria->addCondition ( "t.StartTime >= '$startDT'" );
    }
    
    if (! empty ( $this->event_date_end ))
    {
      $theEndTime = DateTime::createFromFormat ( Yii::app ()->params ['datetimeselect_format'] [Yii::app ()->language] ['php'], $this->event_date_end );
      $endDT = DateHelper::formatISO9075DateTime ( $theEndTime );
      
      $criteria->addCondition ( "t.StartTime <= '$endDT'" ); // date is database date column field
    }
    
    if (! empty ( $this->search_speed_start ) && empty ( $this->search_speed_end ))
    {
      $criteria->addCondition ( "t.Speed >= '$this->search_speed_start'" ); // date is database date column field
    }
    elseif (! empty ( $this->search_speed_end ) && empty ( $this->search_speed_start ))
    {
      $criteria->addCondition ( "t.Speed <= '$this->search_speed_end'" );
    }
    elseif (! empty ( $this->search_speed_end ) && ! empty ( $this->search_speed_start ))
    {
      $criteria->addCondition ( "t.Speed  >= '$this->search_speed_start' and t.Speed <= '$this->search_speed_end'" );
    }
    
    if (! empty ( $this->searchColor ) && is_string ( $this->searchColor ) && startsWith ( $this->searchColor, '#' ))
    {
      if ($criteria->with == null)
        $criteria->with = array ();
      $criteria->with [] = 'colorSet';
      $rgb = ColorHelper::HTMLToRGBArray ( $this->searchColor );
      $sensitivity = paramdeep ( 'search', 'advanced', 'colorSensitivity' );
      $criteria->addCondition ( "
            kria_color_distance_perc(colorSet.c01,$rgb[r],$rgb[g],$rgb[b])>=$sensitivity
            OR
            kria_color_distance_perc(colorSet.c02,$rgb[r],$rgb[g],$rgb[b])>=$sensitivity
            OR
            kria_color_distance_perc(colorSet.c03,$rgb[r],$rgb[g],$rgb[b])>=$sensitivity
            " );
    }
    
    if ($searchForCsv)
    {
      access_denied_check ( 'export_events' );
      
      $criteria->join = "LEFT JOIN event_reporting e ON t.uuid=e.event_uuid";
      
      $criteria->select = array (
          Yii::app ()->user->checkAccess ( 'license_plate_visibility' ) ? 't.Plate as Plate' : "'#######' as Plate",
          't.StartTime as Date',
          't.Gate as Gate',
          't.Speed as Speed',
          't.LaneID+1 as LaneID',
          't.Classe as Class',
          't.Nationality as Nationality',
          't.Kemler as Kemler',
          'e.description as Description' 
      );
      
      return new CActiveDataProvider ( $this, array (
          'criteria' => $criteria 
      ) );
    }
    
    $dataProv = new CActiveDataProvider ( $this, array (
        'criteria' => $criteria,
        'pagination' => array (
            'pageSize' => paramdeep ( 'search', 'advanced', 'pagination' ) 
        ) 
    ) );
    
    // $dataProv->setTotalItemCount(1000000000); //non va bene!
    
    return $dataProv;
  }

  static public function getNationCodesList()
  {
    $vTrace = Event::model ()->resetScope ()
      ->findAll ( array (
        'select' => 'Nationality',
        'distinct' => true 
    ) );
    if (is_null ( $vTrace ))
      return null;
    
    $arr = array ();
    if (! is_array ( $vTrace ))
      $vTrace = array (
          $vTrace 
      );
    
    $labels = array ();
    
    foreach ( $vTrace as $vT )
      $labels [] = $vT->Nationality;
    
    return PlateCountry::getNationListFromLabels ( $labels );
  }

  /**
   *
   * @param mixed $services
   *          array of ids or id from table 'run'
   * @return CArray[]
   */
  public static function getServicesCounters($services)
  {
    if (is_array ( $services ))
      $services = implode ( ',', $services );
    $counters = query ( "SELECT id_run AS id_run ,COUNT(*) AS count_total ,sum(case when (validation_result is null or validation_result <> 'no_validation') then 1 else 0 end) as eventsCount ,sum(case when (ValidatedBy = '' AND data_check = 0 AND (validation_result is null or validation_result <> 'no_validation')) then 1 else 0 end) as eventsNewCount ,sum(case when (data_check = 1) then 1 else 0 end) as eventsExaminedCount ,sum(case when (validation_result = 'pending') then 1 else 0 end) as eventsPendingCount ,sum(case when (validation_result <> '' and validation_result <> 'no_validation') then 1 else 0 end) as eventsValidatedCount ,sum(case when (ext_code IS NULL and ext_code != '') then 1 else 0 end) as eventsQueuedForExportCount ,sum(case when (Protocol != '' and Protocol != 'NO_MULTA') then 1 else 0 end) as eventsExportedCount FROM storicotable WHERE id_run IN ($services) GROUP BY id_run" );
    $result = array ();
    foreach ( $counters as $cnt )
      $result [$cnt->id_run] = $cnt;
    return $result;
  }

  /**
   *
   * @return SimpleXMLElement
   */
  public function getXml()
  {
    $xml = $this->ExtraData;
    if (! empty ( $xml ) && is_string ( $xml ) && startsWith ( $xml, "<?xml" ))
    {
      return new SimpleXMLElement ( $xml );
    }
    return null;
  }

  public function getOcrReliability()
  {
    $xml = $this->getXml ();
    if ($xml != null)
      return ( double ) $xml->OCRLicensePlateReliability;
    else
      return - 1.0;
  }
  
  public function getWhitelistData()
  {
  	$whitelistData = array ();
  	
  	$xml = $this->getXml ();
  	if ($xml != null)
  	{
  		$whitelistData['ocr'] = ( double ) $xml->OCRLicensePlateReliability;
  		
  		$idReference = ( int ) $xml->images_Ids->WhiteListViolation->ReferenceLineID;
  	}
  	
  	$whitelistData['reference_bw'] = null;
  	$whitelistData['reference_col'] = null;
  	
  	foreach ( $this->photos as $photo )
  	{
  		$id = ( int ) $photo->BlobID;
  		
  		// black/white
  		if ($id == $idReference + 1000)
  		{
  			$whitelistData['reference_bw'] = $photo;
  		}
  		
  		// color
  		if ($id == $idReference + 3000)
  		{
  			$whitelistData['reference_col'] = $photo;
  		}
  		
  	}
  	
  	return $whitelistData;
  }

  public function getRedData()
  {
    $redData = array ();
    
    $xml = $this->getXml ();
    if ($xml != null)
    {
      /*
       * T-RedSpeedReport\OCRLicensePlateReliability double
       *
       * T-RedSpeedReport\TrafficLightInfo\YellowTime 15:51:42:0378 - 19/10/2014
       * T-RedSpeedReport\TrafficLightInfo\YellowTimeINT64 long
       * T-RedSpeedReport\TrafficLightInfo\RedTime
       * T-RedSpeedReport\TrafficLightInfo\RedTimeINT64
       * T-RedSpeedReport\TrafficLightInfo\stopped_before_intersection 0=comma3 1=comma2
       *
       * T-RedSpeedReport\images_Ids\RedViolation\BeforeStopLineID
       * T-RedSpeedReport\images_Ids\RedViolation\OverStopLineID
       * T-RedSpeedReport\images_Ids\RedViolation\AfterIntersectionID
       * T-RedSpeedReport\images_Ids\RedViolation\AfterAfterIntersectionID
       */
      
      $redData ['ocr'] = ( double ) $xml->OCRLicensePlateReliability;
      $redData ['yellow'] = DateHelper::parseEx ( ( string ) $xml->TrafficLightInfo->YellowTime, DateHelper::KRIA_DATETIME );
      $redData ['red'] = DateHelper::parseEx ( ( string ) $xml->TrafficLightInfo->RedTime, DateHelper::KRIA_DATETIME );
      $redData ['stopped'] = ( bool ) ($xml->TrafficLightInfo->stopped_before_intersection == '1');
      $redData ['yellow_int64'] = $xml->TrafficLightInfo->YellowTimeINT64;
      $redData ['red_int64'] = $xml->TrafficLightInfo->RedTimeINT64;
      
      $redData ['yellow_timegap'] = (floatval($redData ['red_int64']) - floatval($redData ['yellow_int64']))/10000000.0;
      
      $idBefore = ( int ) $xml->images_Ids->RedViolation->BeforeStopLineID;
      $idOver = ( int ) $xml->images_Ids->RedViolation->OverStopLineID;
      $idAfter = ( int ) $xml->images_Ids->RedViolation->AfterIntersectionID;
      $idAfterAfter = ( int ) $xml->images_Ids->RedViolation->AfterAfterIntersectionID;
    }
    
    $redData ['before_bw'] = null;
    $redData ['over_bw'] = null;
    $redData ['after_bw'] = null;
    $redData ['afterafter_bw'] = null;
    
    $redData ['before_col'] = null;
    $redData ['over_col'] = null;
    $redData ['after_col'] = null;
    $redData ['afterafter_col'] = null;
    
    foreach ( $this->photos as $photo )
    {
      $id = ( int ) $photo->BlobID;
      
      // black/white
      if ($id == $idBefore + 1000)
      {
        $redData ['before_bw'] = $photo;
      }
      if ($id == $idOver + 1000)
      {
        $redData ['over_bw'] = $photo;
      }
      if ($id == $idAfter + 1000)
      {
        $redData ['after_bw'] = $photo;
      }
      if ($id == $idAfterAfter + 1000)
      {
        $redData ['afterafter_bw'] = $photo;
      }
      
      // color
      if ($id == $idBefore + 3000)
      {
        $redData ['before_col'] = $photo;
      }
      if ($id == $idOver + 3000)
      {
        $redData ['over_col'] = $photo;
      }
      if ($id == $idAfter + 3000)
      {
        $redData ['after_col'] = $photo;
      }
      if ($id == $idAfterAfter + 3000)
      {
        $redData ['afterafter_col'] = $photo;
      }
    }
    
    return $redData;
  }

  /**
   *
   * @return MediaAttachment[]
   */
  public function getSpotSpeedData()
  {
    return $this->getPhotoBy ( "BlobID", array (
        'bw1' => '1000',
        'bw2' => '1001',
        'col1' => '3000',
        'col2' => '3001' 
    ) );
  }

  /**
   *
   * @return MediaAttachment[]
   */
  public function getMeanSpeedData()
  {
    return $this->getPhotoBy ( "Description", array (
        'start_bw' => 'MeanSpeedStartRefImage',
        'end_bw' => 'MeanSpeedEndRefImage' 
    ) );
  }

  /**
   *
   * @param string $field          
   * @param mixed $values          
   * @return MediaAttachment[]
   */
  public function getPhotoBy($field, $values)
  {
    if (! is_array ( $values ))
      $values = array (
          $values 
      );
    
    $photos = array ();
    
    foreach ( $this->photos as $photo )
    {
      foreach ( $values as $key => $value )
      {
        if ($photo->$field == $value)
        {
          $photos [$key] = $photo;
        }
      }
    }
    
    return $photos;
  }
  
  public function lastExported()
  {
  }
  
  public function getOcrQuality()
  {
  	$ocrQuality = null;
  	
  	if ($this->ocr_quality >= 0) {
  		$ocrQuality = $this->ocr_quality;
  	}
  	
  	return $ocrQuality;
  }
  
  public function getOcrQualityClass()
  {
  	$qualityLabel = "";
  	
  	$qualityRate = $this->ocrQuality;
  	if (!$qualityRate) {
  		return null;
  	}
  	
  	if ($qualityRate <= paramdeep('ocr', 'quality_threshold_bad')) {
  		$qualityLabel = self::OCR_QUALITY_LABEL_BAD;
  	}
  	elseif ($qualityRate > paramdeep('ocr', 'quality_threshold_bad')
  			&& $qualityRate < paramdeep('ocr', 'quality_threshold_good')) {
  		$qualityLabel = self::OCR_QUALITY_LABEL_MID;
  	}
  	else {
  		$qualityLabel = self::OCR_QUALITY_LABEL_GOOD;
  	}
  	
  	return $qualityLabel;
  }
  
  
  public function resetValidation()
  {
  	if($this->isQueuedForExport())
		return false;
  	
	if($this->isExported())
		return false;
  	
  	$this->ValidatedBy = '';
  	$this->validation_result = '';
  	$this->id_validate_user = 0;
  	return $this->save();
  }
  
  
}