<?php

use Milk\Core\Autoloader;

/**
 * App Error
 */
$errorDocument = 'error.php';
$errorHeader = "HTTP/1.1 503 Service Unavailable";

/**
 *
 */
$rootIndexRedirections = array(
    '/index.php' => '/',
    '/index.html' => '/',
    '/index.htm' => '/',
);
$domainRootRedirections = array(
    '/sitemapindex.xml',
    '/robots.txt',
);
$layout = null;

/**
 * Application Path
 */
$applicationPath = realpath(__DIR__ . '/..') . '/';

include $applicationPath . 'lib/Milk/Core/Exception.php';
include $applicationPath . 'lib/Milk/Core/Exception/FileNotFoundException.php';
include $applicationPath . 'lib/Milk/Core/Exception/InvalidArgumentException.php';
include $applicationPath . 'lib/Milk/Core/Autoloader/Exception.php';
include $applicationPath . 'lib/Milk/Core/Autoloader/Exception/FileNotFoundException.php';
include $applicationPath . 'lib/Milk/Core/Autoloader/Exception/InvalidArgumentException.php';
include $applicationPath . 'lib/Milk/Core/Autoloader/AutoloaderInterface.php';
include $applicationPath . 'lib/Milk/Core/Autoloader.php';
include $applicationPath . 'lib/SiteApp/functions.php';

$parameters = array(
    'defaultDirectory' => $applicationPath . 'lib',
);
$autoloader = new Autoloader($parameters);
$autoloader->register();

if (false === $applicationPath) {
    if (file_exists($errorDocument)) {
        header($errorHeader);
        include $errorDocument;
    }else {
        header($errorHeader);
    }
    exit;
}

/**
 * Application Path
 */
SiteApp::setConfig('applicationPath', $applicationPath);

/**
 * Application Env
 */
$applicationEnv = getenv('APPLICATION_ENV') ?: 'prod';
SiteApp::setConfig('applicationEnv', $applicationEnv);

/**
 * Application Routing
 */
$request = $_SERVER['REQUEST_URI'];
$error = false;
$parsedUrl = parse_url($request);

if (substr($request, 0, 2) == '//') {
    $error = true;
}

if (isset($parsedUrl['path']) && $parsedUrl['path']) {
    $request = $parsedUrl['path'];
}

// Standard request format (+secure)
if (!preg_match('#^\/([a-z0-9\/\-\.]{0,100})$#i', $request)) {
    $error = true;
}

$host = $_SERVER['SERVER_NAME'];
$fullRequest = $host . $request;

$apacheHeaders = apache_request_headers();

if (isset($apacheHeaders['X-Requested-With'])) {
    $xhrHeader = $apacheHeaders['X-Requested-With'];
} else if (isset($apacheHeaders['x-requested-with'])) {
    $xhrHeader = $apacheHeaders['x-requested-with'];
}
$isXhr = isset($xhrHeader) && mb_strtolower($xhrHeader, 'UTF-8') == 'xmlhttprequest';

//X-Requested-With' => string 'XMLHttpRequest'
// $isXhr = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
SiteApp::setXhr($isXhr);

/**
 * Config file
 */
$config = include $applicationPath . 'app/_config.php';
SiteApp::addConfig($config);

/**
 * Cache
 */
$pageCacheId = \Milk\Core\Strings::alias($fullRequest, 0) . (SiteApp::isXhr() ? '-xhr' : '');
$cache = SiteApp::getCache();

if (!SiteApp::isDev() && $cache->exists($pageCacheId)) {
    $page = $cache->load($pageCacheId);
    
    foreach($page['headers'] as $header) {
        header($header, false);
    }
    echo $page['body'];
    
    exit;
}

ob_start();

/**
 * Lang file
 */
$langs = include $applicationPath . 'app/_lang.php';
SiteApp::setLangs($langs);

/**
 * Routing
 */
$lang = false;
$unlangRequest = $request;
$isDomainOnlyBaseRoute = true;

foreach($langs as $pLang => $configLang) {
//     echo '#^' . $configLang['baseRoute'] . '(/.*)?$#i';
//     echo '<br/>';
//     echo $fullRequest;
//     echo '<br/>';
    if (!$lang && isset($configLang['baseRoute']) && preg_match('#^' . $configLang['baseRoute'] . '(/.*)?$#i', $fullRequest)) {
        $lang = $pLang;
        $langRoute = 'http://' . $configLang['baseRoute'];
        $request = preg_replace('#^' . $configLang['baseRoute'] . '#i', '', $fullRequest);
        $unlangRequest = $request;
        
        if (preg_match('#/#', $configLang['baseRoute'])) {
            $isDomainOnlyBaseRoute = false;
        }
    }
    
    if (isset($configLang['default']) && $configLang['default']) {
        $defaultLang = $pLang;
        SiteApp::setDefaultLang($defaultLang);
    }
}

/**
 * Check redirections domains (force if default lang)
 */

if (!$lang || $lang == $defaultLang) {
    foreach($langs as $pLang => $configLang) {
        if (isset($configLang['baseRedirections'])) {
            foreach($configLang['baseRedirections'] as $route) {
                if (preg_match('#^' . $route . '(/.*)?$#i', $fullRequest)) {
                    $newRequest = 'http://' . preg_replace('#^' . $route . '#i', $configLang['baseRoute'], $fullRequest);

                    \SiteApp::redirect($newRequest);
                    exit;
                }
            }
        }
    }
}

// var_dump($request);
// var_dump($unlangRequest);
SiteApp::setUnlangRequest($request);
$langDirectory = $lang;

if (!$lang || $lang == $defaultLang) {
    $lang = $defaultLang;
    $langDirectory = false;
}
SiteApp::setCurrentLangDirectory($langDirectory);
SiteApp::setCurrentLang($lang);

if (SiteApp::getCurrentLang() == SiteApp::getDefaultLang() && preg_match('#^' . $config['admin']['uri'] . '/(page|asset)$#', $request)) {
    $request = substr($request, strlen(SiteApp::getConfig('admin', 'uri')));
    
    $request = SiteApp::getConfig('admin', 'path') . $request;
    $unlangRequest = $request;
    // Admin Routing
}


$isLangPage = true;
// die('Lang ' . $lang . ' - ' . $langDirectory);


$langs = SiteApp::getLangs();

if (isset($langs[$lang]['routes'])) {
    $routes = $langs[$lang]['routes'];
    $inverseRoutes = array_flip($routes);
    
    if (isset($routes[$request]) && isset($langRoute)) {
        // Manage /fr/pricing to /fr/prix
        SiteApp::redirect($langRoute . $routes[$request]);
        exit;
    }
    if (isset($inverseRoutes[$request])) {
        $unlangRequest = $inverseRoutes[$request];
        SiteApp::setUnlangRequest($unlangRequest);
    }
}

$pagePath = str_replace('.', '_', $unlangRequest);


$simpleSlashedRequest = preg_replace('#/+#', '/', $unlangRequest);
// echo $unlangRequest;die;
if ($simpleSlashedRequest != $unlangRequest) {
    SiteApp::redirect($langRoute . $simpleSlashedRequest);
    exit;
}

$metaFile = SiteApp::findMeta($pagePath);

// var_dump($pagePath);
// var_dump($metaFile);
    

// var_dump($pagePath);die;
if (!$metaFile && SiteApp::getCurrentLang() != SiteApp::getDefaultLang()) {
    if (substr($pagePath, -1, 1) == '/') {
        $pagePath = $pagePath . 'index';
        
        $metaFile = SiteApp::findMeta($pagePath);
    }
    
    if (!$metaFile) {
        $metaFile = SiteApp::findMeta($pagePath, true);
    
        if ($metaFile) {
            $isLangPage = false;
        }
    }
}

SiteApp::setPageLang($isLangPage);

// Page exist but "print/index"
if (!$error && $metaFile) {
    $trequest = preg_replace('#\/index$#','/',$request);
    if ($trequest !== $request) {
        SiteApp::redirect($langRoute . $trequest);
        exit;
    }
}

// Page not exist : looking for redirections
if (!$error && !$metaFile) {

    // Handle "/" && "/index"
    $slashedRequest = rtrim($unlangRequest, '/') . '/';
    
    // Redirect to slashed lang route if found
    if (isset($langs[$lang]['routes'])) {
        $inverseRoutes = array_flip($langs[$lang]['routes']);
        
        if (isset($inverseRoutes[$slashedRequest])) {
            SiteApp::redirect($langRoute . $slashedRequest);
            exit;
        }
    }
    
    $slashedPage = str_replace('.', '_', $slashedRequest.'index');
//     var_dump($slashedRequest);
//     var_dump($slashedPage);

    $slashedMeta = SiteApp::findMeta($slashedPage);

    if ($slashedMeta) {
        if ($slashedRequest !== $unlangRequest) {
            SiteApp::redirect($langRoute . $slashedRequest);
            exit;
        } else {
            $pagePath = $slashedPage;
        }
    } else {
        // Remove Last "/" ?
        $trimedRequest = rtrim($unlangRequest, '/');
        $trimedPage = str_replace('.', '_', $trimedRequest);
        
        // Redirect to trimed lang route if found
        if (isset($langs[$lang]['routes'])) {
            $inverseRoutes = array_flip($langs[$lang]['routes']);
        
            if (isset($inverseRoutes[$trimedRequest])) {
                SiteApp::redirect($langRoute . $trimedRequest);
                exit;
            }
        }
        
        $trimedMeta = SiteApp::findMeta($trimedPage, true);
        
        if ($trimedRequest != $request && $trimedMeta) {
            SiteApp::redirect($langRoute . $trimedRequest);
            exit;
        }
        
        // Root index redirections
        if (isset($rootIndexRedirections[$request])) {
            SiteApp::redirect($langRoute . $rootIndexRedirections[$request]);
            exit;
        } else if (isset($rootIndexRedirections[$trimedRequest])) {
            SiteApp::redirect($langRoute . $rootIndexRedirections[$trimedRequest]);
            exit;
        } else if (isset($rootIndexRedirections[$slashedRequest])) {
            SiteApp::redirect($langRoute . $rootIndexRedirections[$slashedRequest]);
            exit;
        }

        $error = true;
    }
}


/**
 * Redirect sitemap and robots requests to domain root
 */
if (!$isDomainOnlyBaseRoute) {
    if (in_array($request, $domainRootRedirections)) {
        SiteApp::redirect(SiteApp::getUrl($request, SiteApp::getDefaultLang()));
        exit;
    }
}

// var_dump($error);

/**
 * App Rendering
 */
if (!$error) {
    // Canonical
    if ($request !== $_SERVER['QUERY_STRING']) {
        $canonical = SiteApp::getRRUrl($request);
    }
} else {
    // Canonical
    $canonical = false;
    // Error Page
    $pagePath = '404';
}


/**
 * Lib
 */
// _lib
$file = SiteApp::getLibLang(true);
if ($file) {
    include $file;
}

// lang/_lib
$file = SiteApp::getLibLang();
if ($file) {
    include $file;
}

// page.lib
$file = SiteApp::getLib($pagePath, true);
if ($file) {
    include $file;
}

// lang/page.lib
$file = SiteApp::getLib($pagePath);
if ($file) {
    include $file;
}

/**
 * Meta
 */
// _meta
$file = SiteApp::getMetaLang(true);
if ($file) {
    include $file;
}

// lang/_meta
$file = SiteApp::getMetaLang();
if ($file) {
    include $file;
}

// page.meta
$file = SiteApp::getMeta($pagePath, true);
if ($file) {
    include $file;
}

// lang/page.meta
$file = SiteApp::getMeta($pagePath);
if ($file) {
    include $file;
}

/**
 * Data
 */
// _lib
$file = SiteApp::getDataLang(true);
if ($file) {
    include $file;
}

// lang/_lib
$file = SiteApp::getDataLang();
if ($file) {
    include $file;
}

// page.data
$file = SiteApp::getData($pagePath, true);
if ($file) {
    include $file;
}

// lang/page.data
$file = SiteApp::getData($pagePath);
if ($file) {
    include $file;
}

/**
 * Manage default lang page
 */
if (!$isLangPage) {
    $headRobots = "noindex,follow";
}


// Header
$file = SiteApp::getLayout('_header', $layout);
if ($file) {
    include $file;
}
 
// View
$file = SiteApp::getView($pagePath);
if ($file) {
    include $file;
} else {
    // Fallback if view file is missing
    $pagePath = '404';
    $file = SiteApp::getView($pagePath);
    if ($file) {
        include $file;
    }
}

// Footer
$file = SiteApp::getLayout('_footer', $layout);
if ($file) {
    include $file;
}

$body = ob_get_clean();
$formatter = new \SiteApp\HtmlFormatter\StandardFormatter();

// No Formatter for .txt or .xml
$doFormat = true;
$headersList = headers_list();
foreach ($headersList as $header) {
    if (stripos($header, "Content-type:") === 0) {
        if (stripos($header, "text/plain") !== false) {
            $doFormat = false;
            break;
        } else if (stripos($header, "text/xml") !== false) {
            $doFormat = false;
            break;
        }
        continue;
    }
}
if ($doFormat) {
    $body = $formatter->format($body);
}

if ((!isset($isCachePage) || $isCachePage) && !$error) {
    $page = array(
        'headers' => headers_list(),
        'body' => $body,
    );
    SiteApp::getCache()->save($pageCacheId, $page);
}

echo $body;
