<?php 




namespace Webfan\Webfat\App;

use Webfan\Webfat\App\ConfigContainer;
use Webfan\Webfat\App\ContainerCollection;
# use frdl\ContainerCollectionV2 as ContainerCollection;


use Configula\ConfigFactory as Config;
use Configula\ConfigValues as Configuration;
use Configula\Loader;
use Doctrine\Common\Cache\FilesystemCache;
//use Eljam\CircuitBreaker\Breaker
use Webfan\Webfat\App\CircuitBreaker as Breaker;
use Eljam\CircuitBreaker\Circuit;


use Eljam\CircuitBreaker\Event\CircuitEvents;
//use Eljam\CircuitBreaker\Event\CircuitEvent as Event;
//use Fuz\Component\SharedMemory\SharedMemory;
use Webfan\Webfat\App\SharedMemory;
//use Fuz\Component\SharedMemory\Storage\StorageFile;
use Webfan\Webfat\App\SharedMemoryStorageFile as StorageFile;

use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\ServerRequest;
use IvoPetkov\HTML5DOMDocument;
use Webfan\Webfat\HTMLServerComponentsCompiler;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Symfony\Component\EventDispatcher\Event;
use Webfan\Webfat\Console;
use Frdlweb\AppInterface;
use frdlweb\StubHelperInterface;
use Frdlweb\AdvancedWebAppInterface;
use LogicException;
use Frdlweb\WebAppInterface;
use Spatie\Once\Backtrace as SpatieBacktrace;
use Spatie\Once\Cache as SpatieCache;

# use Monolog\Level as LogLevel;
use Psr\Log\LogLevel;
use Monolog\Logger;
use Monolog\Handler\StreamHandler as LoggerStreamHandler;
use Psr\Log\LoggerInterface;
use Monolog\Registry as LoggerRegistry;

use Webfan\Webfat\Filesystems\PathResolvingFilesystem as StreamHandler;


class Kernel implements RequestHandlerInterface, WebAppInterface
{
    use \Nette\SmartObject,
	    \Webfan\withClassCastingTrait;

	public const MODULES_INFO_CONTAINER_ID = 'config.modules';
    public const CIRCUIT_MAIN = 'circuit.api.main';
    public const MAIN_STATE_MUTEX = 'runtime.state';
    public const MAIN_CONTAINER = 'runtime.container';
    public const MAIN_EVENTS = 'runtime.events';
    public const USERDATA = 'userdata';
    public const WEBSITES = 'websites';
    public const DOMAINS = 'domains';
    public const GLOBAL = 'global';

	protected $connections = [];
	protected $FRDL_WORKSPACE = null;
    protected $isBooted = false;
    protected $container = null;
    protected $env = null;
	protected $argv = null;
    protected $dir = null;
    protected $sources = [];
    protected static $instances = [];
    protected static $messages = [];
    protected $context = [];
    protected $circuitStorage = [];
    protected $circuit = [];
    protected $appStateStorage = [];
    protected $appStateShare = [];
	protected $appStateShareFiles = [];
    protected $stubHelper = null;
	protected $appId = null;
	
	protected $webUriBase = '/';

	protected $GlobalObject = null;
	protected $terminated = false;
	protected $isMounted = false;
	protected $mgs = null;
	protected $sessionName = 'TILLSESSION';
	protected $devlogfile;
	
	protected $_done = [];
	
	protected $_Document = null;
	
	protected $_CommandCall = null;

	protected $_stateEventEmitters = []; //Webfan\Webfat\EventEmitter
	
/*
             $eventsDirectory = $app->getDir(self::MAIN_EVENTS);
             \Webfan\App\EventModule::setBaseDir($eventsDirectory);
             $event = new \webfan\hps\Event('app.idle');
             $event->setArgumentReference('app', $app);
             $event->setArgumentReference(get_class($app), $app);
             $event->setArgumentReference(AppInterface::class, $app);
             $event->setArgument('context', $contextArgs);
             \Webfan\App\EventModule::action( $app->dotty(__METHOD__) )->emit('app.idle', $event);


$my_directory =  __DIR__.\DIRECTORY_SEPARATOR.'compiled-events';
 \Webfan\App\EventModule::setBaseDir($my_directory);
### Register Events Register the events by your configuration/build script/process.

 \Webfan\App\EventModule::register('test', 'testing', static function($eventName, $emitter, \webfan\hps\Event $Event){
        print_r($Event->getArgument("testParam"));
});
### Call Events Dispatch the events later in a different script/process.

$event = new \webfan\hps\Event('testing');
$event->setArgument('testParam', 'testValue'); 
\Webfan\App\EventModule::action('test')->emit('testing', $event);
*/
	public function emitter(string $action, string $appOrScheme = 'webfan') : \Webfan\App\EventModule | \Webfan\Webfat\EventModule
	{
		$dir = $this->getAppIntentDir($this->scheme($appOrScheme), self::MAIN_EVENTS, true);
		// \Webfan\Webfat\EventModule::setBaseDir( $dir );
//		return new \Webfan\App\EventModule( $action, false, $this->getDir(self::MAIN_EVENTS) );
		//return \Webfan\Webfat\EventModule::action( $action , false, $dir );
		return  \Webfan\Webfat\EventModule::action( $action , false, $dir );
	}
	
	public function state(string $signal = null) : array | \Webfan\Webfat\EventEmitter 
	{
	    if(is_string($signal) ){
		   if(!isset($this->_stateEventEmitters[$signal])){
			  $this->_stateEventEmitters[$signal] = new  \Webfan\Webfat\EventEmitter();  
		   }
		
			return $this->_stateEventEmitters[$signal];
		}
		
		return array_keys($this->_stateEventEmitters);
	}
	
	
    public function __construct(string $env = null, string $dir = null)
    {
		$this->_stateEventEmitters = []; //Webfan\Webfat\EventEmitter
		$this->_done = [];
		$this->FRDL_WORKSPACE = isset($_ENV['FRDL_WORKSPACE']) ? $_ENV['FRDL_WORKSPACE'] : getenv('FRDL_WORKSPACE');	
        $this->terminated = false;
		$this->context([
			'stage'=>null,
			'host' => isset($_SERVER['SERVER_NAME']) 
			      ? $_SERVER['SERVER_NAME'] 
			      : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] 
					// : ($this->isCLI() ? 'localhost' : urlencode('*') )
					   : \php_uname('n')
					),
		]);
		//$this->FRDL_WORKSPACE
		$this->devlogfile =rtrim($this->FRDL_WORKSPACE, '/\ '). \DIRECTORY_SEPARATOR.'devlog.txt'; 
		

		$u = explode('?', $_SERVER['REQUEST_URI']);
		$uri = $u[0];
	 	$this->webUriBase = dirname($_SERVER['PHP_SELF']);
			
		if(!file_exists($_SERVER['DOCUMENT_ROOT'].\DIRECTORY_SEPARATOR.'.htaccess')){
			 $this->webUriBase .= 'index.php/';	
		}
		 
		/** dirty fkn setAppId is too lazy invoked !!! Misuse $env as $appId instead !!! */
		$this->appId =$env;
		$env = 'dev';
			
		
        $this->dir =$dir;
        $this->env =  (null === $env) ? 'dev' : $env;		
    }
	

	public function context(?array $context = null) : array {
	  if(is_array($context)){
		  $this->context = array_merge($this->context, $context);
	  }
		return $this->context;
	}
	
	public function terminate(int $timelimit = null) {
	  if(true!==$this->terminated){	
		$this->terminated = true;
		ignore_user_abort(true);
		  if ( !$this->isCLI() ) {		
			  if($this->hasContainer() && $this->getContainer()->has('response') ){
				  $this->getContainer()->get('response')->withHeader('Connection', 'close');
			  }
			  header('Connection: close');
		  }
	  }
		if(null !== $timelimit){
			set_time_limit($timelimit);
		}
     return $this;
	}
	
	

	
	
    public function hasContainer(): bool
    {
		return null !== $this->container;
	}
	
    public function getContainer(): ContainerInterface
    {
		    $me = &$this;
			$contextContainerId = 'context';
			$configContainerId =  'config';
		//	$globalContainerFactoryServiceId = 'containerfactory.CompiledGlobalContainer';
			
			$rewrittenContainer = false;	
		
        if(!$this->hasContainer()){

			
		  $this->container = new ContainerCollection([			
			 'config.superadmin'=>(function(ContainerInterface $container){
				
			    $superAdminConfig=false;
				//$sources = $ContainerBuilder->get('app.runtime.sources');
			   // $file =  $sources['superadmin']['file'];
		      			
				$sources =$container->get('kernel')->getSources();
			   $file =  $sources['superadmin']['file'];
					
		          if(!is_dir(dirname($file))){
					 mkdir(dirname($file), 0775, true);  
				  }	
		
				 if(file_exists($file)){
					 $superAdminConfig = @include $file;
				 }
				
				 if(!file_exists($file) || !is_array($superAdminConfig) || !isset($superAdminConfig['superadmin'])  ){
		               $e = new ResolvableException(
		                 'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.superadmin=No superadmin installed'
		                   .'|php:'.get_class($this).'=Thrown by the Container Builder Invoker'
		                   .'@Superadmin mising'
		                 );			

					 
					 
					  if(!$container->get('kernel')->hasMaintenance('frdl', 'config.superadmin') ){ 
						  
						  $html = $e->html(-1);
						  
					      $container->get('kernel')->setMaintenance('frdl', 'config.superadmin', [
							 'command' => (function($input, $args, $maintenance, $Maintenance, $Kernel){
								 			   $sources =$Kernel->getSources();
			                                   $file =  $sources['superadmin']['file'];
								                if(file_exists($file)){
													$maintenance['progress'] = 100; 
													$maintenance['step'] = 'config.superadmin FINISHED uploadfile #GC done';
													$Kernel->setMaintenance('frdl', 'config.superadmin', $maintenance);
												 	$Kernel->deleteMaintenance('frdl', 'config.superadmin');
													$Kernel->out('Resolved: The superadmin config was installed.');
												}else{
													$Kernel->out('Missing: No superadmin installed!');
												}
							 }),
							 'flash' => [
								'config.superadmin' => ['error', $html],
							 ],
							 // 'html' => '<h3>Open maintenance task: %s://%s Progress: %s vH</h3>' . $html,
						  ]);
					      if(!$container->get('kernel')->isCLI()){
							  $container->get('kernel')->flash()->error( $html );
						  }
					//	  $this->getAppKernel()->end();
					  }//!maintenance
					return false;
					//  return false;
			    }//!file || !is_array || !isset
				
			   $superAdminConfig = $superAdminConfig['superadmin'];
			   return $superAdminConfig;		  
			}),			//'config.superadmin'		  
	    	\Psr\Http\Message\ServerRequestInterface::class => (function(ContainerInterface $container){
				  return $container->get('request');
			}),
			'request'=> (function(ContainerInterface $container){
			//	 $class = $ContainerBuilder->get(\Psr\Http\Message\ServerRequestInterface::class);
			   //  $request = $class::fromGlobals();
				 $request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals();
				 $request = $request->withUri($request->getUri()->withHost($container->has('context.host')
											    ? $container->get('context.host')
											    : $container->get('kernel')->context()['host'] 
											  ));
				 $container->get('kernel')->context([
				   'request' => $request,
				 ]);
				return $request;
			}),
			  
			'request.host'=> [function(ContainerInterface $container, $previous = null){
				return $container->get('request')->getUri()->getHost();
			 }, 'factory'],
			  
			 'app.runtime.schemes.required' =>function($container)  {
				  return [
					  'frdl', 
					  'webfan', 
					  'webconfig', //'webtemp', 						 
					  'website',// 'webapp', 'webmaster',
					  'web+fat',
					  //'websites', 'webapps', 'webusers',					
					  //'webcentral',
					  'web+cdn',
					  'web+cta',
				  ];
			  },			  
			 'logger.default' =>[function($container, $previous = null) {	
				 $logger =new Logger('default');
				 $dir =  $container->get('kernel')->getAppIntentDir('frdl', 'log', true);
				 if(!is_dir($dir)){
					 mkdir($dir, 0775, true); 
				 }
				 if(!file_exists($dir.'default.log')){
					 touch($dir.'default.log'); 
				 }
				 $logger->pushHandler(new LoggerStreamHandler($dir.'default.log', LogLevel::DEBUG));
				return $logger;
		     }, 'factory'],
			  
			  'config.central.domains' =>  [function($container)  {
				   $file = 'webconfig://domains/central.php'; 
				  if(!file_exists($file)){
					  
					  if(!is_dir(dirname($file))){
						mkdir(dirname($file), 0775, true);  
					  }
					  
					 \Laminas\Config\Factory::toFile($file, [
					  'domains'=>[	 					  
						  'service'=>[	 		
							  'central' => $container->get('RequestDomainFactory')->getRegistrableDomain(),	
							  'registrable'=>[						
								  $container->get('RequestDomainFactory')->getRegistrableDomain(),						
							  ],						
							  'api' => $container->get('RequestDomainFactory')->getRegistrableDomain(),	
							  'cdn' => $container->get('RequestDomainFactory')->getRegistrableDomain(),					 
						  ],					 
					  ],  					 
					 ]);  
				  }

				   if(file_exists($file)){
				     $container->get('runtime')->configure(
				        require $file
				     );
				   }
				  return $container->get('runtime')->getConfig()->has('domains.service')
					  ? $container->get('runtime')->getConfig()->get('domains.service')
					  : false;
			  }, 'default'],	
			  
			  'config.central.domain' =>  [function($container)  {
				  $central = $container->get('config.central.domains');
				  return is_array($central) && isset($central['central']) ? $central['central'] : false;
			  }, 'default'],	
			  
			  'config.vdns.dir' =>  [function($container)  {
				   return 'webconfig://vdns'; 
			  }, 'default'],				  
			  'RequestDomain.suffixFile' =>  [function($container)  {
				   return $container->get('config.vdns.dir').'/registrable-suffix.txt'; 
			  }, 'default'],	
			  'RequestDomain' =>  [function($container)  {
				   return $container->get('RequestDomainFactory');
			  }, 'default'],	
			  'RequestDomainDNSHash' =>  [function($container)  {
				  // return array_reverse(explode('.', $container->get('request')->getHost()));
				   return $container->has('RequestDomain')
					        ? $container->get('RequestDomain')->labels()
					       // : array_reverse(explode('.', $container->get('request')->getHost()));
					          : array_reverse(explode('.', $container->get('request.host')));
			  }, 'default'],	
			  'config.vdns.hostsfile.current.filename' =>  [function($container, $previous = null)  {
				   $path = $container->get('config.vdns.dir'); 
				   $dns = $container->get('RequestDomainDNSHash');
				   $file = false;
				   while(count($dns)>0 && (false === $file || !\file_exists($file))){
					   $file = $path.'/'.implode('/', $dns);
					   array_pop($dns);
				   }
				  return $file;
			  }, 'factory'],	
			  'config.vdns.hostsfile.current' =>  [function($container, $previous = null)  {
				   $file = $container->get('config.vdns.hostsfile.current.filename'); 
				  if(false === $file || !\file_exists($file)){
					  $file = $container->get('config.vdns.dir').'/virtual-hosting-hosts';
				  }
				  return $file;
			  }, 'factory'],		
			  'config.vdns.hostsfile.saveto' =>  [function($container, $previous = null)  {
				   $path = $container->get('config.vdns.dir'); 
				   $dns = $container->get('RequestDomainDNSHash');
				   if(count($dns)>0){
					   $path.='/'.$dns[0];
				   }
				   if(count($dns)>1){
					   $path.='/'.$dns[1];
				   }
				   if(count($dns)>2){
					   $path.='/'.$dns[2];
				   }			  
				  
				  return $path;
			  }, 'factory'],	
			  'RequestDomainFactory' =>  [function($container, $previous = null)  {
				    $suffixFile = $container->get('RequestDomain.suffixFile');
				   // $domain =new \Pdp\Domain($container->get('request')->getHost());
				    $domain =new \Pdp\Domain($container->get('request.host'));
				    $publicSuffixList = \Pdp\Rules::createFromString(\file_exists($suffixFile) ? file_get_contents($suffixFile) : '');
				    $result = $publicSuffixList->resolve($domain);

				  //// DEPRECTAED: print_r($result->getDomain()
				  //// ...  ->getContent());
				//  print_r($result->getPublicSuffix() );
				//  print_r($result->getSubDomain());
				//  print_r($result->getRegistrableDomain());
				//  print_r($result->labels() ); 			
				   return $result;
			  }, 'factory'],	
			  
			  'Document' =>  [function($container, $previous = null)  {
				   return $container->get('kernel')->Document;
			  }, 'factory'],				  
			  
			  'PHP_BIN_PATH' =>  [function($container, $previous = null)  {
				   return (new \Webfan\Helper\PhpBinFinder())->find();
			  }, 'factory'],			  

			  'kernel' =>  [function($container, $previous = null) use(&$me) {
				   return $me;
			  }, 'factory'],		
			  'Maintenance' => [function($container, $previous = null)  {
				  return $container->get(Maintenance::class);
			  }, 'factory'],
			  Maintenance::class =>[function($container, $previous = null)  {
				  return new Maintenance($container->get('kernel'));
			 }, 'factory'],
			  KernelHelper::class => function($container) use(&$me) {
				  return new KernelHelper($me);
			  },
			  $configContainerId => [function($container, $previous = null) use(&$me) {
				   return $me->global()->getConfig();
				  /*
				   if((isset($previous) && !is_null($previous) ) && (
					  ( is_object($previous) 
					  && ($previous instanceof Configuration || $previous instanceof Config)
					  )
					     || is_array($previous)
					   )
					 ){					   								 	
					   if(is_array($previous)){		  
							return $me->global()->getConfig()->merge(Config::fromArray($previous));					
					   }elseif(!is_null($previous)){		 
							return $me->global()->getConfig()->merge($previous);										
					   }
				   }else{
				       return $me->global()->getConfig();
				   }
				   */
			  }, 'factory'],

			 'flash' =>[function($container, $previous = null)  {
			   return $container->get('kernel')->flash();
		     }, 'factory'],
		], ContainerCollection::NULL_ONERROR, ContainerCollection::CALL_ID);  
			
			$this->container->factory('logger.default', function($container, $previous = null) {			   
				 $logger = $previous;
				 $logger->pushProcessor( (new \Monolog\Processor\WebProcessor())->addExtraField('user_agent', 'HTTP_USER_AGENT')  );
				 $logger->pushProcessor( new \Monolog\Processor\HostnameProcessor()  );
				 $logger->pushProcessor( new \Monolog\Processor\ProcessIdProcessor()  );
				 $logger->pushProcessor( new \Monolog\Processor\IntrospectionProcessor('error')  );
				return $logger;
		     });
				
			$this->container->factory('logger.default', function($container, $previous = null) {
			     $logger = $previous;
				 $dir =  $container->get('kernel')->getAppIntentDir('webfan', 'log', true);
				 if(!is_dir($dir)){
					 mkdir($dir, 0775, true); 
				 }
				 if(!file_exists($dir.'default.log')){
					 touch($dir.'default.log'); 
				 }
				 $logger->pushHandler(new LoggerStreamHandler($dir.'default.log', LogLevel::DEBUG));
				return $logger;
		     });
	
			
			/*	*/	
			$this->container->factory('webfan://logger.default', function( $container, $previous = null) {
				return $container->get('logger.default');
		     });		
			
			$this->container->factory('app.runtime.stub', function( $container, $previous = null) {
				return $container->get('kernel')->getStub();
		     });	
	 	
			$this->container->factory('app.runtime.stubrunner', function( $container, $previous = null) {
				return !$container->has('app.runtime.stub')
					 || null===$container->get('app.runtime.stub') ? $previous : $container->get('app.runtime.stub')->getRunner();
		     });	
						
			$this->container->factory('app.runtime.codebase', function( $container, $previous = null) {
				return  !$container->has('app.runtime.stub')
					 || !$container->has('app.runtime.stubrunner')
					 || null===$container->get('app.runtime.stubrunner') 
					    ? $previous 
					    : $container->get('app.runtime.stubrunner')->getCodebase();
		     });	
			$this->container->factory('app.runtime.autoloader.remote', function( $container, $previous = null) {
				return  !$container->has('app.runtime.stub')
					 || !$container->has('app.runtime.stubrunner')
					 || null===$container->get('app.runtime.stub') 
					? $previous 
					: $container->get('app.runtime.stubrunner')->getRemoteAutoloader();
		     });				
				
			
					$this->container->set('files.index.php', (null !== $this->getStub() )
								  ? ''.$this->getStub()->location
								  : \get_included_files()[0]
								 );	
			
		}//!hasContainer()
			
			
			
		 			
			$this->global()->configure([
			  'app.runtime.api.url' => ($this->container->has('app.runtime.codebase') 
										&& null !== $this->container->get('app.runtime.codebase')  )
					       ? $this->container->get('app.runtime.codebase')->getRemoteApiBaseUrl()
					       : 'https://api.webfan.de/',
				
			]);
	 
		
		
		 if(!$this->container->hasContainer($contextContainerId)){	
			$ContextContainer = new ContextContainer( \Webfan\ArrayHelper::toDotTreeStatic($this->context, '{', '}') );
			$this->container = $this->container->addContainer($ContextContainer, $contextContainerId);
		 }//!has $contextContainerId
			 
			
		 if(!$this->container->hasContainer($configContainerId)){
			$ConfigContainer = new ConfigContainer( $this->container->get($configContainerId) );
			$this->container = $this->container->addContainer($ConfigContainer, $configContainerId);
		 }//! has $configContainerId
							    
			 
			
			
			$containerId = 'console';
		 if(!$this->container->hasContainer($containerId)){
		    $containerClass = 'CompiledConsoleContainer';          
				$containerBuilder = new ConsoleContainer($me, $containerClass);           
				$containerBuilder = $containerBuilder->enableCompilation($me->getDir(self::MAIN_CONTAINER, true),
                                                                   $containerClass,
                                                                   \DI\Container::class);		
			//	$containerBuilder->wrapContainer( $this->container  );
			
			  $isOld = file_exists($containerBuilder->filename());
			    if(!$isOld){
					@ini_set('max_execution_time',  max(240, intval(ini_get('max_execution_time')) + 90)  );
					$AppBuilder = $containerBuilder->getAppBuilder();
					$rewrittenContainer = true;
				}
		/*	
			$CompiledCompiledConsoleContainer = $this->main('circuit.breaker')->protect(function () use(&$me, $containerBuilder) {
				try{				
					return $containerBuilder->build(true,  $me->getContainer(), false );					  
				}catch(\Exception $e){
					$me->error($e->getMessage());
					throw $e;
				}				  
			});
		*/
			$CompiledCompiledConsoleContainer = $containerBuilder->build(true,  $this->container, false );	
		//	unset($containerBuilder);
			$this->container = $this->container->addContainer(  $CompiledCompiledConsoleContainer, $containerId  );			
			
			    if($rewrittenContainer && !$this->isCLI() && !$isOld){
				 	$rewrittenContainer = true;
					  $this->flash()->info(
							   'The console container was rebuild! The page reloads automatically...'						
					  );
				     	$this->flash()->info( $this->getFormFromRequest(
							  '<span class="btn-success">circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7 - Resolved automatically</span>', 
											 null, true, 5)
						);
					
					
					
				//	 $this->exec('setup');	
					
					if(!$this->isCLI()){
						 // clearstatcache();
					   // $this->end();
					}
				 // return $this->container;
				}				
			
		 }// if(!$this->container->hasContainer($containerId))
		
		
			$containerIdGlobal = 'global';			         
		    $containerClassGlobalContainer = 'CompiledGlobalContainer';  
		
		  if(!$this->container->hasContainer($containerIdGlobal)){
		    
				 $containerBuilderGlobalContainer = new ContainerAppKernel($me
																		   , $containerClassGlobalContainer);           
				 $containerBuilderGlobalContainer = $containerBuilderGlobalContainer->enableCompilation(
					                                                    $me->getDir(self::MAIN_CONTAINER, true),
                                                                        $containerClassGlobalContainer,
                                                                   \DI\Container::class);		
			//	$containerBuilderGlobalContainer->wrapContainer( $this->container  );
			
			    $isOld = file_exists($containerBuilderGlobalContainer->filename());
			    if( !$isOld){
					@ini_set('max_execution_time',  max(240, intval(ini_get('max_execution_time')) + 90)  );
					$AppBuilder = $containerBuilderGlobalContainer->getAppBuilder();
					$rewrittenContainer = true;
				}					
			   
				// try{				
					    $CompiledContainerKernelContainer = $containerBuilderGlobalContainer->build(true,   $this->container, false );	
			          // unset($containerBuilderGlobalContainer);
			  //  }catch(\Exception $e){
					 //  $this->error($e->getMessage());
				   // throw $e;
				// }
				  
					/*
				   if($rewrittenContainer && !$this->isCLI() && !$isOld){
					  $this->flash()->info(
							   'The global container was rebuild! The page reloads automatically...'						
					  );
				     	$this->flash()->info( $this->getFormFromRequest(
							  '<span class="btn-success">circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7 - Resolved automatically</span>', 
											 null, true, 5)
						);
					if(!$this->isCLI()){
						$this->flash()->info(
							$this->getFormFromRequest(
							  '<span class="btn-success">The global container was rebuild</span>', 
											null, true, 5));
						 //  clearstatcache();
						  $this->end();
					}
				}						
					*/
			
			 	/*
			if($CompiledContainerKernelContainer  instanceof ContainerInterface){
				//$this->container->unregister($globalContainerFactoryServiceId, true);
		    	$this->container = $this->container->addContainer(  $CompiledContainerKernelContainer, $containerIdGlobal  );		
			}else{
				$err = 'Could not get compiled container in '.__METHOD__.' '.__LINE__;
				$this->flash()->error($err);
                $this->error($err);
				return $this->container;
			}
			*/
                $this->container = $this->container->addContainer(  $CompiledContainerKernelContainer, $containerIdGlobal  );		
		//	if(true === $rewrittenContainer){
		//		$this->exec('setup', true, true);
		 //	}
        }//if(!$this->container->hasContainer($containerIdGlobal))

	/*
 		$eventName = 'container:ready';	
		$event = new \Webfan\Webfat\Event($eventName);
		$event->setArgument('kernel', $this);  
		$event->setArgument('container', $this->container);  		
		$this->state('container', 'webfan')->emit($eventName, $event);
	
		if($this->isMounted('website')){
			$this->state('container', 'website')->emit($eventName, $event);
		}
			*/	
		
        return $this->container;
    }	
	
	
	
	
	public function hasShared(string $id = null, string $appOrScheme = null) : bool {   
		
			
		 if(!$this->isMounted($appOrScheme)){							
			throw new ResolvableException(
		              'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.5.1=Scheme '.$appOrScheme.':// is NOT MOUNTED into the app!'
		             .'|php:'.get_class($this).'=Thrown by the Kernel'
		                .'@'.$appOrScheme.':// is not mounted!'
		             );			
		}	
		
		if(null === $id){
			 return isset($this->appStateShare[$appOrScheme]);
		}
	   return isset($this->appStateShare[$appOrScheme][$id]);
	}	
	
	public function deleteShared(string $sharedId, string $appOrScheme){  
		if(!$this->hasShared( $appOrScheme, $sharedId ) ){
		  return;	
		}
		if(isset($this->appStateShare[$appOrScheme][$sharedId])){
		  @$this->appStateShare[$appOrScheme][$sharedId]->unlock();	
		}
		unset($this->appStateShare[$appOrScheme][$sharedId]); 
		unset($this->appStateStorage[$appOrScheme][$sharedId]);
		unlink($this->appStateShareFiles[$appOrScheme][$sharedId]);
		unset($this->appStateShareFiles[$appOrScheme][$sharedId]);	
	//	if(0 === count($this->appStateShare[$appOrScheme]) ){
	//	  unset($this->appStateShare[$appOrScheme]);	
	//	}
	}		
	
	public function &getShared(string $sharedId, string $ext = 'txt', string $appOrScheme = null) : SharedMemory {      
		
		
		if(!$this->isMounted($appOrScheme)){							
			throw new ResolvableException(
		              'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.5.1=Scheme '.$appOrScheme.':// is NOT MOUNTED into the app!'
		             .'|php:'.get_class($this).'=Thrown by the Kernel'
		                .'@'.$appOrScheme.':// is not mounted!'
		             );			
		}
		
		$dir = null !== $appOrScheme && $this->isMounted($appOrScheme)
			? StreamHandler::resolve( $this->getAppIntentDir($appOrScheme, self::MAIN_STATE_MUTEX, true) )
			: $this->getDir(self::MAIN_STATE_MUTEX);
			
		$file = $dir.'/'.preg_replace("/[^A-Za-z0-9\-\.\_]/", "-", $appOrScheme.'.'.$sharedId).'.'.$ext;
		
               if(!is_dir($dir)){
                  mkdir($dir, 0775, true);
                } 
		
		if(!isset($this->appStateStorage[$appOrScheme])){
			$this->appStateStorage[$appOrScheme] = [];
		}		
		if(!isset($this->appStateShare[$appOrScheme])){
			$this->appStateShare[$appOrScheme] = [];
		}				
		
		
		if(!isset($this->appStateStorage[$appOrScheme][$sharedId])){    
			if(!isset($this->appStateShareFiles[$appOrScheme])){
			  	$this->appStateShareFiles[$appOrScheme] = [];
			}
			$this->appStateShareFiles[$appOrScheme][$sharedId] = $file;
			$this->appStateStorage[$appOrScheme][$sharedId] = new StorageFile($file); 
		}                
		if(!isset($this->appStateShare[$appOrScheme][$sharedId])){                  
			$this->appStateShare[$appOrScheme][$sharedId] = 
				new SharedMemory($this->appStateStorage[$appOrScheme][$sharedId] );               
		}		
		

		$this->appStateShare[$appOrScheme][$sharedId]->unlock();
		return $this->appStateShare[$appOrScheme][$sharedId];
	}
	
	
	
	
	
	public function &getCircuitBreaker(string $appOrScheme = null, string $circuitId = null, 
									  bool | \callable | \Closure $onSuccess = null,
									  bool | \callable | \Closure $onFailure = null,
									  bool | \callable | \Closure $onOpen = null,
									  bool | \callable | \Closure $onClosed = null,
									  bool | \callable | \Closure $onHalfopen = null,
									   int $max_failure = 1,
									   int $reset_timeout = 5,
									   bool $ignore_exceptions = false, 
									   string $ext = 'txt',
									  array $exclude_exceptions = [],
									  array $allowed_exceptions = [],
									  bool $forceAddEventHandlers = false) : Breaker {  
		
		
		
		if(!$this->isMounted($appOrScheme)){							
			throw new ResolvableException(
		              'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.5.1=Scheme '.$appOrScheme.':// is NOT MOUNTED into the app!'
		             .'|php:'.get_class($this).'=Thrown by the Kernel'
		                .'@'.$appOrScheme.':// is not mounted!'
		             );			
		}
			
		
		
		    $me = &$this;
		
			$dir = null !== $appOrScheme && $this->isMounted($appOrScheme)
			? StreamHandler::resolve( $this->getAppIntentDir($appOrScheme, self::CIRCUIT_MAIN, true) )
			: $this->getDir(self::CIRCUIT_MAIN);
			
               if(!is_dir($dir)){
                  mkdir($dir, 0775, true);
                } 
		
		       if(!is_dir($dir)){
                  mkdir($dir, 0775, true);
                }	
		
		if(!isset($this->circuitStorage[$appOrScheme])){
			$this->circuitStorage[$appOrScheme] = [];
		}
	 
                  if(!isset($this->circuitStorage[$appOrScheme][$circuitId])){
                      $this->circuitStorage[$appOrScheme][$circuitId] = new FilesystemCache($dir,
							//	preg_replace("/[^A-Za-z0-9\-\.\_]/", "-", $appOrScheme.'.'.$circuitId)
								preg_replace("/[^A-Za-z0-9\-\.\_]/", "-", $appOrScheme.'.'.preg_split("/\s+|\./m", $circuitId)[0])												.'.'.$ext);
                  }		
		
				
		if(!isset($this->circuit[$appOrScheme])){
			$this->circuit[$appOrScheme] = [];
		}
		
		          $isNew = false;
                  if(!isset( $this->circuit[$appOrScheme][$circuitId])){					  
				    $isNew = true;					  
                    $this->circuit[$appOrScheme][$circuitId] = new Breaker($appOrScheme.'-'.$circuitId, [                     
						'ignore_exceptions' => $ignore_exceptions,						
						'max_failure' => $max_failure,
						'reset_timeout' => $reset_timeout,
						'exclude_exceptions' => $exclude_exceptions,
						'allowed_exceptions' => $allowed_exceptions,
                    ], $this->circuitStorage[$appOrScheme][$circuitId]  );
				  }	  
					  
		
		     if(true === $isNew || true === $forceAddEventHandlers){
				 
							     if(true === $onSuccess){
						 $onSuccess = function ( $event) use(&$me, $circuitId) {                       
							//// $circuit = $event->getCircuit();						
							 //$me->debug(sprintf("Connection to service '%s$1' success!\n", $circuit->getName()));                   
						 }; 
					 }
						   
				    if(true === $onFailure){
						 $onFailure = function ( $event) use(&$me, $circuitId) {                       
							// $circuit = $event->getCircuit();						
							// $me->error(sprintf("Connection to service '%s$1' failed!\n", $circuit->getName()));  
							 $me->error(sprintf("Connection to service '%s$1' failed!\n", $circuitId));  
						 }; 
					 }		 
				  
				    if(true === $onOpen){
						 $onOpen = function ( $event) use(&$me, $circuitId) {                       
						//	 $circuit = $event->getCircuit();						
							 $me->error(sprintf("Connection to service '%s$1' is open!\n", $circuitId));                   
						 }; 
					 }		 
				 
						   
				 
				 if(true === $onClosed){
						 $onClosed = function ( $event) use(&$me, $circuitI) {                       
							// $circuit = $event->getCircuit();						
							 //$me->debug(sprintf("Connection to service '%s$1' success!\n", $circuit->getName()));                   
						 }; 					
				 }		 
				 
				 
				 				  
				    if(true === $onHalfopen){
						 $onHalfopen = function ( $event) use(&$me, $circuitI) {                       
						//	 $circuit = $event->getCircuit();						
							 $me->warning(sprintf("Connection to service '%s$1' is half-open!\n", $circuitId));                   
						 }; 
					 }			
				 
					  if(!is_null($onSuccess)){
	                    $this->circuit[$appOrScheme][$circuitId]->addListener(CircuitEvents::SUCCESS, $onSuccess);					  
					  }
					  					  
					  if(!is_null($onFailure)){
	                    $this->circuit[$appOrScheme][$circuitId]->addListener(CircuitEvents::FAILURE, $onFailure);					  
					  }			
					  
					  if(!is_null($onOpen)){
	                    $this->circuit[$appOrScheme][$circuitId]->addListener(CircuitEvents::OPEN, $onOpen);					  
					  }			
					  
					  if(!is_null($onClosed)){
	                    $this->circuit[$appOrScheme][$circuitId]->addListener(CircuitEvents::CLOSED, $onClosed);					  
					  }			
					  
					  if(!is_null($onHalfopen)){
	                    $this->circuit[$appOrScheme][$circuitId]->addListener(CircuitEvents::HALF_OPEN, $onHalfopen);					  
					  }
			 }
		

		return  $this->circuit[$appOrScheme][$circuitId];
	}
	
	
	
	public function hasConnection(string $id = null, string $appOrScheme = null) : bool {   
		if(null === $id){
			 return isset($this->connections[$appOrScheme]);
		}
	   return isset($this->connections[$appOrScheme][$id]);
	}	
	
	public function &getConnectionState(string $appOrScheme,  string $id) : SharedMemory {
          $storageId = $this->_getConnectionStorageId($appOrScheme, $id); 
		return $this->getShared($storageId, 'txt', $appOrScheme);
	}
	
	protected function _getConnectionStorageId(string $appOrScheme = null,  string $id){
			return self::MAIN_STATE_MUTEX.'.connection-state'
			.'.'
			.sha1($id).'.'.strlen($id)
			.'.'
			.preg_replace("/[^A-Za-z0-9\-\.\_]/", "-", $id);	
	}
	
	public function &getConnection(string $appOrScheme = null,  string $id, 
								  int $max_failure = 1, int $reset_timeout = 5, bool $ignore_exceptions = false,
									  array $exclude_exceptions = [],
									  array $allowed_exceptions = []){
		
		$connection = null;
		

		if(null===$appOrScheme || !$this->isMounted($appOrScheme)){							
			throw new ResolvableException(
		              'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.5.1=Scheme '.$appOrScheme.':// is NOT MOUNTED into the app!'
		             .'|php:'.get_class($this).'=Thrown by the Kernel'
		                .'@'.$appOrScheme.':// is not mounted!'
		             );			
		}
				
		//if(null===$appOrScheme){
		//   $appOrScheme = 'webfan';	
		//}
		
		
		if(!isset($this->connections[$appOrScheme])){
			$this->connections[$appOrScheme] = [];
		}
		
		if( isset($this->connections[$appOrScheme][$id])){
		  return $this->connections[$appOrScheme][$id];	
		}
		
		
		
		$storageId = $this->_getConnectionStorageId($appOrScheme, $id);
		
		$me = &$this;
		
          
				   $state = $this->getConnectionState($appOrScheme, $id);
					  
				  $circuit = $this->getCircuitBreaker($appOrScheme, $storageId, 
					function ( $event) use( $id, &$me, &$state) {
                     //   $circuit = $event->getCircuit();
                    //    echo "Success:".$circuit->getFailures()."\n";
						$state->main = true;
                    }, function ( $event) use( $id, &$me, &$state) {
                       // $circuit = $event->getCircuit();
						$me->error(sprintf("Connection to service '%s$1' failed!", $id));
						$me->flash()->error( sprintf("Connection to service '%s$1' failed!\n", $id) );
                      //   echo "Increment failure:".$circuit->getFailures()."\n";
					//	$state->main = "Increment failure:".$circuit->getFailures()."\n";
						$state->main = false;
                    }, function ( $event) use( $id, &$me, &$state) {
                      //  $circuit = $event->getCircuit();
						$me->warning(sprintf("The service '%s$1' is NOT CONNECTED correctly!", $id));
                        $me->flash()->error( sprintf("The service '%s$1' is NOT CONNECTED correctly!", $id) );
						 
						//$state->main = sprintf("circuit %s is open \n", $circuit->getName());
						//$state->main = sprintf("The service '%s$1' is NOT CONNECTED correctly!\n", $circuit->getName());
						$state->main = false;
                    }, function ( $event) use( $id, &$me, &$state) {
                       // $circuit = $event->getCircuit();
                     //   echo sprintf("circuit %s is closed \n", $circuit->getName());
						// $state->main = sprintf("circuit %s is closed \n", $circuit->getName());
						$me->debug(sprintf("circuit %s is closed", $id));
						$state->main = true;
                    }, function ( $event) use( $id, &$me, &$state) {
                       // $circuit = $event->getCircuit();
						$me->warning(sprintf("The service '%s$1' is NOT READY!", $id));
                        $me->flash()->error( sprintf("The service '%s$1' is NOT READY!", $id) );
						 
						$state->main = false;
                    },
									   $max_failure,
									   $reset_timeout,
									   $ignore_exceptions, 
									   'txt',
									  $exclude_exceptions,
									  $allowed_exceptions,
									false);
					  
             
  		
		  $connection = $circuit->protect(function () use( $appOrScheme, $id, &$me, &$state ) {
			  if( !$me->getContainer()->has($id) && 
				 !$me->getContainer()->has($appOrScheme.'://'.$id) && 
				 !$me->getContainer()->has($appOrScheme.'@'.$id) && 
				 !$me->getContainer()->has($appOrScheme.'.'.$id) 
				){
				  throw new \Exception(sprintf('The ID# %3$s.%1$s is not registered in the Container in %2$s!',
											   $id, __METHOD__, $appOrScheme));
			  }
			  
			  if($me->getContainer()->has($id)){
				return $me->getContainer()->get($id);  
			  }			  
			  
			  if($me->getContainer()->has($appOrScheme.'://'.$id)){
				return $me->getContainer()->get($appOrScheme.'://'.$id);  
			  }
			  
			  if($me->getContainer()->has($appOrScheme.'@'.$id)){
				return $me->getContainer()->get($appOrScheme.'@'.$id);  
			  }			  
			  
			  if($me->getContainer()->has($appOrScheme.'.'.$id)){
				return $me->getContainer()->get($appOrScheme.'.'.$id);  
			  }		  
			  

             return $me->getContainer()->has($appOrScheme.'.'.$id)
				 ? $me->getContainer()->get($appOrScheme.'.'.$id)
				 : $me->getContainer()->get($id);
		  });
		
		
		
		if($connection && !is_null($connection) && true !== $connection instanceof \Exception){
		  $this->connections[$appOrScheme][$id] = $connection;
		}
		
		return $connection;
	}
	
	
	
	
	public function &flash(){
		if(null===$this->mgs){
			$this->session_start($this->sessionName);
			$this->mgs = new \frdl\Flash();
		}
		
      return $this->mgs;
	}
 
/**
$constructor = \Webfan\Script::create(function () {
    $this->property = 1;
    $this->getProperty = function () {
        return $this->property;
    };
});

$constructor->prototype = \Webfan\Script::create([
    'getDouble' => function () {
        return $this->getProperty() * 2;
    },
]);

$doubleInstance = $constructor();

echo $doubleInstance->getDouble();//
	*/	
   public function &global(){	
	//	 public function global(){
		 if(null === $this->GlobalObject){
			 $obj = call_user_func(function(){
				 $obj = \Webfan\Script::create(function () {  						  
					 $arr = [];
					 $this->configuration =new Configuration($arr);
					//  $this->configuration = Config::fromArray($arr);
				 });	
				 $obj->prototype = \Webfan\Script::create([  				
					  'getConfig' =>  function () {      					
						    return $this->configuration;    				
					  },
					 'configure' => function (array|Config|Configuration $config = null) {     	
								 		if(!is_null($config) && is_array($config)){		  
											$this->configuration = $this->getConfig()->merge(Config::fromArray($config));		
										}elseif(!is_null($config) && is_object($config) && $config instanceof Configuration){		 
											$this->configuration = $this->getConfig()->merge($config);		
										}
								 return $this->getConfig();  
					 },
				 ]);
				 return $obj;
			 });
			 $this->GlobalObject = $obj( );
			 $arr = [];
			 $this->GlobalObject->configuration =	new Configuration($arr);	
			 $this->GlobalObject->page = call_user_func(function($arg = []){
						 $page = \Webfan\Script::create(function ( ) {  		
							 $this->languages = [];
						    
				        });	
						 return $page( );					 
			 });			
			 
			  $languages = []; //@ToDo: get languages
              $this->GlobalObject->page->languages = $languages;
			  $this->GlobalObject->page->html =call_user_func(function( ){
								$html = \Webfan\Script::create(function ( ) {  					                        
								  $this->head = '';
								  $this->body = '';
								  $this->footer = '';
						       });	
							  return $html( );
							});		 


		 }//null === $this->GlobalObject

		 return $this->GlobalObject;
	 }

	
	public function dotEnvNamespaces(array $envNamespaces = []){
		
		foreach($envNamespaces as $ns){
		    try{
			
		        $this->global()->configure(Config::loadEnv($ns, '_'));
		    }catch(\Exception $e){
		        throw new ResolvableException(
		                 'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.6='.$ns.' Environment not OK?'
		                   .'|php:'.get_class($this).'=Thrown by the Kernel Class'
		                   .'@'.$e->getMessage()

		                 );
		    }
		}		
		$this->global()->getConfig();
	}
	
	public function loadEnvVars(array $envDirs, array $envFiles = ['.env'])
	{
		foreach($envDirs as $dir){
		   foreach($envFiles as $filename){

		       if(!is_dir($dir) || !is_file(rtrim($dir, '/\ '). \DIRECTORY_SEPARATOR.$filename)){
		           continue;
		       }

		            try{
		             $dotenv = \Dotenv\Dotenv::createImmutable($dir, $filename, false);
		             $dotenv->load();
		         }catch(\Exception $e){
		               throw new ResolvableException(
		                 'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.6='.$filename.' is not readable correctly in '.$dir
		                   .'|php:'.get_class($this).'=Thrown by the Kernel Class'
		                   .'@'.$e->getMessage()

		                 );
		        }
		   }
		}

	}
	
	/*
	public function loadCentral(){
		
	}
	
	public function loadWebsite(){
		
	}
	*/
	
	public function setAppId(string $appId = '1.3.6.1.4.1.37553.8.1.8.8.1958965301') : ?self {
		if('1.3.6.1.4.1.37553.8.1.8.8.1958965301' === $appId){
		  //throw new \Exception('You should not use appID #'.$appId.'!');
			$appId = null;
			$this->flash()->error( ( new \Webfan\Webfat\App\ResolvableLogicException(
                         'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.1=The (Main) Application ID must be defined'
                           .'|php:'.get_class($this).'=Thrown by the Codebase Class '.__METHOD__
                           .'@The Application ID must be defined'
                       ))->html(-1)  );
		}
		$this->appId =$appId;
	  return $this;
	}
	
	//'1.3.6.1.4.1.37553.8.1.8.8.1958965301'   circuit%3A1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.1
	/*
	                       throw new ResolvableException(
                         'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.superadmin=No superadmin installed'
                           .'|php:'.get_class($me).'=Thrown by the Kernel Class'
                           .'@Superadmin mising'
                         );	
						 */
	public function getAppId() : string {
		if(null === $this->appId){
			throw new ResolvableLogicException(
                         'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.5.1=The (Main) Application ID must be defined'
                           .'|php:'.get_class($this).'=Thrown by the Kernel Class '.__METHOD__
                           .'@The Application ID must be defined'
                         );	
		}
		return $this->appId;
	}

	
   public function isMethod(string $method, $classOrObject) : \stdclass {
        if(!is_string($classOrObject)){
		  $class = \get_class($classOrObject);	
		}else{
		  $class = $classOrObject;	
		}
  
	   $result = new \stdclass;
	   $result->exists = \method_exists($class, $method) 
		   || \method_exists($classOrObject, $method);
	   $result->callable = \is_callable([$classOrObject, $method]) || \is_callable([$class, $method]);
	   
	   try{ 
	       $refl = new \ReflectionMethod($classOrObject, $method);
		   $result->valid = $result->exists || $result->callable || $refl->isPublic();		   
		   $result->static = $refl->isStatic();
		   $result->public = $refl->isPublic();
		   $result->private = $refl->isPrivate();		   
	   }catch(\Exception $e){
		   $result->valid = false;
		   $result->static = false;
		   $result->public = false;
		   $result->private = false;		   
	   }
	   
	   return $result;
	}
	
	
	
	
	
	
	public function &__get($name){
		$me = &$this;
		switch($name){			
			case 'Document' :
				  if(null === $this->_Document){	
				    	$this->_Document = $this->HTMLDOcument;
				  }
				  return $this->_Document;
				break;
			case 'HTML5DOMDocument' :	
			case 'HTMLDOcument' :			
			//$HTMLDOcument = call_user_func(function(Kernel $me){
				 $obj = \Webfan\Script::create(function ($arg = []) use(&$me)  {  		
					 $withDocType = isset($arg['DocType']) ? $arg['DocType'] : '<!DOCTYPE html>';		
					 $content = isset($arg['content']) ? $arg['content'] : '';		
					 if(is_string($withDocType) && $withDocType !== substr($content, 0, strlen($withDocType))){        
						 $strtpl = "%s%s";          
						 $content=sprintf($strtpl, $withDocType, $content);		       
					 }
					 
					 $this->compiler = isset($arg['compiler']) ? $arg['compiler'] : $me->HTMLCompiler;	
				//	 $this->compiler =$arg['compiler'];					 				
				//	 $this->content =$arg['content'];					
                     $this->dom = new HTML5DOMDocument();
					 $this->dom->substituteEntities = false;
					 $this->dom->loadHTML($content, HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
				 });	
				 $obj->prototype = \Webfan\Script::create([  
					 'compile' => function (string | HTML5DOMDocument $content = '') : string {     	
	                       if(!empty($content)){
						      $this->dom->insertHTML($content);		
						   }
						 
						   $content = $this->save();	   
						   $content = $this->compiler->process($content);						
						 return $content;  
					 },
					 'load' => function (string | HTML5DOMDocument $content = '')  {     	
						 $this->dom->loadHTML($content, HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
						return $this;
					 },
					 'save' => function () : string {     	
						return $this->dom->saveHTML();	 
					 },
					 'doc' => function () {  
						//return $this->document();	
						 return $this->dom;	 
					 },
					 'document' => function () {  
						return $this->dom;	 
					 },
					 'write' => function (string | HTML5DOMDocument $content = '')  {     	
						 $this->dom->insertHTML($content);		 
						return $this;
					 },
				 ]);
			//	 return $obj;
			// }, $this);
				
				$obj = $obj([
			'content' => '',
			'compiler' => $this->HTMLComponentsCompiler,
			'DocType' => '<!DOCTYPE html>',
		]);
					
				     $obj->compiler =  $this->HTMLCompiler;	 		
                     $obj->dom = new HTML5DOMDocument();
					 $obj->dom->substituteEntities = false;
					 $obj->dom->loadHTML('', HTML5DOMDocument::ALLOW_DUPLICATE_IDS);			
				
			return $obj;			
			/* new $HTMLDOcument([					
				'compiler' =>&$this->HTMLComponentsCompiler,	
				'content' => '',
			]);
				 
			return $HTMLDOcument([					
				'compiler' =>&$this->HTMLComponentsCompiler,	
				'content' => '',
			]);*/
				break;
			case HTMLServerComponentsCompiler::class :
			case 'HTMLServerComponentsCompiler' :
			case 'HTMLCompiler' :
			case 'HTMLComponentsCompiler' :
			if(null !== $this->container){
			$compiler = $this->container->has(HTMLServerComponentsCompiler::class) 
														  ? $this->container->get(HTMLServerComponentsCompiler::class)        
				    : new HTMLServerComponentsCompiler($this->container->has('website.components.paths') 
														  ? $this->container->get('website.components.paths') 
														  : null, 
														 $this->container->has('call') 
														  ? $this->container->get('call') 
														  : null, 
														 $this->container->has('require') 
														  ? $this->container->get('require') 
														  : null, 
														  $this->container->has('define') 
														  ? $this->container->get('define') 
														  : null);
			

		}else{
			$compiler = new HTMLServerComponentsCompiler();
		}		
					
		if(null === $compiler->getViewTemplateRenderer() 
		   && null !== $this->container
		   && $this->container->has('app.runtime.renderer.default') 
		  ){
			$compiler->setViewTemplateRenderer($this->container->get('app.runtime.renderer.default'));				
		}		
			 	  return $compiler;				
				break;
			case 'CommandCall' :
                    if(null === $this->_CommandCall){            
						if(!is_array($this->argv)){				
							$this->argv = [];   					
						}							      
						if ($this->isCLI() || isset($_SERVER['argv']) ) {	
							$this->argv = array_merge($this->argv, isset($_SERVER['argv']) ? $_SERVER['argv'] : []);       
						} 					
						$this->_CommandCall = new \Webfan\Webfat\Console\CommandCall($this->argv);
					}
				 return $this->_CommandCall;
                break;
		    case 'Console' :				
			case 'console' :
				if($this->hasContainer()
				 //  && $this->getContainer()->hasContainer('console') 
				   && $this->getContainer()->has('Console')){		
					return $this->getContainer()->get('Console');		
				}else{	      
					return new Console([
		             'BIN_PATH.PHP'=>(new \Webfan\Helper\PhpBinFinder())->find(),
		             // 'app_path' => [
		             //     __DIR__ . '/app/Command',
		             //   '@minicli/command-help'
		             // ],
		             'debug' => true,		   		
					], $this->getContainer() );				
				}
				break;
			default:
				if($this->hasContainer() && $this->getContainer()->has($name)){		
					return $this->getContainer()->get($name);		
				}
				
                 if(isset($this->{$name})){
					 return $this->{$name};
				 }
				
				 // throw new \InvalidArgumentException('Cannot magically __get('.$name.') in '.__METHOD__);
				 return null;
				break;
		}
	}
		
	
	
    public static function __callStatic($method, $params){
		$callable = false;
		
		if($this->isMethod($method, KernelFunctions::class)->static 
		    && ($this->isMethod($method, KernelFunctions::class)->valid || $this->isMethod($method, KernelFunctions::class)->public)){
		    $callable = [KernelFunctions::class, $method];
		}	
		
		
	  if(!\is_callable($callable) ){
		   if( 'static' === strtolower(substr($method, 0, strlen('static')))){
		    	$method = substr($method, strlen('static'), strlen($method));
		   }elseif( 'static' === strtolower(substr($method, strlen($method)-strlen('Static'), strlen($method)))){
		   	    $method = substr($method, 0, strlen($method)-strlen('Static') );
		   }
			
		   if(!is_callable($callable)){
		   	$callable = [self::mutex(), $method];
		   }
	   }
		
		
		if(is_callable($callable)){
		   return call_user_func_array($callable, $params);
		}
		
		throw new \Exception($method .' is not callable in '.__METHOD__);
	}
	
    public function __call($method, $params){
		 // if(false===$this->isBooted){
		 //   $this->boot();
		//  }
		
		$callable = false; 
		
		switch($method){
			case 'error' :
			case 'warning' :
			case 'notice' :
			case 'debug' :
			case 'info' :
			case 'critical' :
			case 'alert' :
			case 'emergency' :
				  array_unshift($params, $method);
				 if(count($params) < 3){
					$params[] = []; 
				 }
				 if(count($params) < 4){
					$params[] =  'default'; 
				 }			
				//  return \call_user_func_array([$this, 'log'], $params);
				//log(string $type, string $message, array $context = [], string $loggerName = 'default')
				   $callable = [$this, 'log'];
				break;
				default :
				   //continue...
				  $callable = false;
				 break;
		}
		
		if(false === $callable 
		   && $this->hasContainer() && $this->getContainer()->has(KernelHelper::class)
		   && (true === $this->isMethod($method, $this->getContainer()->get(KernelHelper::class))->valid 
			   || true === $this->isMethod($method, $this->getContainer()->get(KernelHelper::class))->public )){
			$callable = [$this->getContainer()->get(KernelHelper::class), $method];
		}elseif(false === $callable 
		   && ($this->isMethod($method, KernelHelper::class)->valid || $this->isMethod($method, KernelHelper::class)->public )){
			$callable = [new KernelHelper($this), $method];
		}
		
		
		if(false === $callable 
		   && ($this->isMethod($method, KernelFunctions::class)->valid || $this->isMethod($method, KernelFunctions::class)->public )){
		    $callable = [new KernelFunctions($this), $method];
		}
	
	if(false === $callable){	
		if($this->hasContainer() && $this->getContainer()->has(Maintenance::class)
		   && ( true === $this->isMethod($method, $this->getContainer()->get(Maintenance::class))->valid 
			   || true === $this->isMethod($method, $this->getContainer()->get(Maintenance::class))->public )){
			$callable = [$this->getContainer()->get(Maintenance::class), $method];
		}elseif($this->isMethod($method, Maintenance::class)->valid || $this->isMethod($method, Maintenance::class)->public ){
			$callable = [new Maintenance($this), $method];
		}		
	}
		
		
		if(is_callable($callable)){
			return call_user_func_array($callable, $params);
		}
		
		
		throw new \Exception($method .' is not callable in '.__METHOD__);
	}	
	
	
	
    public static function mutex(): AppInterface{
		foreach(self::$instances as $dir => $envs){
		  foreach($envs as $instance){
			return $instance;
		  }			
		}
	
	  return self::getInstance();
	}
	
    public static function getInstance(string $env = null, string $dir = null): self
    {
        $class = self::class;

        if(null ===$env){
           $env = 'dev';
        }

        $dir = (new $class($env, $dir))->findAppDir($dir, false);
        if(!isset(self::$instances[$dir])){
            self::$instances[$dir] = [];
        }

        if(!isset(self::$instances[$dir][$env])){
            self::$instances[$dir][$env] = new $class($env, $dir);
            self::$instances[$dir][$env]->findAppDir(self::$instances[$dir][$env]->getDir('app', true), true);
        }

	//	$res = &self::$instances[$dir][$env];
      //  return $res;
		return self::$instances[$dir][$env];
    }
	
	public function getWebUriBase() : string | bool {
		return $this->webUriBase;
	}
	
	public function getEnvFlag() : string {
		return $this->env;
	}
	
    public function getSources(string $userdir = null, $create = false) : array
    {
        if(null === $this->sources){
            $this->findAppDir($userdir, $create);
        }

        return $this->sources;
    }

    public function findAppDir(string $userdir = null, $create = false)
    {
        if(null===$userdir){
			
		//	if(substr(getcwd(), 0, strlen($_SERVER['DOCUMENT_ROOT']) ) !== $_SERVER['DOCUMENT_ROOT']){			
         //            trigger_error('Unexpected working directory in '.__METHOD__, \E_USER_WARNING);
		//	}
			
            $userdir = getcwd();
        }
        $dir = $this->FRDL_WORKSPACE;


        $pathFinderStageOneApp = \Phpactor\PathFinder\PathFinder::fromAbsoluteDestinations($userdir, [
                         'source' =>'<module>/<section>',
                         'legacy' =>  $_SERVER['DOCUMENT_ROOT'].'/../<module>/<section>/../..',
                         'blue' =>  $dir.'/apps/'.urlencode($this->getAppId()).'/deployments/blue/<module>/<section>',
                         'green' => $dir.'/apps/'.urlencode($this->getAppId()).'/deployments/green/<module>/<section>',
          ]);

        $pathFinderStageOneAppSuggestions = $pathFinderStageOneApp->destinationsFor('deploy/app');
        $pathFinderStageOneAppSuggestions['legacy' ] = $_SERVER['DOCUMENT_ROOT'].'/..';

        $pathFinder = \Phpactor\PathFinder\PathFinder::fromAbsoluteDestinations($userdir, [
                         'source' => 'config/<module>/<section>.php',
                         'dir' =>  $dir.'/config/<module>',
                         'file' => $dir.'/config/<module>/<section>.php',
          ]);

        $targetsAdmin = $pathFinder->destinationsFor('config/superadmin/superadmin.php');
        $this->sources['superadmin'] = $targetsAdmin;
		
      //  $domains = $pathFinder->destinationsFor('config/domains/domains.php');
     //   $this->sources['domains'] = $domains;		

        $pathFinderWebrootDir = \Phpactor\PathFinder\PathFinder::fromAbsoluteDestinations($userdir, [
                         'source' => '1.3.6.1.4.1.37553.8.1.8.8.11.6'.'/'. '<module>'.'/'.'<section>.php',
                         'dir' =>  $dir.'/'. '1.3.6.1.4.1.37553.8.1.8.8.11.6'.'/'. '<module>',
                         'file' => $dir.'/'. '1.3.6.1.4.1.37553.8.1.8.8.11.6'.'/'.'<module>'.'/'.'<section>.php',
          ]);

        $targetsWebrootDir = $pathFinderWebrootDir->destinationsFor(
                      '1.3.6.1.4.1.37553.8.1.8.8.11.6'.'/'.sha1(str_replace(getenv('HOME'), '', $_SERVER['DOCUMENT_ROOT'])).'/'.'app.php');
        $this->sources['webrootconfig'] = $targetsWebrootDir;

             $data = [
                'VERSION'=> sha1_file(__FILE__),
                'DOCUMENT_ROOT'=>[
                    'relative'=> str_replace(getenv('HOME'), '', $_SERVER['DOCUMENT_ROOT']),
                    'absolute'=> $_SERVER['DOCUMENT_ROOT'],

                ],
				'app' => [					
					//'initial' =>$this->getAppId(),
					//'main' => null,
					//'api'=>null,
					//'cdn'=>null,
					//'central'=>null,
					//'global'=>null,
				],
				'apps' => [
					//$this->getAppId() => [						
					//
					//],
				 ],
                'stage'=>'blue',
                'stages'=>$pathFinderStageOneAppSuggestions,
             ];


        if(true === $create && !is_dir($this->sources['webrootconfig']['dir'])){
            mkdir($this->sources['webrootconfig']['dir'], 0775, true);
        }

        $webrootconfig = file_exists($this->sources['webrootconfig']['file'])
                          ? require $this->sources['webrootconfig']['file']
                          : [
                             'VERSION'=> false,//sha1_file(__FILE__),
                          ];

        if(true === $create &&
             (
                    !file_exists($this->sources['webrootconfig']['file'])
                 || $webrootconfig['VERSION'] !== $data['VERSION']
             )
          ){
		//	$data = array_merge_recursive($webrootconfig, $data);
			
			$data = array_merge($webrootconfig, $data);
			
			if(!isset($data['app']['initial'])){
				$data['app']['initial'] = $this->getAppId();
			}
			
			if(!isset($data['apps'][$this->getAppId()])){
				$data['apps'][$this->getAppId()] = [];
			}
			
            $exp = var_export($data, true);
            $code = '<?php return '.$exp.';';

            file_put_contents($this->sources['webrootconfig']['file'], $code);
        }


        $webrootconfig = file_exists($this->sources['webrootconfig']['file'])
                          ? require $this->sources['webrootconfig']['file']
                          : $data;

        $this->sources['@runtime/webrootconfig'] = $webrootconfig;
		$stage = isset($this->context['stage']) && is_string($this->context['stage']) ? $this->context['stage'] : $webrootconfig['stage'];
        return $webrootconfig['stages'][$stage];
    }

    public function setStub(?StubHelperInterface $stubHelper = null) : self
    {
        $this->stubHelper=$stubHelper;
        return $this;
    }

    public function getStub(): ?StubHelperInterface
    {
        return $this->stubHelper;
    }

    public function getFile(string $path, string $type = null) : string
    {
        $dir = $this->getDir( $type, false );
        return rtrim($dir, '/\ ').\DIRECTORY_SEPARATOR
            .ltrim(str_replace(['/', '\\'], [\DIRECTORY_SEPARATOR,\DIRECTORY_SEPARATOR], $path), '/\ ');
    }

    public function scheme(string $appOrScheme) : string
    {
		switch($appOrScheme){
			case 'frdl' :
			case 'workspace' :
				$appOrScheme = 'frdl';
			  break;
			case 'web+fan' :
			case 'webfan' :
			case 'global' :
			case 'web+app' :
			case 'app' :
			case 'main' :
				$appOrScheme = 'webfan';
			  break;
			case 'web+site' :
			case 'website' :
			case 'site' :
				$appOrScheme = 'website';
			  break;
			case 'web+vhost' :
			case 'web+domain' :
			case 'vhost' :
			case 'domain' :
			case 'webhost' :
			case 'web+host' :				
			case 'host' :
				$appOrScheme = 'webhost';
			  break;
			case 'webuser' :
			case 'user' :
				$appOrScheme = 'webuser';
			  break;
			case 'config' :
			case 'webconfig' :
				$appOrScheme = 'webconfig';
			  break;
			default : 
				  throw new \Exception('Protocol '.$appOrScheme.' is not available!');
				break;				
		}		
		return $appOrScheme;
	}
	
	
    public function getAppIntentDir(string $appOrScheme, string $intent = null, $create = false) : string
    {
		$type = $intent;
		$appOrScheme = $this->scheme($appOrScheme);

        switch($type){
			case 'DOCUMENT_ROOT' :
			case 'app.config.webroot' :
			case 'app.config.DOCUMENT_ROOT' :
            case 'app.config.www' :
            case 'app.config.httpdocs' :
            case 'app.config.web' :
				 $sources = $this->getSources($this->dir, $create);
				 $dir = $sources['webrootconfig']['dir'];
				break;
			case self::GLOBAL :
	                $dir = 'webfan://';			
				break;
			case self::USERDATA :
            case 'app.config.userdata' :
            case 'var' :
			case 'data.users' :
				 $dir = $appOrScheme.'://userland/userdata/';	
				break;
		   case self::WEBSITES :
           case 'userdata.sites' :
           case 'vhosts' :
           case 'userdata.vhosts' :
            case 'app.config.websites' :
				  $dir = $appOrScheme.'://userland/websites/';	
               break;
		   case self::DOMAINS :
           case 'userdata.domains' :
           case 'vhosts.domains' :
           case 'config.domains' :
           case 'config.domains' :
           case 'hosts' :
           case 'app.config.hosts' :
				$dir = $appOrScheme.'://userland/domains/hosts/';	
               break;
           case '~' :
           case 'HOME' :
                  $dir = getenv('HOME');
               break;
           case 'WORKSPACE' :
           case 'WS' :
           case 'workspace' :
           case 'frdl' :
                  $dir = 'frdl://';		
               break;
           case 'modules' :
				$dir = $appOrScheme.'://modules/';	
               break;
          case 'app.public' :
          case 'app.www' :
          case 'app.httpdocs' :
          case 'app.web' :
				$dir = $appOrScheme.'://public/';	
               break;				
		/*
           case 'public' :
           case 'www' :
           case 'httpdocs' :
           case 'web' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'public'.\DIRECTORY_SEPARATOR;
               break;
			   */
           case 'assets' :
           case 'public.assets' :
           case 'app.public.assets' :
           case 'www.assets' :
           case 'httpdocs.assets' :
           case 'web.assets' :
           case 'app.web.assets' :
           case 'data.assets' :
           case 'web.files' :
           case 'files.static' :
				$dir = $appOrScheme.'://public/assets/';	
               break;
           case 'runtime' :
				$dir = $appOrScheme.'://runtime/';	
               break;
           case 'config' :
          // case 'runtime.config' :
				$dir = $appOrScheme.'://config/';	
               break;
           case self::MAIN_STATE_MUTEX :
           case 'runtime.state' :
				$dir = $appOrScheme.'://runtime/state/';	
               break;
           case self::MAIN_CONTAINER :
           case 'runtime.container' :
           case 'container' :
				$dir = $appOrScheme.'://runtime/container/';
               break;
           case 'runtime.cache' :
           case 'cache' :
				 $dir = $appOrScheme.'://runtime/cache/';
               break;
            case self::MAIN_EVENTS :
            case 'runtime.events' :
				 $dir = $appOrScheme.'://runtime/events/';
               break;
           case 'runtime.temp' :
           case 'temp' :
           case 'tmp' :
				 $dir = $appOrScheme.'://runtime/tmp/';
               break;
            case self::CIRCUIT_MAIN :
           case 'runtime.circuit' :
				 $dir = $appOrScheme.'://runtime/circuit/';
               break;
           case 'app':
                  $dir = $appOrScheme.'://';
               break;
           case 'logging' :
           case 'logs' :
           case 'log' :
				 $dir = $appOrScheme.'://logs/';
               break;
           default:
                 // $dir = $appOrScheme.'://'.$type.'/';
				$dir = $appOrScheme.'://';
               break;
           }		
		
	                
	    	if(true === $create && !is_dir($dir)){                 
			   mkdir($dir, 0775, true);                 
		    }	
		return $dir;
	}
	
	
	
	
    public function getDir(string $type = null, $create = true) : string
    {
        if(null === $this->dir){
          $d =     $this->findAppDir();
          $this->dir =     $d['dir'];
        }

        switch($type){
			case 'config' :
			case 'webconfig' :
				return rtrim($this->FRDL_WORKSPACE, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'config'.\DIRECTORY_SEPARATOR
                                                                   .$this->getAppId().\DIRECTORY_SEPARATOR;		
				
               break;
			case 'app.config.webroot' :
			case 'app.config.DOCUMENT_ROOT' :
            case 'app.config.www' :
            case 'app.config.httpdocs' :
            case 'app.config.web' :
				 $sources = $this->getSources($this->dir, $create);
				 return $sources['webrootconfig']['dir'];
				break;
			case self::GLOBAL :
	                return rtrim($this->FRDL_WORKSPACE, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'global'.\DIRECTORY_SEPARATOR
                                                                   .'app'.\DIRECTORY_SEPARATOR;			
				break;
			case self::USERDATA :
            case 'app.config.userdata' :
            case 'var' :
			case 'data.users' :
	                return rtrim($this->FRDL_WORKSPACE, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'.userdata'.\DIRECTORY_SEPARATOR
                                                                   .'data'.\DIRECTORY_SEPARATOR;			
				break;
			case self::WEBSITES :
           case 'userdata.sites' :
           case 'vhosts' :
           case 'userdata.vhosts' :
            case 'app.config.websites' :
                 return rtrim($this->FRDL_WORKSPACE, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'.websites'.\DIRECTORY_SEPARATOR
                                                                   .'sites'.\DIRECTORY_SEPARATOR;
               break;
		   case self::DOMAINS :
           case 'userdata.domains' :
           case 'vhosts.domains' :
           case 'config.domains' :
           case 'config.domains' :
           case 'hosts' :
           case 'app.config.hosts' :
                 return rtrim($this->FRDL_WORKSPACE, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'.domains'.\DIRECTORY_SEPARATOR
                                                                   .'hosts'.\DIRECTORY_SEPARATOR;
               break;
           case '~' :
           case 'HOME' :
                  return getenv('HOME');
               break;
           case 'WORKSPACE' :
           case 'WS' :
           case 'workspace' :
                  return $this->FRDL_WORKSPACE;
               break;
           case 'modules' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'modules'.\DIRECTORY_SEPARATOR;
               break;
          case 'app.public' :
          case 'app.www' :
          case 'app.httpdocs' :
          case 'app.web' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'public'.\DIRECTORY_SEPARATOR;
               break;				
		/*
           case 'public' :
           case 'www' :
           case 'httpdocs' :
           case 'web' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'public'.\DIRECTORY_SEPARATOR;
               break;
			   */
           case 'assets' :
           case 'public.assets' :
           case 'app.public.assets' :
           case 'www.assets' :
           case 'httpdocs.assets' :
           case 'web.assets' :
           case 'app.web.assets' :
           case 'data.assets' :
           case 'web.files' :
           case 'files.static' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'public'.\DIRECTORY_SEPARATOR
                                                                   .'assets'.\DIRECTORY_SEPARATOR;
               break;
           case 'runtime' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR;
               break;
           case 'runtime.config' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'config'.\DIRECTORY_SEPARATOR;
               break;
           case self::MAIN_STATE_MUTEX :
           case 'runtime.state' :
                 $dir = rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'state'.\DIRECTORY_SEPARATOR;

                  if(true === $create && !is_dir($dir)){
                    mkdir($dir, 0775, true);
                  }
                 return $dir;
               break;
           case self::MAIN_CONTAINER :
           case 'runtime.container' :
           case 'container' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'container'.\DIRECTORY_SEPARATOR;
               break;
           case 'runtime.cache' :
           case 'cache' :
                 $cacheDir = rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'cache'.\DIRECTORY_SEPARATOR;
				
				  $_ENV['FRDL_HPS_CACHE_DIR']=$cacheDir;
				  @putenv("FRDL_HPS_CACHE_DIR=".$cacheDir);
				return $cacheDir;
               break;
            case self::MAIN_EVENTS :
            case 'runtime.events' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'events'.\DIRECTORY_SEPARATOR;
               break;
           case 'runtime.temp' :
           case 'temp' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'tmp'.\DIRECTORY_SEPARATOR;
               break;
            case self::CIRCUIT_MAIN :
           case 'runtime.circuit' :
                 return rtrim($this->dir, '/\ ').\DIRECTORY_SEPARATOR
                                                                   .'runtime'.\DIRECTORY_SEPARATOR
                                                                   .'circuit'.\DIRECTORY_SEPARATOR;
               break;
           case 'app':
                 return $this->dir;
               break;
           default:
                 return $this->dir;
               break;
           }
    }




  
	
	public function log(string $type, string $message, array $context = [], string $loggerName = 'default'){
		$serviceId = 'logger.'.$loggerName;
		$context = array_merge($this->context, $context);
		
          $type = Logger::toMonologLevel($type);
		 /*
		if($this->hasContainer() && $this->getContainer()->has($serviceId) ){
			$this->getContainer()->get($serviceId)->log($type, $message, $context);
		}
		 */
		
		if($this->isMounted('frdl') 
		   && !LoggerRegistry::hasLogger($loggerName) && $this->hasContainer() && $this->getContainer()->has($serviceId) ){
			 LoggerRegistry::addLogger($this->getConnection('frdl', $serviceId), $loggerName, false);
		}
		if($this->isMounted('webfan') 
		   && !LoggerRegistry::hasLogger('webfan://'.$loggerName)
		   && $this->hasContainer() && $this->getContainer()->has('webfan://'.$serviceId) ){
			 LoggerRegistry::addLogger($this->getConnection('webfan', 'webfan://'.$serviceId), 'webfan://'.$loggerName, false);
		}
		if($this->isMounted('website') 
		   && !LoggerRegistry::hasLogger('website://'.$loggerName) 
		   && $this->hasContainer() && $this->getContainer()->has('website://'.$serviceId) ){
			 LoggerRegistry::addLogger($this->getConnection('website', 'website://'.$serviceId), 'website://'.$loggerName, false);
		}
		
        $type = Logger::toMonologLevel($type);
		
		if(LoggerRegistry::hasLogger($loggerName)){
			$logger = LoggerRegistry::getInstance($loggerName);		
			$logger->log($type, $message, $context);
		}
 
		if(LoggerRegistry::hasLogger('webfan://'.$loggerName)){
			$logger = LoggerRegistry::getInstance('webfan://'.$loggerName);		
			$logger->log($type, $message, $context);
		}
		
		if(LoggerRegistry::hasLogger('website://'.$loggerName)){
			$logger = LoggerRegistry::getInstance('website://'.$loggerName);		
			$logger->log($type, $message, $context);
		}
			
		//if($type > LogLevel::Notice && 'debug' !== $type){
		//	$this->devlog($message, $context);
		//}
		
	}

	public function devlog(string $message, $data = []){
	    
         $file = $this->devlogfile;
			
		$data = array_merge($this->context, $data);

		if(!file_exists($file)){
		 // touch($file);
			file_put_contents($file, "Log started: ".date("d.m.Y g:i A")."\n");
		}
                   $fp = fopen($file, 'a');			
			       fwrite($fp, sprintf('%1$s %2$s %3$s %4$s %5$s'.\PHP_EOL,
									   date("d.m.Y g:i A"), 
									   $_SERVER['REMOTE_ADDR'],
									   $_SERVER['SERVER_NAME'],
									   $message, 
									   json_encode($data)));
			       fclose($fp);
		

        //     $this->log('debug', $message, $data, 'default');
		 /*		   
  $ShutdownTasks = \frdlweb\Thread\ShutdownTasks::mutex();

           $ShutdownTasks(function($text, $logfile){
                   $fp = fopen($logfile, 'a');			
			       fwrite($fp, $text);
			       fclose($fp);
            }, sprintf('%1$s %2$s %3$s %4$s %5$s'.\PHP_EOL,
									   date("g:i A"), 
									   $_SERVER['REMOTE_ADDR'],
									   $_SERVER['SERVER_NAME'],
									   $message, 
									   json_encode($data)), 
						  $file);	
		
 */
		/*

           $ShutdownTasks(function($message, $data, $logfile){
                   $fp = fopen($logfile, 'a');			
			       fwrite($fp, sprintf('%1$s %2$s %3$s %4$s %5$s'.\PHP_EOL,
									   date("g:i A"), 
									   $_SERVER['REMOTE_ADDR'],
									   $_SERVER['SERVER_NAME'],
									   $message, 
									   json_encode($data)));
			       fclose($fp);
            }, $message, $data, $this->devlogfile);	
		*/	
	}	


	

	
    public function getPatchHtmlBodyAppend()
    {
        $html = '';



		
		if(isset($_GET['errorinfo']) && isset($_GET['instance'])){
			 
			
			$html.="<frdlweb-terminal commands=\"['@webfan3/components/webfat-terminal-commands/frdl', '@webfan3/components/webfat-terminal-commands/misc', '@webfan3/components/webfat-terminal-commands/webfat']\" terminal-config=\"webfat\" style=\"text-align:left;\"></frdlweb-terminal>";
		}
 //frdl-fade-speed="100"
			$footer = (null !== $this->container && $this->container->has('website.pageview.footer'))
				? $this->container->get('website.pageview.footer') 
				: '
 <div style="display:inline-block;float:bottom;width:auto;bottom:0px;margin:5px;" frdl-if-js-fadeout="30000" frdl-fade-speed="10000">					
			
<div ng-show="langIsDefault==true || langShortCode==\'en\'">
This is ALPHA Version of the installer! If you get this as your default-Template and want to install or use another system on this host, please delete this (index.php, webroot files and/or .frdl directory). If you want to continue to use this, we will guide you step by step. Just use the wizards on the next pages or <a href="https://webfan.de/apps/marketplaces/12/support.html">contact the support</a> if you need help further! 
</div>

<div ng-show="langShortCode==\'de\'" ng-cloak>
Dies ist die ALPHA-Version des Installers! Wenn Sie dies als Standard-Template erhalten und ein anderes System auf diesem Host installieren oder verwenden möchten, löschen Sie dieses bitte (index.php, Webroot-Dateien und/oder .frdl-Verzeichnis). Wenn Sie dies weiterhin verwenden möchten, werden wir Sie Schritt für Schritt anleiten. Verwenden Sie einfach die Assistenten auf den nächsten Seiten oder <a href="https://webfan.de/apps/marketplaces/12/support.html">wenden Sie sich an den Support</a>, wenn Sie weitere Hilfe benötigen! 
</div>

'.(null !== $this->container && $this->hasRoute('webmaster.dashboard') ? '
<div>
	<p>
	  <a href="'.($this->container->get('router')
   ->getNamedRoute('webmaster.dashboard')
   ->getPath([
	   'module' => 'welcome',
	   'path' => 'index.html',
   ])).'">
	   Got to Admin Setup
	  </a>
	</p>
</div>
'
   
	 : ''
					
).'
</div>
';

        return $html.$footer;
    }

	
	//$route = $router->getNamedRoute('actionOne');
	//$route->getPath(); // "/admin/acme/route1"
	public function hasRoute(string $name) : bool 
	{
		$router = null !== $this->container && $this->container->has('router') 
			? $this->container->get('router') 
			: false;
      
		 if(false === $router){
		   return false;	 
		 }
		try{
			return is_string( $router->getNamedRoute($name) ->getPath() );
		}catch(\Exception $e){
		   return false;	
		}
			
	}

//https://github.com/smarty-php/smarty/blob/v4.3.0/docs/programmers/api-functions/api-fetch.md
//https://github.com/miroshnikov/jsmart/blob/master/test/templates/javascript.tpl
    public function getPatchHtmlHeadAppend()
    {
        $html = '';

        /*
        $html.='<script src="/assets/!bundle/run/abcdef1234567890-fj/@webfan3/frdlweb/webfan-website.js" data-webfan-config-query="DEBUG.enabled=false&website.consent.ads=false" async="defer"></script>';
        */
		        $html.="<base href=\"".$this->webUriBase."\" />";
		
		
	//	if(isset($_GET['errorinfo']) && isset($_GET['instance'])){		
		
	$dataJSON = json_encode([
		  'HTTP_HOST' => $_SERVER['HTTP_HOST'],
		], \JSON_PRETTY_PRINT);
		

			$html.= <<<JSSCRIPT
<script>
window.WebfanWebmaster = window.WebfanWebmaster || {};
window.WebfanWebmaster.modules = window.WebfanWebmaster.modules || {};
window.WebfanWebmaster.modules.AdminAppClient = $dataJSON;
window.WebfanWebmaster.modules.User = false;
</script>
JSSCRIPT;		
// }
		
		$cdn = null !== $this->container && $this->container->has('website.urls.cdn')
			? $this->container->get('website.urls.cdn')
			: 'https://cdn.startdir.de';
		
        $html.=
        "<style>[ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak{\tdisplay:none;}</style>\n<script>\n((q, w,d)=>{\nvar s=d.createElement('script');\ns.setAttribute('src', 'https://cdn.startdir.de/webfan.js?cdn=".$cdn
			."&?' + q);\t\ns.async='true';\ns.onload=()=>{\n\twindow.frdlweb.ready(async()=>{
		  (await require('frdlweb'))
                .Webfan.EventEmitter.DEFAULT.once('ready:frdlweb.modules.Terminal', () =>{
                    window.frdlweb.modules.Terminal.exec('webfat-cli-url '
                             + window.location.protocol + '//' + window.location.host + window.location.pathname
                    );
                 })
          ;		
		});\n};\nd.head.prepend(s);\t\t\n})('"
		        //'website.app.injector="
			//   .urlencode('https://io4.xyz.webfan3.de/assets/@webfan3/website/app/webfan-webfat-qqq')
			 //  ."&website.consent.ads=false&angularjs.ngAppModule.name="
			//toQuery(array | \object $data)
			//."website.consent.ads=false&angularjs.ngAppModule.name="
			
			/*
			.((isset($_GET['errorinfo']) && isset($_GET['instance']))
			 // ? 'webfan-webmaster' 
			  ? 'webfan-webfat' 
			  : 'webfan-webfat'
			 )
			 */
		  .	(
			   null !== $this->container && $this->container->has('website.js.cfg.webfan-website')
			   ? $this->toQuery( $this->container->get('website.js.cfg.webfan-website') )
			   : 'website.consent.ads=false&angularjs.ngAppModule.name=webfan-webfat&requirejs.deps[]='
			                .urlencode('@frdl/apps/webfan-webfat')
			)
		 ."', window, document);\t\n</script>\n"	
		;
		
	    return $html;
    }

	
	
/* https://stackoverflow.com/questions/12433958/how-to-parse-response-headers-in-php
// Get any header except the HTTP response...
function getResponseHeader($header, $response) {
  foreach ($response as $key => $r) {
     // Match the header name up to ':', compare lower case
     if (stripos($r, $header . ':') === 0) {
        list($headername, $headervalue) = explode(":", $r, 2);
        return trim($headervalue);
     }
  }
}
// example:
echo getResponseHeader("Content-Type");
// text/html; charset=utf-8

// Get the HTTP response code
foreach ($response as $key => $r) {
  if (stripos($r, 'HTTP/') === 0) {
    list(,$code, $status) = explode(' ', $r, 3);
    echo "Code: $code, Status: $status";
    break;
  }
}

foreach ($response->getHeaders() as $name => $values) {
    echo $name . ': ' . implode(', ', $values) . "\r\n";
}
*/
	





    public function patch_ob_handler($content)
    {
		$initialContent = $content;
		
		if($this->isCLI()){
			return $content;
		}
		
		$contentType = $this->getResponseHeader("Content-Type");
		if(	false!==$contentType && 'text/html' !== explode(";", $contentType, 2)[0]){
			return $content;
		}
		
		  $compiler = $this->HTMLComponentsCompiler;
		
	//    $content = $compiler->process($content);
 		    
		if(($this->isSessionStarted() || isset($_COOKIE[$this->sessionName])) && $this->flash()->hasMessages()) { 
				    $this->global()->page->html->body.=
                    	'<div style="display:inline-block;width:auto;margin:10px;">';
					  $this->global()->page->html->body.= $this->flash()->display(null, false, true); //all types no verbose
				   $this->global()->page->html->body.=
					   '</div>';			
		}		
		
		/*		
     //   $dom = new HTML5DOMDocument();
		$documentPrototype = $this->HTMLDOcument;
		$HTMLDOcument = $documentPrototype([
			'content' => $content,
			'compiler' => $compiler,
			'DocType' => '<!DOCTYPE html>',
		]);

		$HTMLDOcument = $this->Document;*/
	//	$dom = $HTMLDOcument->doc();
      //  $dom->substituteEntities = false;		
		
		//if('<!DOCTYPE html>' !== substr($content, 0, strlen('<!DOCTYPE html>'))){
		/* 	
            $strtpl = "<!DOCTYPE html><html><head><title>Webfan Webf.at Framework Setup</title><meta name=viewport content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=yes\"><meta http-equiv=\"Content-type\" content=\"text/html; charset=UTF-8\" /><meta http-equiv=\"Content-Language\" content=\"en,de\">    <meta name=\"robots\" content=\"index, follow\" /><meta name=\"keywords\" content=\"php,cms,framework,webfan\" /><meta name=\"description\" content=\"Webfan Webf.at Framework\" /></head><body>%s</body></html>";
           $content=sprintf($strtpl, $content);
		   */
         //  $strtpl = "<!DOCTYPE html>%s";
          // $content=sprintf($strtpl, $content);			
       // }
		
		
	 //   $dom->loadHTML($content, HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
		
             $HTMLDOcument = $this->Document;
             $HTMLDOcument->load($content);
		
		

		if(is_array($this->global()->page->languages) && 0 <count($this->global()->page->languages)){
			$this->global()->page->html->head .= '
			  <meta http-equiv="Content-Language" content="'.implode(',', array_keys($this->global()->page->languages)).'">	 
			';
		}

		$this->global()->page->html->head .= '
          <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=yes">
		  <meta http-equiv="Content-type" content="text/html; charset=UTF-8" />';
		

		$this->global()->page->html->head .= $this->getPatchHtmlHeadAppend(); 
		

		//$mainUiView = $dom->querySelector('[ui-view]');
		$mainUiView = $HTMLDOcument->doc()->querySelector('[ui-view]');
        if(!$mainUiView){
			$mainUiViewWrapStart='<!-- Main ui-view added in '.__METHOD__.' '.__LINE__.' --><div ui-view>';
			$mainUiViewWrapEnd='</div>';
		}else{
			$mainUiViewWrapStart='<!-- Main ui-view found in '.__METHOD__.' '.__LINE__.' -->';
			$mainUiViewWrapEnd='';			
		}
		
       //  $body = $dom->querySelector('body');
		$body = $HTMLDOcument->doc()->querySelector('body');
         if($body){
			 $oldBody = $body->innerHTML;
             $body->innerHTML =
				  $mainUiViewWrapStart
				   .$oldBody
				//   .$this->getPatchHtmlBodyAppend()
				// .$this->global()->page->html->body
				 .$mainUiViewWrapEnd
				 ;
			// $this->global()->page->html->body = '';
         }else{
	             $this->global()->page->html->body = ''
			        .$mainUiViewWrapStart 
					 .$initialContent
					//  .$this->getPatchHtmlBodyAppend()
				      .$this->global()->page->html->body
				   .$mainUiViewWrapEnd
				 ;		
			 }

		


		//$this->global()->page->html->footer.=$this->getPatchHtmlBodyAppend();



        // $footer = $dom->querySelector('footer');
		$footer = $HTMLDOcument->doc()->querySelector('footer');
         if($footer){
			 $oldFooter = $footer->innerHTML;
             $footer->innerHTML =
				  $oldFooter
			       .$this->global()->page->html->footer
				  .$this->getPatchHtmlBodyAppend()
				 ;
			// $this->global()->page->html->footer = '';
         }else{
			 
               $this->global()->page->html->body.= '
		            <footer style="display:inline-block;float:bottom;width:auto;bottom:0px;margin:5px;">
                      '.$this->global()->page->html->footer
				       .$this->getPatchHtmlBodyAppend()
				   .'	
		            </footer>
                ';
			 
			//   $this->global()->page->html->footer = '';
			 }
		

		
		//$dom->insertHTML('
		$HTMLDOcument->write('
    <html>
        <head>
          '.$this->global()->page->html->head.'
        </head> 	
        <body>
          '.$this->global()->page->html->body.'	
        </body> 
    </html>
');			
		


     //    $content = $dom->saveHTML();	
	//	$content = $compiler->process($content);
		



		// Error : ob in ob handler !? $content = $HTMLDOcument->compile();
		$content = $HTMLDOcument->compile();
		return $content;
    }



    public function reboot(): AppInterface
    {
        $this->close();
        return $this->boot();
    }




	public function isSessionStarted() : bool
	{
       if ($this->isCLI()){
         return false;
	   }
		
        if (version_compare(phpversion(), '5.4.0', '>='))
        return session_status() === \PHP_SESSION_ACTIVE;

       return session_id() !== '';
	}
	
	public function session_start(string $session_name = 'WEBFATSESSION'){
		if (!$this->isCLI() && !$this->isSessionStarted()) {  
			session_name($session_name);  
			//session_set_cookie_params($cookie_options);   
			session_start();
		}
	}
	
	


    public function onError($number = null, $message = null, $file = nulle, $line = null, $errcontext = null)
    {
        return $this->err_handler($number, $message, $file, $line, $errcontext);
    }

    public function err_handler($errno = null, $errstr = null, $errfile = null, $errline = null, $errcontext = null)
    {
		
        $error_is_enabled = (bool)($errno & ini_get('error_reporting') );

		  $logType = 'error';
          $exit = false;
		
            $l = error_reporting();
            if ( $l & $errno ) {                
                switch ( $errno ) {
                    case \E_USER_ERROR:
                        $type = 'Fatal Error';
                        $exit = true;
						$logType = 'error';
                    break;
                    case \E_USER_WARNING:
                    case \E_WARNING:
                        $type = 'Warning';
						$logType = 'warning';
                    break;
                    case \E_USER_NOTICE:
                    case \E_NOTICE:
                    case @\E_STRICT:
                        $type = 'Notice';
						$logType = 'notice';
                    break;
                    case @\E_RECOVERABLE_ERROR:
                        $type = 'Catchable';
                    break;
                    default:
						$logType = 'error';
                        $type = 'Unknown Error';
                        $exit = true;
                    break;
                }

                $exception = new \ErrorException($type.': '.$errstr, 0, $errno, $errfile, $errline);

                if ( $exit ) {
                     $this->exception_handler($exception);
                    if( $this->isCLI() ){
						//	exit($errstr);
					echo $errstr;
					}else{
					   //	 die($errstr);	
					echo $errstr;
					}
                }else{
                      if( in_array($errno, [\E_USER_ERROR, \E_RECOVERABLE_ERROR]) && $error_is_enabled ) {
						 // $this->devlog(sprintf("%s in %s line %s", $errstr, $errfile, $errline));
						   $this->log($logType, sprintf("%s in %s line %s", $errstr, $errfile, $errline) );
                           //throw $exception;
						     $this->exception_handler($exception);
						// throw $exception;
                      }
                }
            }
        return false;
    }

    public function exception_handler($exception)
    {
		$file_paths = debug_backtrace();
       $trace = '';//print_r(debug_backtrace(), true);

		$show = 'dev' === $this->env;
		$show=true;
		
        if(is_object($exception) && ($exception instanceof \Webfan\Webfat\App\ResolvableException 
		   || $exception instanceof \Webfan\Webfat\App\ResolvableLogicException)){
                self::$messages[]=$exception;
               //    $log = $exception->html(-1);
			     $log = $exception->getMessage() . " " . $exception->getTraceAsString(); //. \PHP_EOL;
                 $out =  $exception->html(-1);
			      $this->log('error', $log);
			  $show = true;
          }    elseif(is_object($exception) && ($exception instanceof \Exception)) {
                 $log = $exception->getMessage() . " " . $exception->getTraceAsString();// . \PHP_EOL;
		     //	$this->devlog($log);
			   $this->log('error', $log);
               $out = $exception->getMessage();			  
          } else{
			 $log = sprintf("%s %s", $exception->getMessage(), $exception->getTraceAsString());
			 $out = 'An error occured! '.$exception->getMessage();
			//$this->devlog(sprintf("%s %s", $exception->getMessage(), $exception->getTraceAsString()));
			 $this->log('error', $log);
		}

            if ( ini_get('log_errors') ){
                error_log($log, 0);
            }



            if($show){
               // print("Unhandled Exception" . " - $log");
                //print($out);
                echo $out.$trace;
            }else{
			   echo 'An error occured! '.$exception->getMessage().$trace;
			}

		
		foreach($file_paths as $file_path) { 
			foreach($file_path as $key => $var) {    
				if($key == 'args') {     
					foreach($var as $key_arg => $var_arg) {      
						echo $key_arg . ': ' . $var_arg . '<br>';    
					}
				} else {  
					echo $key . ': ' . $var . '<br>';  
				}   
			}
		}
		
    }
	

	

	
    public function setPhpHandlers(string $case = null)
    {
		$me = &$this; 
		
		
				if(!isset($this->_done['SpatieCache::getInstance()->enable()']) 
				   && 'once' !== $case 
				   && 'all' !== $case
				   && '*' !== $case 
				   && null !== $case ){   
                     $this->setPhpHandlers('once');  
				}
		
		switch($case){				
			case 'ob_start' :   
				if(!$this->isCLI()){
				  self::once(function () use (&$me) { 
					if( !$me->isCLI() ) {					
				    	ob_start([$me, 'patch_ob_handler']);	      
					}
				  });
				}
              break;		
			case 'timezone' : 
                   \Webfan\Patches\Start\Timezone::defaults( );
              break;		
			case 'once' : 
				 $this->_done['SpatieCache::getInstance()->enable()'] = true;
                 SpatieCache::getInstance()->enable();	
              break;		
			case 'shutdowns' : 
					$me->setPhpHandlers('shutdown_trim_log');				
              break;		
			case 'shutdown_trim_log' :      
				$logfile = $this->devlogfile;
				self::once(function () use ($logfile) {	    
					$ShutdownTasks = \frdlweb\Thread\ShutdownTasks::mutex();          
					$ShutdownTasks(function($logfile){			 
						if(file_exists($logfile)){			
							Kernel::trim_log_to_length($logfile,2,1024);	 
						}           
					}, $logfile);	        
				});                 
              break;		
			case 'errors' : 			
				if(!isset($this->_done['exception_handler']) || !isset($this->_done['error_handler']) ){			
					$this->setPhpHandlers('exception_handler');				
					$this->setPhpHandlers('error_handler');					 
				} 
				 ini_set('log_errors', true);        
				ini_set('display_errors', $this->getEnvFlag() === 'dev' ||  $this->isCLI() ? '1' : '0');      
				error_reporting(\E_ERROR | \E_WARNING | \E_PARSE);
              break;			
			case 'error_handler' : 							
				if(!isset($this->_done['set_error_handler']) ){
					$this->_done['set_error_handler'] = true;
                    set_error_handler([$this, 'onError']);	
				 }					
              break;		
			case 'exception_handler' : 
				if(!isset($this->_done['set_exception_handler']) ){
					$this->_done['set_exception_handler'] = true;
                  \set_exception_handler( [$this, 'exception_handler'] );
				}
              break;	
			case 'start' :                  
				$this->sessionName = 'TILLSESSION';
		\Webfan\Webfat\App\ResolvableException::$urlformtemplate
			= $this->webUriBase.'1.3.6.1.4.1.37553.8.1.8.8.91397908338147/admin/error/resolver/?instance=%2$s&errorinfo=%1$s';		
			
		\Webfan\Webfat\App\ResolvableLogicException::$urlformtemplate
			= $this->webUriBase.'1.3.6.1.4.1.37553.8.1.8.8.91397908338147/admin/error/resolver/?instance=%2$s&errorinfo=%1$s';				
				
              break;
			case 'all' :                  
				 if(!isset($this->_done['SpatieCache::getInstance()->enable()']) ){
                   $this->setPhpHandlers('once');
				 }
                 $this->setPhpHandlers('start');
				 $this->setPhpHandlers('errors');
				 $this->setPhpHandlers('ob_start');
                 $this->setPhpHandlers('timezone');
				 $this->setPhpHandlers('shutdowns');
              break;
			case '*' : 
			case null :
		    default : 
                   $this->setPhpHandlers('all');
				break;
		}
		
		
    }	
	



/*
    protected function setShutdownHandlers()
    {
        $ShutdownTasks = \frdlweb\Thread\ShutdownTasks::mutex();

           $ShutdownTasks(function(AppInterface &$app = null){
                 call_user_func_array([$app, 'shutdown'], $contextArgs);
            }, $this);

          $ShutdownTasks(function(AppInterface &$app = null) {
                  $data = \error_get_last();
                   if (is_array($data)) {
                       // $output = ob_end_clean();
                        $weid = 'weid:root:2-RR-2';
                      // echo  $output.'<notice frdl-notice-view="'.$weid.'">';
                        echo  '<notice frdl-notice-view="'.$weid.'">';
                        echo 'Error occurred! - ' . $data['message']
                            .' - ' . $data['file']
                            .' - ' . $data['line']
                            .'<br />'
                          //  .print_r(self::$messages, true)
                            ;
                       echo '</notice>';

                       echo '<script src="https://cdn.startdir.de/!bundle/run/122-8-abcdef0123456789-20220827-dhzdrf/@webfan3/frdlweb/webfan-website.js"></script>';


                    //   echo $output;
                    }


			  
           }, $this);
    }
*/
    public function shutdown()
    {
        $this->close();
    }

    public function __destruct()
    {
        $this->close();
    }

    public function close()
    {
        $this->isBooted = false;
        $this->container = null;
        if(isset($this->appStateShare[self::MAIN_STATE_MUTEX])){
           try{
             $this->appStateShare[self::MAIN_STATE_MUTEX]->unlock();
           }catch(\Exception $e){
               //silent, not critical
           }
        }
        $this->appStateShare=[];
        $this->appStateStorage=[];
        $this->circuit=[];
        $this->circuitStorage=[];
        $this->context=[];
    }


        
	
	protected function _boot( ): AppInterface|\ErrorException
    {
        $me = &$this;
         if(false!==$this->isBooted){
          // $e = new \ErrorException('Kernel cannot boot twice, unless you use the reboot method!', \E_USER_ERROR, 0, __FILE__, __LINE__);
           //  return $e;
			 return $this;
         }

    
		$this->isBooted = true;
		

		

		if($this->CommandCall->hasParam('host')){
			$host = $this->CommandCall->getParam('host');
		    $_SERVER['HTTP_HOST'] = $host;
			$this->context([
				'host' => $host,
			]);
		}		

        if ($this->isCLI() || isset($_SERVER['argv']) ) {
               if(!is_array($this->argv)){
				 $this->argv = [];   
			   }
			$this->argv = array_merge($this->argv, $_SERVER['argv']);
        } 
		
		


	//	$this->setPhpHandlers('start');
	//	$this->setPhpHandlers('errors');
		 // ob_start([$this, 'patch_ob_handler']);	  
		
		if('.frdl' === basename($this->FRDL_WORKSPACE) && !is_dir($this->FRDL_WORKSPACE) ){
			mkdir($this->FRDL_WORKSPACE, 0775, true);
		}
 
		if(is_dir($this->FRDL_WORKSPACE) && !is_writable($this->FRDL_WORKSPACE)  ){
			chmod($this->FRDL_WORKSPACE, 0775);
		}		

		if(!is_dir($this->FRDL_WORKSPACE) || !is_readable($this->FRDL_WORKSPACE) || !is_writable($this->FRDL_WORKSPACE) ){
		        throw new ResolvableException(
		                 'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.2=No FRDL WORKSPACE set!'
		                   .'|php:'.get_class($this).'=Thrown by the Kernel Class'
		                   .'@No FRDL WORKSPACE'

		                 );			
		}

		$this->mountDir('frdl', $this->FRDL_WORKSPACE, false);	
		$tempDir = rtrim($this->FRDL_WORKSPACE, '\\/ ').\DIRECTORY_SEPARATOR.'tmp'.\DIRECTORY_SEPARATOR;
		if(!is_dir($tempDir)){
		  mkdir($tempDir, 0777, true);	
		}else{
		  chmod($tempDir, 0777);	
		}
		putenv(sprintf('TMPDIR=%s', $tempDir));
		$_ENV['TMPDIR'] = $tempDir;		
		//$this->mountDir('webtemp', $tempDir, false);	
		
		//$this->mountDir('webfan', $this->getDir('app', true), false);
		$this->mountDir('webfan', $this->getDir('app', true), true);
		

		if(!is_dir($this->getDir('config', true))){
		  mkdir($this->getDir('config', true), 0775, true);	
		}else{
		  chmod($this->getDir('config', true), 0775);	
		}
		$this->mountDir('webconfig', $this->getDir('config', true), false);		

	//	$this->setPhpHandlers('*');	  
           
	//	$this->loadEnvVars([$this->FRDL_WORKSPACE]);
	
		 ob_start([$this, 'patch_ob_handler']);	  

		 
          if( !$this->isCLI() && filemtime(__FILE__) > time() - 6){
		           $this->flash()->info( $this->getFormFromRequest(
					  '<span class="btn-success">The library ('.\get_class($this).') was rewritten - The page reloads automatically</span>', 
											 null, true, 7)
						);
					
					if(!$this->isCLI()){
						$this->end();
					}
		  }
		
    
		 if(!isset($this->main('state')->specials)){
            $this->main('state')->specials = [];
		 }
 
		



	if(!$this->isCLI() &&
	    isset($_SERVER['DOCUMENT_ROOT']) && 
	    is_dir($_SERVER['DOCUMENT_ROOT']) && 
	   !file_exists($_SERVER['DOCUMENT_ROOT'].\DIRECTORY_SEPARATOR.'.htaccess')){		 
	//	$htaccessDefault = file_get_contents('https://raw.githubusercontent.com/frdlweb/webfat/main/public/.htaccess?cache-bust='.time());
			$htaccessDefault =$this->loadFromUrlForCache(
				'https://raw.githubusercontent.com/frdlweb/webfat/main/public/.htaccess?cache-bust='.time(),
				null, null, 'txt', 60, 
														null/*'application/json, application/x-www-form-urlencoded;q=0.9, * / *;q=0.8'*/,
													   null,
													   null);	
		if(!file_put_contents($_SERVER['DOCUMENT_ROOT'].\DIRECTORY_SEPARATOR.'.htaccess', $htaccessDefault)){
		   $this->webUriBase .= 'index.php/';	
		}else{
		   chmod($_SERVER['DOCUMENT_ROOT'].\DIRECTORY_SEPARATOR.'.htaccess', 0777);
		}

		if(!$this->isCLI()){			     
		           $this->flash()->info( $this->getFormFromRequest(
							  '<span class="btn-success">circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5 - Resolved automatically</span>', 
											 null, true, 5)
						);	
				
					
			$this->end();				
		}
	}
										
					
	        



			  
                  if(!$this->isCLI() &&	   
					 isset($_SERVER['DOCUMENT_ROOT']) && 	    
					 is_dir($_SERVER['DOCUMENT_ROOT']) && 	   
					 !file_exists($_SERVER['DOCUMENT_ROOT'].\DIRECTORY_SEPARATOR.'.htaccess')){
                       $this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5'] 
						     = false;
						 $this->flash()->warning( (new ResolvableException(
                         'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5=Invalid .htaccess file'
                           .'|php:'.get_class($this).'=Thrown by the Kernel Class'
                           .'@Your .htaccess file is missing'
                            ))->html(-1)
                         );              
												 
					  
					 // die($this->webUriBase);
                          $this->webUriBase .= 'index.php/';


				  }elseif(!$this->isCLI() ){
					  if(isset($this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5'])
						    && true === $this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5']){
						   unset($this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5']);
					   }else{
						   $this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.5'] = true;
					   }
				  }
			 


		/*	
                  try{
                       $container = $this->getContainer();
					   if(isset($this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7'])
						    && true === $this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7']){
						   unset($this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7']);
					   }else{
						   $this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7'] = true;
					   }
					   
                  }catch(\Exception $e){
					   $this->main('state')->specials['circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7'] = 
                        new ResolvableException(
                         'circuit:1.3.6.1.4.1.37553.8.1.8.8.1958965301.4.7=Could not build container'
                           .'|php:'.get_class($this).'=Thrown by the Kernel Class'
                           .'@'.$e->getMessage()

                         );
                  }		

	  */  
           $container = $this->getContainer();
  	       
		  $stirb = false;
		if(!$this->isCLI() ){
          foreach($this->main('state')->specials as $id  => $special){
			  if(is_object($special) && ($special instanceof ResolvableException || $special instanceof ResolvableLogicException )){
				   $this->flash()->error(  'ERROR: Not resolved: '.$id.'<br />'.$special->html(-1) );
				  $stirb = true;
			  }elseif(is_object($special) && ($special instanceof \Exception )){
				   $this->flash()->error( 'ERROR: Not resolved: '.$id.'<br />'.$special->getMessage() );
				  $stirb = true;
			  }elseif(is_string($special)){
				   $this->flash()->info( 'INFO: '.$id.'<br />'.$special );
			  }elseif(is_bool($special) && true !== $special){
				   $this->flash()->warning( 'WARNING: Not resolved: '.$id );
			  }elseif(is_bool($special) && true === $special){
				   $this->flash()->success( 'Resolved: '.$id );
				   unset($this->main('state')->specials[$id]);
			  }elseif(!is_bool($special) || true !== $special){
				   $this->flash()->warning( 'WARNING: Not resolved: '.$id.'<br />'.print_r($special, true) );
			  }
		  }
	
		  $this->main('state')->specials = $this->main('state')->specials;


		}//!$this->isCLI() 

		
	if(!$this->isCLI()){		
		foreach($this->getContainer()->get('app.runtime.schemes.required') as $appOrScheme){  
			if($this->isMounted($appOrScheme) && $this->isLockedByMaintenances($appOrScheme)){    
				$this->flash()->warning(
					sprintf('There are current (configuration-) maintenances for <strong>%s%s</strong>',
							$appOrScheme.'://',
							$_SERVER['HTTP_HOST']
						   )
				);
				$this->global()->page->html->body .=								
					$this->flash()->getMessageHtml(
					   sprintf('There are current (configuration-) maintenances for <strong>%s%s</strong>',
							$appOrScheme.'://',
							$_SERVER['HTTP_HOST']
						   ), 
					'error', 
					false)
					.$this->flash()->getMessageHtml(
					sprintf('<h2>Pending maintenances for <strong>%s%s</strong></h2>%s',
							$appOrScheme.'://',
							$_SERVER['HTTP_HOST'],
							$this->getMaintenancesHtml($appOrScheme, true, true)
						   ), 
					'warning', 
					false);
			}elseif($this->isMounted($appOrScheme) && !$this->isLockedByMaintenances($appOrScheme)){    
				$this->global()->page->html->body .= $this->flash()->getMessageHtml(
					sprintf('<h2>Running maintenances for <strong>%s%s</strong></h2>%s',
							$appOrScheme.'://',
							$_SERVER['HTTP_HOST'],
							$this->getMaintenancesHtml($appOrScheme, true, true)
						   ), 
					'info', 
					false);
			}elseif(!$this->isMounted($appOrScheme)){
				$this->flash()->warning(
					sprintf('The resource for <strong>%s%s</strong> is not mounted!',
							$appOrScheme.'://',
							$_SERVER['HTTP_HOST']
						   )
				);				
			}
		}// foreach schemes
	}//!$this->isCLI()	

		
            if(!$this->isCLI() && isset($this->main('state')->lastSetupLockTime) 
			    && $this->main('state')->lastSetupLockTime > 0
			    && $this->main('state')->lastSetupLockTime < time() - 30){
				$this->flash()->warning(
					sprintf('Setup is running for <strong>%s</strong>',
							$this->getAppId()
						   )
				);																   
			}

          if(!$this->isCLI() && true===$stirb){			                
			//  $this->end();
		  }
		
            $this->main('state')->hit = time();

        return $this;
    }
	



    public function boot(): AppInterface
    {
        if(false===$this->isBooted){
            $this->_boot();
			$this->isBooted = true;
        }
        return $this;
    }

 

    public function handleCliRequest()
    {
		$this->boot();
		

		$args = null === $this->argv || !is_array($this->argv) 
			? (isset($_SERVER['argv']) ? $_SERVER['argv'] : [] ) 
			: $this->argv;
		
 
	 
		$this->terminate();
		$Console = &$this->Console;
       return $Console($args);
    }

	
	
	public function exec(string | array $args, bool $needResultCode = true, bool $runAsScript = false){				
		    if(!is_array($args)){					
				$args = preg_split("/\s+/m", $args);				
			}			
           
		     $this->boot();		

             if(!is_array($this->argv)){
				 $this->argv = [];   			
			 }
		
		      $this->argv = array_merge($this->argv,  $args);
		
		    //  if(!$this->CommandCall->hasParam('host')){
			//	  $this->argv = array_push($this->argv, '--host='.$this->context()['host']);
			//  }

		      if ( $this->isCLI() ) {
				 return $this->handleCliRequest();
			  }
		
				
		$Console = &$this->Console;				
		$this->terminate();		
			 

	  return true === $runAsScript
		   ? $Console->runScript($this->argv, null, null, $needResultCode)
		   : $Console($this->argv);
	}



    public function handleHttpRequest(ServerRequestInterface $request = null): ?ResponseInterface
    {
		$this->boot();

        if(null === $request){
			$request = $this->hasContainer() && $this->getContainer()->has('request') 
				? $this->getContainer()->get('request') 
				: ServerRequest::fromGlobals();
        }
	
	
		$origin = $request->getHeader('Origin');
 

	if( $this->hasContainer() && $this->getContainer()->has('router') ){	
		try{
		  $router = $this->getContainer()->get('router');
		  $response = $router->dispatch($request);
		}catch(\League\Route\Http\Exception\NotFoundException $e){
		     $response = new Response(404);
             $response =  $response->withBody(\GuzzleHttp\Psr7\Utils::streamFor( '<h1>Not found</h1>'.$e->getMessage() ));			
		}catch(\Exception $e){
		     $response = new Response(500);
             $response =  $response->withBody(
				 \GuzzleHttp\Psr7\Utils::streamFor( '<h1>Error</h1><error>'. $e->getMessage().'</error>')
			 );			
		}
		
			if(is_string($response)){
	           $response2 = new Response(200);
               $response =  $response2->withBody(\GuzzleHttp\Psr7\Utils::streamFor($response));			
			}
	}else{//$this->hasContainer()
		     $response = new Response(404);
             $response =  $response->withBody(\GuzzleHttp\Psr7\Utils::streamFor( 
				 '<h1>Not found</h1>'																				
				 .'There is no container available which has a router!'
			     .' - You should continue the installation!'										   
			 ));		
	}
		
	    if($origin){
			$response =  $response->withHeader('Access-Control-Allow-Origin', $origin);	
		}else{
           $response = $response->withHeader('Access-Control-Allow-Origin', '*');	
		}

			
		$ConentType = $this->getResponseHeader('Content-Type', $response);
		if(false === $ConentType || 'text/html' === $ConentType){
		  $contents = (string) $response->getBody();
	//	  $contents = $this->patch_ob_handler($this->Document->compile($contents));
		  $contents = $this->Document->compile($contents);
		  $response =  $response->withBody(\GuzzleHttp\Psr7\Utils::streamFor($contents));
		}

	
	  return $response;
    }
	
    /* PSR-15 */
       public function handle(ServerRequestInterface $request): ResponseInterface
	   {
		   $this->boot();
		
           if ($this->isCLI()) {             			
		    	$this->handleCliRequest();
			    $this->end();
           }else{
                return $this->handleHttpRequest($request);
           }
	   }
	
}__halt_compiler();----SIGNATURE:----UNjMTf8ycdJ5eBw5905SgFTAyiBrxOZDhtmLCWzu2DbJD4S5vel/fqqYaA9FaTE9yMCVcbfRdlX49xKkMMictg6x0Laz4BCxzWFOpO7Fy8ynXUkOB/QU24v11YOUWFd5Pk4MgkvZVp7KNjf4E9xMWUsDGw1te5Cs1gkxi0G9ifD5s0RH1piaAd8fho+R+fgi3cpbsx39ouNloVpTlDrFqm0fROtVV2HG+D1pc/jhPh2OWs5Vl+3IZm8dGbV4YmpmbCCyKZVA4VN1ukwv53fzPkacCPwdFJK80D4C4bhPXrhkY5ougk7bGORNpL9cpSShXjrvXY4ejNQXTwWmsXrVy7TCpe/aar1o0Xu+P+wP8qoOUcTjR1rnZNcU9hF/bNKruPj/RYPwXyeMStbwL+ABQ0OsDJPaQipqfVY4e5TAQMCOZm2Z3Xtnu0W0AdOPJjgi4L64fxC9ylMiG29vPEAvhqVRagrqFRFn9uTIT4+Y16f8ziJ9TipcVgWrg1uFuvqDL4RpkhXHiDa9qo4NnZgnHof3oy16OwFIGMjKFvSpJ3dnHGTPOik1gIGe20veJHKYYLne5nYqTYroiaH8nBlIvqCFgL7njVloqh+XxsV+AMsYNxu7qkjDhIjgbmpiNdeIs9ze32qkaL9D/zddUFQ0Wv35fXWPmMK9vLVCH0LyoYs=----ATTACHMENT:----MzA3NzQxNDUzMDAyMDc4NCA3NDA1NDI3NzYyMzkzNDU2IDQ2NzAxNzAxNTk4OTA1MTc=