<?php
###############################################################################
# loader.php
#
# @author Anil Kumar <akumar@codepunch.com>
# @link   https://codepunch.com
#
############################################################################### 

error_reporting(-1);

###############################################################################
// Make lib/php available for third-party self-loading libraries
set_include_path(__DIR__ . PATH_SEPARATOR . get_include_path());
require_once __DIR__ . '/NetDNS2/Resolver.php';

###############################################################################

$classes = array("Doctrine","CodePunch","Psr","Katzgrau", "Firebase", "PhpSocks");
foreach($classes as $class) {
	$classLoader = new ClassLoader($class, dirname(__FILE__));
	$classLoader->register();
}

\CodePunch\Config\ConfigRoot::load_global_config_data();

###############################################################################

class ClassLoader {
	
	protected $fileExtension = '.php';
	protected $namespace;
	protected $includePath;
	protected $namespaceSeparator = '\\';
	
	public function __construct($ns = null, $includePath = null) {
        $this->namespace   = $ns;
        $this->includePath = $includePath;
    }
	
	public function register() {
        spl_autoload_register([$this, 'loadClass']);
    }
	
	public function loadClass($className) {
        if(self::typeExists($className))
            return true;
        if(!$this->canLoadClass($className))
            return false;
		$fpath = ($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '') . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension;
		if(strpos($className, "ConfigBase") !== false) {
			// Check if the universal version exists
			$cfgpath = str_replace("ConfigBase.php", "ConfigBase.0.0.php", $fpath);
			if(!file_exists($cfgpath)) {
				// Check if the file is encoded
				$handle = fopen($fpath, 'r');
				fseek($handle, 0);
				$content = fread($handle, 1024);
				if(stristr($content, "class ConfigBase extends ConfigRoot") === false) {
					// If encoded, load the correct version based on PHP version.
					if(version_compare(PHP_VERSION, '8.2.0') >= 0)
						$cfgpath = str_replace("ConfigBase.php", "ConfigBase.8.2.php", $fpath);
					else if(version_compare(PHP_VERSION, '8.1.0') >= 0)
						$cfgpath = str_replace("ConfigBase.php", "ConfigBase.8.1.php", $fpath);
				}
			}
			$fpath = file_exists($cfgpath) ? $cfgpath : $fpath;
		}
		require($fpath);
        return self::typeExists($className);
    }
	
	public function canLoadClass($className) {
        if ($this->namespace !== null && strpos($className, $this->namespace . $this->namespaceSeparator) !== 0) {
            return false;
        }

        $file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension;

        if ($this->includePath !== null) {
            return is_file($this->includePath . DIRECTORY_SEPARATOR . $file);
        }

        return stream_resolve_include_path($file) !== false;
    }
	
	private static function typeExists($type, $autoload = false) {
        return class_exists($type, $autoload)
            || interface_exists($type, $autoload)
            || trait_exists($type, $autoload);
    }
}
