<?php

/**
 * This is the model class for table "gatetable".
 *
 * The followings are the available columns in table 'gatetable':
 * @property integer $ID                Chiave primaria record
 * @property string  $Descrizione           Descrizione del varco / località
 * @property string  $Matricola             da definire
 * @property integer $ValidationMaxDelay        Numero massimo di giorni a disposizione dell'operatore di polizia per gestire un evento.
 *                            0 = igrora
 *                            server per dare avverimento se passa troppo tempo
 * @property string  $Type                Comportamento del Varco. vedi i commenti ai const GM_ nel modello
 * @property integer $Gate                Numero Varco. Coincide con il seriale del dispositivo tranne che per i T-ID (anche se dovrebbe)
 * @property boolean $Enable              Gate abilitato o no; default 1;
 * @property string  $IP                IP del dispositivo remoto
 * @property string  $Code                Codice esportato. serve per collegamento a terze parti
 * @property integer $LinkedGate            Per ragioni storiche contiene il SN della unità di Elaborazione
 * @property string  $epoch               data inserimento record
 * @property integer $AreaSourceID            ID area di origine nell'areatable. default -1
 * @property integer $AreaDestinationID         ID area di destinazione nell'areatable. default -1
 * @property string  $Status              Stato del varco. viene impostato da eventserver ai valori definiti
 *                            dai const GS_ del model in funzione del tempo trascorso dall'ultimo
 *                            aggiornamento in LastLifeSignal sino al tempo attuale e
 *                            in base al timeout LifeSignalTimeOut configurato
 * @property string  $LastLifeSignal          istante di riceziono dell'ultimo segnale di vita
 * @property string  $Homologation            stringa che contiene la dicitura di omologazione del dispositivo
 * @property integer $LastEventID           ID dell'ultimo evento
 * @property integer $LifeSignalTimeOut         Timeout segnale di vita in secondi. se -1 non viene verificato lo stao del varco
 * @property string  $LastEventTime           Istante temporale di rilevazione  dell'ultimo evento ricevuto
 * @property string  $GateType              Tipo di Dispositivo
 *                            "TRED"  T-RED
 *                            "TID"   T-ID
 *                            "TRS"   T-EXSPEED
 *                            "NONE"  non definito
 * @property string  $id_group
 * @property string  $short_name
 * @property string  $latitude
 * @property string  $longitude
 * @property string  $function
 * @property string  $mapx
 * @property string  $mapy
 * @property GateBehavior[] gateBehavior
 * @property GateGroup gateGroup
 * @property int orderIndex
 * @property boolean isWhiteList 
 */
class Gate extends ActiveRecord
{

  const GT_T_ID = 'TID';

  const GT_T_RED = 'TRED';

  const GT_T_EXSPEED = 'TRS';

  const GT_NONE = 'NONE';

  const GM_IN = 'IN';
  // varco di ingresso
  const GM_OUT = 'OUT';
  // varco di uscita
  const GM_CHECK = 'CHECK';
  // non usato o usato in passato
  const GM_FOLLOW = 'FOLLOW';
  // varco di inseguimentp / verifica passaggio
  const GM_PASS = 'PASS';
  // gate che rileva un transito
  const GM_INOUT = 'IN/OUT';
  // varco con possibilità di ingresso e uscita
  const GM_TRAJECTORY = 'TRAJECTORY';
  // non usato o usato in passato
  const GM_FILTER = 'FILTER';
  // i transiti che vengono rilevati da questo varco vengono eliminati dal database
  const GM_BL = 'BLACKLIST';
  // non usato o usato in passato
  const GM_IE = 'INTERESTINGEVENTS';
  // non usato o usato in passato
  const GS_UNDEF = 'UNDEF';
  // non definito
  const GS_ALIVE = 'ALIVE';
  // varco attivo
  const GS_WARNING = 'WARNING';
  // varco in warning
  const GS_DEAD = 'DEAD';
  // l'attività del varco non è più rilevata da tempo
  
  /**
   *
   * @param system $className          
   * @return Gate
   */
  public static function model($className = __CLASS__)
  {
    return parent::model ( $className );
  }

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

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

  public function primaryKey()
  {
    return 'Gate';
  }

  public function rules()
  {
    return array (
        array (
            'Descrizione, Gate, GateType, Type, Enable, id_group',
            'required' 
        ),
        array (
            'Gate',
            'unique' 
        ),
        array (
            'Matricola',
            'default',
            'value' => '',
            'setOnEmpty' => '' 
        ),
        array (
            'ValidationMaxDelay',
            'default',
            'value' => 0,
            'setOnEmpty' => 0 
        ),
        
        array (
            'Type',
            'default',
            'value' => self::GM_PASS,
            'setOnEmpty' => self::GM_PASS 
        ),
        array (
            'Type',
            'in',
            'range' => array (
                self::GM_IN,
                self::GM_OUT,
                self::GM_CHECK,
                self::GM_FOLLOW,
                self::GM_PASS,
                self::GM_INOUT,
                self::GM_TRAJECTORY,
                self::GM_FILTER,
                self::GM_BL,
                self::GM_IE 
            ) 
        ),
        
        array (
            'Enable',
            'boolean' 
        ),
        array (
            'Enable',
            'default',
            'value' => 1,
            'setOnEmpty' => 1 
        ),
        
        array (
            'IP',
            'length',
            'max' => 16 
        ),
        
        array (
            'AreaSourceID, AreaDestinationID',
            'default',
            'value' => '-1',
            'setOnEmpty' => '-1' 
        ),
        
        array (
            'GateType',
            'in',
            'range' => array (
                self::GT_T_ID,
                self::GT_T_RED,
                self::GT_T_EXSPEED,
                self::GT_NONE 
            ) 
        ),
        
        array (
            'Status',
            'default',
            'value' => self::GS_UNDEF,
            'setOnEmpty' => self::GS_UNDEF 
        ),
        array (
            'Status',
            'in',
            'range' => array (
                self::GS_UNDEF,
                self::GS_ALIVE,
                self::GS_WARNING,
                self::GS_DEAD 
            ) 
        ),
        
        array (
            'LifeSignalTimeOut',
            'default',
            'value' => - 1,
            'setOnEmpty' => - 1 
        ),
        
        array (
            'LastEventID',
            'default',
            'value' => - 1,
            'setOnEmpty' => - 1 
        ),
        
        array (
            'ValidationMaxDelay, Gate, LinkedGate, AreaSourceID, AreaDestinationID, LastEventID, LifeSignalTimeOut, id_group',
            'numerical' 
        ),
        
        array (
            'Descrizione, Matricola, Code, Homologation',
            'length',
            'max' => 250 
        ),
        
        array (
            'Matricola, ValidationMaxDelay, IP, Code, LinkedGate',
            'safe' 
        ),
        
        array (
            'epoch, device_model',
            'safe' 
        ),
        
        array (
            'ID, Descrizione, Matricola, ValidationMaxDelay, Type, Gate, Enable, IP, Code, LinkedGate, epoch, AreaSourceID, AreaDestinationID, Status, LastLifeSignal, Homologation, LastEventID, LifeSignalTimeOut, LastEventTime, GateType, id_group',
            'safe',
            'on' => 'search' 
        ),
        
        array (
            'function',
            'safe' 
        ),
        array (
            'mapx',
            'safe' 
        ),
        array (
            'mapy',
            'safe' 
        ) 
    );
  }

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

  public function relations()
  {
    return array (
        'gateGroup' => array (
            self::BELONGS_TO,
            'GateGroup',
            'id_group' 
        ),
        'gateBehavior' => array (
            self::HAS_MANY,
            'GateBehavior',
            array (
                'id_gate' => 'Gate' 
            ) 
        ) 
    );
  }

  public function myAttributeLabels()
  {
    return array (
        'ID' => t ( 'ID' ),
        'Descrizione' => t ( 'Descrizione' ),
        'Matricola' => t ( 'Matricola' ),
        'ValidationMaxDelay' => t ( 'Validation Max Delay' ),
        'Type' => t ( 'Type' ),
        'Gate' => t ( 'Gate' ),
        'Enable' => t ( 'Enabled' ),
        'IP' => t ( 'Ip' ),
        'Code' => t ( 'Code' ),
        'LinkedGate' => t ( 'Linked Gate' ),
        'epoch' => t ( 'Epoch' ),
        'AreaSourceID' => t ( 'Area Source' ),
        'AreaDestinationID' => t ( 'Area Destination' ),
        'Status' => t ( 'Status' ),
        'LastLifeSignal' => t ( 'Last Life Signal' ),
        'Homologation' => t ( 'Homologation' ),
        'LastEventID' => t ( 'Last Event' ),
        'LifeSignalTimeOut' => t ( 'Life Signal Time Out' ),
        'LastEventTime' => t ( 'Last Event Time' ),
        'GateType' => t ( 'Gate Type' ),
        'id_group' => t ( 'Id Group' ),
        'speed_limit' => t ( 'Speed Limit' ),
        'last_exported_event_id' => t ( 'Last Exported Event' ),
        'last_exported_event_time' => t ( 'Last Exported Event Time' ),
        'last_exported_event_validation_time' => t ( 'Last Exported Event Validation Time' ),
        'latitude' => t ( 'Latitude' ),
        'longitude' => t ( 'Longitude' ),
        'altitude' => t ( 'Altitude' ),
        'short_name' => t ( 'Short Name' ),
        'live_url' => t ( 'Live Url' ),
        'work_mode' => t ( 'Work Mode' ),
        'device_model' => t ( 'Device Model' ),
        'immunity_from_s' => t ( 'Immunity From S' ),
        'immunity_to_s' => t ( 'Immunity To S' ),
        'last_section_event' => t ( 'Last Section Event' ),
        'function' => t ( 'Function' ) 
    );
  }

  /**
   *
   * @param string|DateTime|DateTimeEx $now          
   * @return boolean
   */
  public function isZtlLimited($now = null)
  {
    $validZtls = array ();
    $limited = $this->isZtlLimitedEx ( $now, $validZtls );
    return $limited;
  }

  /**
   *
   * @param string|DateTime|DateTimeEx $now          
   * @param Ztl[] $validZtls          
   * @return boolean
   */
  public function isZtlLimitedEx($now = null, &$validZtlsOut)
  {
    $now = DateHelper::ensureObject ( $now );
    $nowEx = new DateTimeEx ( $now );
    
    /** @var ZtlValidityResult[] $validZtls */
    if ($validZtls == null || ! is_array ( $validZtls ))
      $validZtls = array ();
    
    $ztls = Ztl::model ()->findAll ( 'GateID=:gt OR GateID=-1', array (
        ':gt' => $this->ID 
    ) );
    foreach ( $ztls as $ztl )
    {
      /** @var Ztl $ztl */
      $v = $ztl->getValidity ( $now );
      if ($v->isValid)
        $validZtls [] = $v;
    }
    
    $limited = false;
    
    if (count ( $validZtls ) > 0)
    {
      $validZtls = sort_sortable ( $validZtls );
      /** @var ZtlValidityResult $best */
      $best = array_last ( $validZtls );
      $limited = $best->ztl->isLimited ();
    }
    
    $validZtlsOut = $validZtls;
    
    return $limited;
  }

  /**
   *
   * @return array Gate=>Descrizione
   */
  static public function getGateList()
  {
    $res = Gate::model ()->findAll ();
    if (is_null ( $res ))
      return null;
    
    $arr = array ();
    if (! is_array ( $res ))
      $res = array (
          $res 
      );
    
    foreach ( $res as $gt )
      $arr [$gt->Gate] = $gt->Descrizione;
    
    return $arr;
  }

  /**
   *
   * @return array ID=>Descrizione
   */
  static public function getGateListPk()
  {
    $res = Gate::model ()->findAll ();
    if (is_null ( $res ))
      return null;
    
    $arr = array ();
    if (! is_array ( $res ))
      $res = array (
          $res 
      );
    
    foreach ( $res as $gt )
      $arr [$gt->ID] = $gt->Descrizione;
    
    return $arr;
  }

  public function isAlive()
  {
    return $this->Status == self::GS_ALIVE;
  }

  public static function getGateTypeList()
  {
    $list [self::GT_T_ID] = t ( self::GT_T_ID );
    $list [self::GT_T_RED] = t ( self::GT_T_RED );
    $list [self::GT_T_EXSPEED] = t ( self::GT_T_EXSPEED );
    return $list;
  }

  public static function getTypeList()
  {
    $list [self::GM_IN] = t ( self::GM_IN );
    $list [self::GM_OUT] = t ( self::GM_OUT );
    $list [self::GM_CHECK] = t ( self::GM_CHECK );
    $list [self::GM_FOLLOW] = t ( self::GM_FOLLOW );
    $list [self::GM_PASS] = t ( self::GM_PASS );
    $list [self::GM_INOUT] = t ( self::GM_INOUT );
    $list [self::GM_TRAJECTORY] = t ( self::GM_TRAJECTORY );
    $list [self::GM_FILTER] = t ( self::GM_FILTER );
    $list [self::GM_IE] = t ( self::GM_IE );
    
    return $list;
  }

  public function orderByGroupShortName()
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'order' => 'id_group ASC, short_name ASC' 
    ) );
    
    return $this;
  }

  public function orderByGroupDescrizione()
  {
    $this->getDbCriteria ()
      ->mergeWith ( array (
        'join' => 'left join gate_group gg on gg.ID=t.id_group',
        'order' => 'gg.name ASC, t.Descrizione ASC' 
    ) );
    
    return $this;
  }

  /**
   *
   * @return Gate[]
   */
  public static function getAllGates()
  {
    return Gate::model ()->findAll ();
  }

  /**
   *
   * @return Gate
   */
  public static function getByCode($gate)
  {
    return Gate::model ()->find ( 'Gate=:gt', array (
        ':gt' => $gate 
    ) );
  }

  public function getGateName()
  {
    if (! empty ( $this->Descrizione ))
      return $this->Descrizione;
    return $this->Code;
  }

  /**
   *
   * @return Ztl[]
   */
  public function getZtls()
  {
    return Ztl::model ()->findAll ( 'GateID=:gt OR GateID=-1', array (
        ':gt' => $this->ID 
    ) );
  }

  /**
   *
   * @return string HTML tags
   */
  public function getZtlIconTags()
  {
    $tags = "";
    foreach ( $this->getZtls () as $ztl )
      $tags = $tags . $ztl->getIconTag ();
    return $tags;
  }

  /**
   *
   * @return string HTML tags
   */
  public function getZtlIconTagsForDay($day = null)
  {
    $day = DateHelper::ensureObjectEx ( $day );
    $tags = "";
    foreach ( $this->getZtls () as $ztl )
      $tags = $tags . $ztl->getIconTagForDay ( $day );
    return $tags;
  }

  /**
   *
   * @return boolean
   */
  public function hasMapData()
  {
    return ! empty ( $this->mapx ) && ! empty ( $this->mapy );
  }

  public function getIsWhiteList()
  {
    foreach ( $this->gateBehavior as $gb )
      if ($gb->is_whitelist)
        return true;
    return false;
  }

  public function getLivePageUrl()
  {
    return url ( 'live/index', array (
        'id' => $this->ID 
    ) );
  }

  public function getLivePageAUrl()
  {
    return absoluteUrl ( 'live/index', array (
        'id' => $this->ID 
    ) );
  }

  public function getGoogleMapsLink()
  {
    if (! $this->hasCoordinates ())
      return null;
    return "https://www.google.com/maps?q=" . urlencode ( "{$this->latitude},{$this->longitude}" );
  }

  public function hasCoordinates()
  {
    return ! isEmptyOrWhitespace ( $this->latitude ) && ! isEmptyOrWhitespace ( $this->longitude );
  }

  public function hasLive()
  {
    $lu = $this->live_url;
    return ! empty ( $lu );
  }
}
