<?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', 'License 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', 'License 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;
    }

    public function byOcrQuality($minOcrQuality, $maxOcrQuality)
    {
        $this->getDbCriteria()
            ->mergeWith(array(
                'condition' => 'ocr_quality >= :min_ocr_quality and ocr_quality <= :max_ocr_quality',
                'params' => array(
                    ':min_ocr_quality' => $minOcrQuality,
                    ':max_ocr_quality' => $maxOcrQuality,
                ),
            ));

        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 recentlyForCache($seconds, $datetimeField = 'StartTime')
    {
        if (isEmpty($datetimeField) || !$this->hasAttribute($datetimeField)) {
            $datetimeField = 'StartTime';
        }

        $interval = new DateInterval("PT{$seconds}S");
        $past = (new DateTime())->setTime(0, 0);
        $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;
    }

    public 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, $datetime)
    {
        $this->ext_code = $code;
        $this->ext_code_time = $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;
        }

        $this->getImagesForGif();
        $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();
    }

    public function getImagesForGif()
    {
        $jsArrayString = "[";
        $firstPic = $this->getCorrectMediaById(1000);
        if (isset($firstPic)) {
            $jsArrayString .= "'" . $firstPic->url . "',";
        }
        $secondPic = $this->getCorrectMediaById(1001);
        if (isset($secondPic)) {
            $jsArrayString .= "'" . $secondPic->url . "']";
        }
        return $jsArrayString;
    }

    public function getCorrectMediaById($selectedId)
    {
        $tmpMedia = MediaAttachment::model();
        $tmpMedia->setSignificantPhotoBlobIdBw($selectedId);
        $tmpMedia->byEventIds($this->ExtraInfoID);
        $tmpMedia->preview();
        return $tmpMedia->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();
        //var_dump($criteria);
        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;
    }

    public static 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;
            /* Mod. Trento Obscure System - 12.02.2019
             *  Added SelectedByUserID Tag to Xml
             */
            //$idReference = (int) $xml->images_Ids->WhiteListViolation->ReferenceLineID;
            if (Yii::app()->params['selectedbyuserid']) {
                if (!isset($xml->images_Ids->WhiteListViolation->SelectedByUserID)) {
                    $idReference = (int) $xml->images_Ids->WhiteListViolation->ReferenceLineID;
                } else {
                    $idReference = (int) $xml->images_Ids->WhiteListViolation->SelectedByUserID;
                }
            } else {
                $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();
    }

}
