<?php 

//var_dump( __FILE__ );

class yLogicEngine {
  
  // declaracion
  public $oYApp = null;

  function __construct( $aParameters = null ) {
    //var_dump( "yLogicEngine.__construct" );
    $this->sTitu = "Sistema - Motor de Lógica";
    $this->sFiltLabl = "Sistema - Motor de Lógica";
    $this->init();
  }

  public function init( $aParameters = null ) {
    //var_dump( "yLogicEngine.init" );
    global $oYApp;
    $this->oYApp = $oYApp;
  }

  public function getViewSnapshot ( $aParameters = null ) {
    //var_dump( "yLogicEngine.getViewSnapshot - INI" );
    
    $oYApp = $this->oYApp;
    $aLandInst = $aParameters;

    /*
    //var_dump( $oYApp ); 
    //var_dump( "yLogicEngine.getViewSnapshot" );
    var_dump( $oYApp->sModu );
    var_dump( $oYApp->aModu[ $oYApp->sModu ]['_sisevnt'][0]['_sisevntiden'] );
    var_dump( $oYApp->aModu[ $oYApp->sModu ]['_sisevnt'][0]['_sisevntnomb'] );
    var_dump( $aLandInst['_deflandsnap'] );
    //*/

    $sJtpt = isset( $aLandInst['_sislandjtpt'] ) ? $aLandInst['_sislandjtpt'] : $aLandInst['_deflandjtpt'];
    
    $aSnap = array(
      "aJtpt" => json_decode( $sJtpt, true ),
      "aInst" => array(),
      "sValo" => "",
    );
    //var_dump( $aLandInst );
    //var_dump( $aSnap['aJtpt'] );

    // popular los templates con los valores de la vista actual y de la aplicacion
    foreach ( $aSnap['aJtpt'] as $sEntiNomb => $aEntiProp ) 
    {
      //var_dump( $sEntiNomb );
      //var_dump( $aEntiProp );
      foreach ( $aEntiProp as $sPropNomb => $sPropValo ) 
      {
        // mapeo
        if ( $sEntiNomb == "yApp" )
        {
          $sPropValo = $oYApp->$sPropNomb;
          if ( $sPropNomb == "bLgin" && is_null( $sPropValo ) )                                     // 2016-02-23 - bug - aparecio al actualizar proyecto cubo
            $sPropValo = false;
        }
        else if ( isset( $oYApp->a_view['a_data'][ $sEntiNomb ][0][ $sPropNomb ] ) )
        {
          $sPropValo = $oYApp->a_view['a_data'][ $sEntiNomb ][0][ $sPropNomb ];
        }
        else if ( isset( $oYApp->a_data[ $sEntiNomb ][0][ $sPropNomb ] ) )
        {
          $sPropValo = $oYApp->a_data[ $sEntiNomb ][0][ $sPropNomb ];
        }
        
        $sAuxiNomb = $sPropNomb; 
        
        $aEntiProp[ $sAuxiNomb ] = $sPropValo;
      }

      $aSnap['aInst'][ $sEntiNomb ] = $aEntiProp;
    }

    // 2016-02-24 #1 - el orden y el nombre de las claves afectaban el valor del hash
    //*
    if ( isset( $aSnap['aInst']['_sisview'] ) )
    {
      //if ( is_null( $aSnap['aInst']['_sisview']['_defviewiden'] ) )
      if ( isset( $aSnap['aInst']['_sisview']['_defviewiden'] ) )
      {
        $aAuxi = array();
        $aSnap['aInst']['_sisview']['_defviewiden'] = $aSnap['aInst']['_sisview']['_sisviewiden'];
        unset( $aSnap['aInst']['_sisview']['_sisviewiden'] );
        $aAuxi['yApp'] = $aSnap['aInst']['yApp'];
        $aAuxi['_defview'] = $aSnap['aInst']['_sisview'];
        unset( $aSnap['aInst']['yApp'] );
        unset( $aSnap['aInst']['_sisview'] );
        $aSnap['aInst'] = array_merge( $aAuxi, $aSnap['aInst'] );                                   // _sisview tiene que estar primero
      }
    }
    //*/
    
    $aSnap['sValo'] = json_encode( $aSnap['aInst'] );
    $aSnap['sValo'] = sha1( $aSnap['sValo'] );
  
    /*
    var_dump( $aSnap['sValo'] );
    var_dump( $aSnap['aInst'] );
    //*/    
    
    //var_dump( "yLogicEngine.getViewSnapshot - END" );
    return $aSnap;
  }
  
  public function getLandscape ( $aParameters = null ) {
    //var_dump( "yLogicEngine.getLandscape - INI" );
    //var_dump( $this->oYApp->a_view['a_data'] );

    $aResu = array();
    $oYApp = $this->oYApp;
    $oLand = new _sisland (); 

    $aView = $this->oYApp->a_view['a_data']['_sisview'];
    $iView = $aView[0]['_sisviewiden'];

    $aView_def = $this->oYApp->a_view['a_data']['_defview'];
    $iView_def = $aView_def[0]['_defviewiden'];

    // obtener las instancias de landscape vinculados con una vista
    $oLand->aBase['aFilt'][0] = "_sisland._sisland_sisview = '".$iView."' "; 
    $oLand->enable_relations();
    $aLand = $oLand->find();
    
    $oLand = new _defland (); 
    $oLand->aBase['aFilt'][0] = "_defland._defland_defview = '".$iView_def."' "; 
    $oLand->enable_relations();
    $aLand_def = $oLand->find();
    
    $aLand = array_merge( $aLand, $aLand_def );

    //var_dump( $this->oYApp->a_view['a_data'] );
    //var_dump( $iView_def );
    //var_dump( $aLand_def );
    //var_dump( $aLand );
    
    // comparar cada landscape con el snapshot de la vista actual de acuerdo con el template del 
    // landscape
    foreach ( $aLand as $iInst => $aInst ) 
    {
      $aSnap = $this->getViewSnapshot( $aInst );
      
      /*
      echo "<pre>";
      var_dump( "aSnap['sValo']: ".$aSnap['sValo'] );
      var_dump( "aInst['_sislandvalo']: ".$aInst['_sislandvalo'] );
      var_dump( "aInst['_sislandvalo'] generado: ". sha1( $aInst['_sislandvalo'] ) );
      var_dump( "aInst['_deflandvalo']: ".$aInst['_deflandvalo'] );
      var_dump( "aInst['_deflandvalo'] generado: ". sha1( $aInst['_deflandsnap'] ) );
      var_dump( $aInst );
      echo "</pre> <br />";
      //*/

      $_sislandvalo_actual = sha1( $aInst['_sislandsnap'] );
      $_deflandvalo_actual = sha1( $aInst['_deflandsnap'] );
      
      //if ( $aSnap['sValo'] == $aInst['_sislandvalo'] || $aSnap['sValo'] == $aInst['_deflandvalo'] )
      if ( $aSnap['sValo'] == $_sislandvalo_actual || $aSnap['sValo'] == $_deflandvalo_actual )
        $aResu[] = $aInst;
    }

    //var_dump( "yLogicEngine.getLandscape - END" );
    return $aResu;
  }
  // getLandscape - END

  function array_get_by_key_recursive ( $aParameters = null ) {
    $sClav = $aParameters['key'];                                                                   // clave que se busca
    $aData = $aParameters['array'];                                                                 // array donde se realiza la busqueda
    $aResu = null;                                                                                  // resultado que devuelve la funcion

    // se recorre el array donde se realiza la busqueda
    foreach ( $aData as $xClav => $xValo ) 
    {
      if ( $xClav === $sClav )                                                                      // si hay coinciden 
        $aResu = $xValo;                                                                            // se guarda el contenido de la clave
      else if ( gettype ( $xValo ) == "array" )                                                     // si no hay coincidencia entre las claves
        $aResu = $this->array_get_by_key_recursive( array(
          "key" => $sClav,
          "array" => $xValo,
        ) );                                                                                        // se produce la recursividad
      if ( ! is_null( $aResu ) )                                                                    // si hay contenido porque hubo coincidencia
        break;                                                                                      // se interrumpe el bucle
    }
    return $aResu;
  }

  public function executeLogic ( $aParameters = null ) {
    //var_dump("yLogicEngine.executeLogic");
    
    $bLand = false;                                                                                 // FLAG que determina la existencia de un escenario
    $fLand = null;                                                                                  // variable que almacenara la funcion del escenario que proviene de un archivo
    
    $sView = $this->oYApp->a_view['s_name'];
    $sModu = $this->oYApp->a_view['s_folder'];
    $aModu = $this->oYApp->a_data;

    if ( ! empty( $aParameters['landscape'] ) )
      $bLand = true;

    // Persistir los valores existentes dentro de las instancias de las entidades almacenadas en  
    // $aParameters['entities'], dispara la logica implementada en cada clase. Este es el ultimo
    // paso.
    foreach (  $aParameters['entities'] as $sEntiNomb => $aEntiInst )
    {
      if ( $sEntiNomb == "undefined" )                                                              // las instancias no identificadas se evitan
        continue;

      // recorrer cada instancia de las entidades identificadas
      foreach ( $aEntiInst as $iInstPosi => $aInstData ) 
      {
        $aInstCache = $this->array_get_by_key_recursive( array(
          "key" => $sEntiNomb,                                                                      // nombre de la entidad sobre la que se esta iterando
          "array" => $aModu,                                                                        // valores en cache del modulo actual
        ) );                                                                                        // controlar si existe una o mas instancia en cache
        
        if ( ! is_null( $aInstCache ) && ! is_null( $aInstCache[ $iInstPosi ] ) )                   // controlar si hubo instancias en cache
          $aInstData = array_merge( $aInstCache[ $iInstPosi ], $aInstData );                        // la instancia de cache debería corresponderse con la instancia que viene desde afuera
        
        $oEnti = new $sEntiNomb ();
        $a_function_result = $oEnti->exis( $aInstData, false );                                                                  // crear o actualizar
        if ( $a_function_result['bExis'] )
          $oEnti->set( $aInstData );                                                                  // crear o actualizar
      }
    }

    // POST-PERSISTENCIA ejecutar las acciones relacionadas con el escenario. Esta logica puede 
    // encontrarse en la base de datos porque fue definida a traves del CMS o puede estar 
    // implementada en codigo en algun archivo puntual.

    // control de existencia de logica en la plataforma
    //if ( $bLand ) {}
    
    // control de existencia de logica en archivo externo
    $_SESSION['a_app'][ FMWK_CLIE_NAME ] = serialize( $this->oYApp );
    //include_once( dirname(__FILE__)."/../project/landscapes.php" );
    include_once( FMWK_CLIE_DIRE."project/landscapes.php" );

    $iLand = isset( $aParameters['landscape'][0]['_sislandiden'] ) ? 
      $aParameters['landscape'][0]['_sislandiden'] : $aParameters['landscape'][0]['_deflandiden'] ;
    $sLand = isset( $aParameters['landscape'][0]['_sislandnomb'] ) ?
      $aParameters['landscape'][0]['_sislandnomb'] : $aParameters['landscape'][0]['_deflandnomb'] ;
    
    //var_dump( $aParameters['landscape'] );
    //var_dump( $iLand );
    //var_dump( $sLand );
    //var_dump( $aLandscape[ $sModu ][ $sView ] );

    if ( isset( $aLandscape[ $sModu ] ) )
    {
      if ( isset( $aLandscape[ $sModu ][ $sView] ) )
      {
        if ( isset( $aLandscape[ $sModu ][ $sView][ $sLand ] ) )                                    // 20160213 va directo a la funcion del landscape
        {
          $fLand = $aLandscape[ $sModu ][ $sView ][ $sLand ];
          //$fLand = $aLandscape[ $sModu ][ $sView][ $iLand ];
          //var_dump( $fLand );
        }
      }
    }

    if ( gettype( $fLand ) === "object" && ! is_null( $fLand ) )                                    // control si es una funcion
      $aParameters = $fLand( $aParameters );                                                        // se ejecuta la funcion y la devolucion debe ser un array con los string de mapeo

    //var_dump( $aParameters );

    // devolver a la vista
    $this->oYApp = unserialize( $_SESSION['a_app'][ FMWK_CLIE_NAME ] );
    $aParameters['entities'] = $this->oYApp->a_data;                                                // se devuelven todas las entidades en cache del modulo
    foreach ( $aParameters['entities'] as $sEntiNomb => $aEntiInst )                                // crear dinamicamente las variables de las entidades
      $GLOBALS[ $sEntiNomb ] = $aEntiInst;                                                          // de esta forma la variable es global
    
    // evaluar valores de aParameters
    // PENDIENTE: control.redirect problema cuando el usuario utiliza dos tabs a la vez
    
    return $aParameters;
  }

}