<?php
ini_set( 'session.use_only_cookies', 1 );
    
require_once( 'logrotate_config.php' );
require_once( 'config.php' );
require_once( 'sysConfig.php' );

$cookie_lifetime = 0;
$cookie_domain = parse_url( TVWEB_HOME, PHP_URL_HOST );
$cookie_path = parse_url( TVWEB_HOME, PHP_URL_PATH );
$cookie_secure = true;
$cookie_httponly = true;
$cookie_samesite = 'None';

if ( version_compare( PHP_VERSION, '7.3.0', '<' ) ) {
    session_set_cookie_params( $cookie_lifetime, $cookie_path . '; samesite=' . $cookie_samesite, $cookie_domain, $cookie_secure, $cookie_httponly );
} else {
    session_set_cookie_params( array(
        'lifetime' => $cookie_lifetime,
        'domain' => $cookie_domain,
        'path' => $cookie_path,
        'secure' => $cookie_secure,
        'httponly' => $cookie_httponly,
        'samesite' => $cookie_samesite
    ) );
}

session_name( COOKIE_PREFIX . 'session' );
session_start();
//session_regenerate_id();
header( 'P3P: CP="This is not a policy"' );

if ( !isset( $_SESSION[ 'sessionID' ] ) ) {
    $t_expl = explode( ".", microtime( true ) );
    $_SESSION[ 'sessionID' ] = uniqid() . end( $t_expl );
}

if ( !isset( $_SESSION[ 'storage' ] ) )
    $_SESSION[ 'storage' ] = array( 'storage_creation' => date( "Y-m-d H:i:s" ) );

//$_SESSION['kev.dev'] = array();

//require_once('lib/logger.php');
//$logger = new Logger();
//$logger->sessionID = $_SESSION['sessionID'];
//$logger->ip = $_SERVER['REMOTE_ADDR'];

function myDebug( $data, $name = false, $outputter = false ) {
    $echo = "<pre>";
    if ( $name )
        $echo .= "<h1>$name</h1>";
    if ( is_array( $data ) || is_object( $data ) )
        $echo .= print_r( $data, true );
    else
        $echo .= "'$data'";
    $echo .= "</pre>";
    $echo .= "<hr/>";
    
    if ( $outputter instanceof PageOutputter )
        $outputter->Add( $echo );
    else
        echo $echo;
}

if (defined('E_DEPRECATED')) {
    error_reporting(E_ALL & ~E_DEPRECATED);
} else {
    error_reporting(E_ALL);
}

function __Main_Error_Handler__($errno, $errstr, $errfile, $errline) {
    global $main_Error_String, $php_errors;

    $main_Error_String .= $errfile . ":" . $errline . " > " . $errstr . "\n";
    $php_errors[] = $errfile . ":" . $errline . " > " . $errstr;
}

set_error_handler('__Main_Error_Handler__');

function myLog( $msg ) {
    list( $sec, $msec ) = explode( ".", microtime( true ) );
    $ts = date( "Y-m-d H:i:s", $sec ) . ".$msec";
    $handle = fopen( "logs/" . LOG_MYLOG, "a" );
    fwrite( $handle, $ts . "\t" . $msg . "\n" );
    fclose( $handle );
}

function log_debug( $msg ) {
    if ( !!DEBUG_MODE && g_GET( 'url', '' ) != "datatransmission" ) {
        $msg = ( $_SESSION[ 'sessionID' ] ?? 'session' ) . ' | ' . $msg;
        writeLog( $msg, SYS_GENERAL_LOG_DEBUG );
    }
}

$skip_outputter = false;
try {
    define( 'APPMODE', 'HTML' );

    if ( !isset( $config[ 'debug' ] ) )
        $config[ 'debug' ] = FALSE;
    
    // Datenmodelle
    require_once('model/params.php');
    require_once('model/mandatorparams.php');
    require_once 'model/usage_feedback.php';

    require_once('lib/translate.php');
    require_once('lib/datetime.php');
    require_once('lib/database.php');
    require_once('lib/tools.php');

    require_once('lib/routing.php');
    require_once('lib/output.php');
    require_once('lib/stringTools.php');
    require_once('lib/errorControl.php');

    require_once('view/languageMenu.php');
    
    require_once('lib/logrotate/logrotate_autoload.php');

    require_once 'lib/kmx_BrowserDetection.php';

//    log_debug( '#######################################################################################################' );

    $urls_ignore = array(
        'images/favicon.gif',
        '{tplPath}/images/help.png',
        'favicon.ico'
    );
    if ( in_array( g_GET( 'url', '' ), $urls_ignore ) ) {
        http_response_code( 404 );
        exit;
    }

    if ( isset( $_GET[ 'rs' ] ) ){
        session_unset();

        $t_expl = explode( ".", microtime( true ) );
        $_SESSION[ 'sessionID' ] = uniqid() . end( $t_expl );

        $_SESSION[ 'storage' ] = array( 'storage_creation' => date( "Y-m-d H:i:s" ) );
    }

    if ( !!DEBUG_NETWORK )
        writeLog( "index (" . __LINE__ . "), url '" . g_GET( 'url' ) . "', start", SYS_DEBUG_NETWORK );

    if ( g_SESSION( 'usage_uuid', false ) === false )
        $_SESSION[ 'usage_uuid' ] = get_uuid();

    $rsv_mode_mapping = array(
        0 => 'Unbekannt',
        1 => 'Reservierung',
        2 => 'Terminänderung',
        3 => 'Terminwunsch'
    );

    $url = g_GET( 'url', '' );

    // Datenbankverbindung aufbauen
    Database::ConnectToDefaultDatabaseInstance( $config[ 'database' ] );
    if ( !!DEBUG_NETWORK )
        writeLog( "index (" . __LINE__ . "), url '" . g_GET( 'url' ) . "', DB-Con hergestellt", SYS_DEBUG_NETWORK );

    if ( !!DEBUG_STORAGE ) {
        writeLog( "###################################################################################", LOG_STORAGE );
        writeLog( g_SESSION( 'sessionID', 'session' ) . " | URL: '" . g_GET( 'url', '' ) . "'", LOG_STORAGE );
    }

    $storage_creation = g_STORAGE( 'storage_creation', '1970-01-01 00:00:00' );
    $sendxmldata_last_run = date( "Y-m-d H:i:s", Params()->ReadDateTime( '!sendxmldata', 'last_run', 0 ) );
    if ( $storage_creation < $sendxmldata_last_run ) // neue tevis-daten => storage leeren => neue DB-abfrage
        r_STORAGE();

    require_once( 'app/routes.php' );
    $routed_file = Routing::Route( g_GET( 'url', '' ), $_ROUTES, AE( $config, 'custom_routes', array() ) );

    $urls_process_minimal = array(
        'datatransmission',
        'datatransmission2',
    );
    if ( !in_array( g_GET( 'url', '' ), $urls_process_minimal ) ) {
        // normaler prozess
        $cookiePath = parse_url( TVWEB_HOME, PHP_URL_PATH ); // 'http://tvweb.devdev/ks_dev/' -> '/ks_dev/'
        $cookieDomain = parse_url( TVWEB_HOME, PHP_URL_HOST ); // 'http://tvweb.devdev' -> 'tvweb.devdev'

        $contrast_forced = false;
        $contrast_default = false;
        if ( isset( $config[ 'contrast_mode' ] ) ) {
            if ( isset( $config[ 'contrast_mode' ][ 'default' ] ) )
                $contrast_default = (bool)$config[ 'contrast_mode' ][ 'default' ];

            if ( isset( $config[ 'contrast_mode' ][ 'forced' ] ) )
                $contrast_forced = (bool)$config[ 'contrast_mode' ][ 'forced' ];
        }

        if ( $contrast_forced === true ) {
            s_COOKIE( 'contrast', 1, ( time() + 60 * 60 * 24 * 7 ), $cookiePath, $cookieDomain, null, false, false );
        } else {
            if ( $contrast_default === true ) {
                if ( g_COOKIE( 'contrast', false, false ) === false )
                    s_COOKIE( 'contrast', 1, ( time() + 60 * 60 * 24 * 7 ), $cookiePath, $cookieDomain, null, false, false );
            } else {
                if ( isset( $config[ 'contrast_mode' ][ 'display_menu' ] ) && (bool)$config[ 'contrast_mode' ][ 'display_menu' ] === false ) {
                    if ( g_COOKIE( 'contrast', false, false ) !== false ) {
                        unset( $_COOKIE[ COOKIE_PREFIX . 'contrast' ] );
                        s_COOKIE( 'contrast', '', time() - 3600, $cookiePath, $cookieDomain, null, false, false );
                    }
                }
            }
        }

        $language = g_GET( 'lang', false );
        if ( $language ) {
            Translator::SetLanguage( $language );
        } else {
            $language_sess = g_SESSION( 'language', false );
            if ( $language_sess !== false )
                Translator::SetLanguage( $language_sess );
            else
                Translator::SetLanguage( Params()->Read( 'general', 'default_lang', 'de_DE' ) );
        }

        SetAnyLocale( LC_ALL, array( _TX( TX_E_LOCALE1 ), _TX( TX_E_LOCALE ) ) );
        setlocale( LC_TIME, _TX( TX_E_LOCALE ) );
        setlocale( LC_NUMERIC, 'C' );
        date_default_timezone_set( _TX( "Europe/Berlin" ) );

        unregister_GLOBALS();

        $wochentage_key = array(
            1 => "Montag",
            2 => "Dienstag",
            3 => "Mittwoch",
            4 => "Donnerstag",
            5 => "Freitag",
            6 => "Samstag",
            0 => "Sonntag"
        );

        $wochentage_eng = array(
            "monday"    => "Montag",
            "tuesday"   => "Dienstag",
            "wednesday" => "Mittwoch",
            "thursday"  => "Donnerstag",
            "friday"    => "Freitag",
            "saturday"  => "Samstag",
            "sunday"    => "Sonntag"
        );

        $useRules = Params()->ReadInt('rules', 'useRules', 0);
        $bos_activationKey = Params()->Read( 'bos', 'activationKey', '' );

        $useTerminal = g_GET( 'terminal', false );
        if ( $useTerminal && ( $bos_activationKey != '' ) && ( $useTerminal == $bos_activationKey ) ) {
            $useTerminal = $bos_activationKey;
            Outputter()->setTerminal( TRUE );
            if ( g_GET( 'btserver' ) != '' ) {
                if ( g_SESSION( 'btserver' ) == '' )
                    $_SESSION[ 'btserver' ] = g_GET( 'btserver' );
            }
        } else {
            $useTerminal = false;
        }

        $urlAttach = '';
        if ( $useTerminal ) {
            //wenn Terminal verwendet wird an jede URL &terminal=true anhängen
            $urlAttach .= '&terminal=' . $useTerminal;
            if ( !isset( $config[ 'terminal' ][ 'backurl' ] ) )

                // Änderungen move2net - 23.08.2016
                // $config['terminal']['backurl'] = Params()->Read('site', 'url', 'http://web.kommunix.de');
                $config[ 'terminal' ][ 'backurl' ] = Params()->Read( 'site', 'url' );


            $addUrl = str_replace( '&', '?', $urlAttach );
            if ( !isset( $_SESSION[ 'btserver' ] ) )
                $_SESSION[ 'btserver' ] = $config[ 'terminal' ][ 'backurl' ] . $addUrl;
            define( 'TERMINAL_BACK_URL', $_SESSION[ 'btserver' ] );
            $tplPath = 'styles/terminal/' . Params()->Read( 'template', 'terminalTemplate', 'basis' );
        } else {
            $tplPath = 'styles/web/' . Params()->Read( 'template', 'webTemplate', 'basis' );
        }

        $openInFrame = g_GET( 'openInFrame', false );
        if ( $openInFrame == 'true' )
            $urlAttach .= '&openInFrame=true';

        Outputter()->setGlobalConfig( $config );

        if ( $tplPath == 'styles/web/' )
            $tplPath = 'styles/web/basis';
        elseif ( $tplPath == 'styles/terminal/' )
            $tplPath = 'styles/terminal/basis';

        if ( file_exists( $tplPath ) ) {
            require_once( $tplPath . '/params.php' );
            Outputter()->setTemplate( $tplPath );
            Outputter()->Clear();
        } else {
            if ( $useTerminal )
                $tplPath = 'styles/terminal/basis';
            else
                $tplPath = 'styles/web/basis';
            require_once( $tplPath . '/params.php' );
            Outputter()->setTemplate( $tplPath );
            Outputter()->Clear();
        }

        // Laden einer externen Templatedatei wenn konfiguriert
        if ( AE( $style_config, 'externalstyle.active', FALSE ) ) {
            $exportPath = $tplPath . '/template.html';
            $fileExpired = FALSE;
            if ( file_exists( $exportPath ) ) {
                $maxage = AE( $style_config, 'externalstyle.maxage', 0 );
                $age = time() - filemtime( $exportPath );
                if ( g_GET( 'reloadtemplate' ) ) {
                    $fileExpired = TRUE;
                } else if ( $maxage > 0 ) {
                    if ( $age > $maxage ) { //Sekunden * Minuten * Stunden * Tage
                        $fileExpired = TRUE;
                    }
                }
            }
            if ( $fileExpired ) {
                //Reload des Templates
                require_once( 'app/templateParser.php' );
                $tp = new templateParser();
                $tp->loadTemplate( $style_config, $tplPath );
            }
        }

        if ( !!DEBUG_MODE ) {
            myLog( "############################################################################################################################" );
            myLog( "############################################################################################################################" );
            myLog( "routing url '" . g_GET( 'url', '' ) . "' to file: '$routed_file'" );
            myLog( "REQUEST_METHOD '" . g_SERVER( 'REQUEST_METHOD' ) . "'" );
            myLog( "INDEX _GET: " . print_r( $_GET, true ) );
            myLog( "INDEX _POST: " . print_r( $_POST, true ) );
            myLog( "INDEX _SESSION: " . print_r( $_SESSION, true ) );
//            myLog( "INDEX _FILES: ".print_r($_FILES, true) );
//            myLog( "INDEX getallheaders: ".print_r(getallheaders(), true) );
//            myLog( "INDEX php://input:\r\n".print_r( file_get_contents('php://input'), true) );
//            myLog( "INDEX _SERVER: ".print_r($_SERVER, true) );
            myLog( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
        }

        if ( !!DEBUG_NETWORK )
            writeLog( "index (" . __LINE__ . "), url '" . g_GET( 'url', '' ) . "', route '$routed_file'", SYS_DEBUG_NETWORK );
        if ( !file_exists( $routed_file ) )
            throw new Exception( _TX( "Die Datei existiert nicht: " ) . $routed_file );

        // Änderungen move2net - 23.08.2016
        //Wichtige Variablen zur Nutzung in den Dateien
        $siteurl = Params()->Read( 'site', 'url', 'http://localhost/' );

        $time = DateTimeTools::MontagDieserWoche( time() );

        require_once( 'model/mandators.php' );
        require_once( 'model/calendars.php' );
        require_once( 'model/concerns.php' );
        require_once( 'model/allocations.php' );
        require_once( 'model/reservations.php' );
        require_once( 'app/settings.php' );

        /* WARTUNGSMODUS */
        if ( g_CONFIG( 'maintenance_mode/active', false ) === true ) {
            myLog( 'maintenance mode -> via config.php' );
            require_once( 'view/maintenance.php' );
        } else {
            $maintenance_mode_active = Params()->ReadInt( 'maintenance_mode', 'active' );
            if ( $maintenance_mode_active === 1 && !in_array( g_GET( 'url', '' ), array( 'datatransmission', 'datatransmission2' ) ) ) {
                $maintenance_start = strtotime( Params()->Read( 'maintenance_mode', 'active_from', '1970-01-01 00:00:00' ) );
                $maintenance_end = strtotime( Params()->Read( 'maintenance_mode', 'active_to', '2099-12-31 23:59:59' ) );
                $now = time();
                if ( $maintenance_start <= $now && $now <= $maintenance_end ) {
                    myLog( 'maintenance mode -> via tevis' );
                    require_once( 'view/maintenance.php' );
                }
            }
        }

        /* BROWSERPRÜFUNG */
        if ( g_GET( 'accept_browser_error', false ) !== false ) {
            $cookieExpireTime = time() + 60 * 60 * 24 * 3; // browser-meldung taucht nach 3 tagen wieder auf
            $cookiePath = parse_url( TVWEB_HOME, PHP_URL_PATH ); // 'http://tvweb.devdev/ks_dev/' -> '/ks_dev/'
            $cookieDomain = parse_url( TVWEB_HOME, PHP_URL_HOST ); // 'http://tvweb.devdev' -> 'tvweb.devdev'
            s_COOKIE( 'browser_error_accepted', 1, $cookieExpireTime, $cookiePath, $cookieDomain );
        } else {
            if (g_CONFIG( 'browser_detection', false ) === true &&
                !in_array( g_GET( 'url', '' ), array( 'datatransmission', 'datatransmission2', 'api', 'version' ) ) &&
                g_COOKIE( 'browser_error_accepted', 0 ) === 0
            ) {
                $browser_detect = new kmx_BrowserDetection();
                if ( !$browser_detect->browser_is_valid( g_SERVER( 'HTTP_USER_AGENT', '' ) ) ) {
                    $detected_browser = AE( g_SESSION( 'browser_detection', array() ), 'detected_browser', 'Unbekannt' );
                    $detected_version = AE( g_SESSION( 'browser_detection', array() ), 'detected_version', 0 );

                    myLog( "browser detection: $detected_browser $detected_version" );
                    require_once( 'view/browser_error.php' );
                }
            }
        }
    } else {
        // minimaler prozess
        $skip_outputter = true;
    }

    if ( !!DEBUG_NETWORK )
        writeLog( "index (" . __LINE__ . "), url '" . g_GET( 'url', '' ) . "', require start", SYS_DEBUG_NETWORK );
    require_once( $routed_file );
    if ( !!DEBUG_NETWORK )
        writeLog( "index (" . __LINE__ . "), url '" . g_GET( 'url', '' ) . "', require end", SYS_DEBUG_NETWORK );
    if ( !!DEBUG_NETWORK )
        writeLog( '##################################################', SYS_DEBUG_NETWORK );
} catch ( Exception $e ) {
    switch ( get_class( $e ) ) {
        case "DbError":
            writeLog( $e->getMessage(), SYS_DB_ERRORS );
            writeLog( $e->getTraceAsString(), SYS_DB_ERRORS );
            Outputter()->getExceptionWrap( _TX( "Es ist ein Datenbank-Fehler aufgetreten" ) );
            break;

        case "ControllerException":
            Outputter()->getExceptionWrap( _TX( "Es ist ein Fehler aufgetreten" ), $e->getMessage() );
            break;
        
        case "CitykeyError":
            Outputter()->getExceptionWrap( _TX( "Es ist ein Fehler aufgetreten" ), $e->getMessage(), g_SESSION( 'return_url', false ), _TX( 'Zurück zu Citykey' ) );
            break;
            
        case "ReservationWishResponseError":
            Outputter()->getExceptionWrap( _TX( "Es ist ein Fehler aufgetreten" ), $e->getMessage(), $siteurl . 'reservation_wish_response', _TX( 'Zurück zur Eingabe' ) );
            break;

        case "OpenIDConnectClientException":
            writeLog( $e->getMessage(), SYS_GENERAL_LOG_ERROR );
            Outputter()->getExceptionWrap( _TX( "Fehler beim Abruf der Personendaten" ) );
            break;

        case "CancelReservationWarning":
            Outputter()->getExceptionWrap( _TX( "Hinweis" ), $e->getMessage(), $siteurl . $urlAttach, _TX( 'Zurück zur Startseite der Online-Terminvergabe' ) );
            break;

        default:
            writeLog( $e->getMessage(), SYS_GENERAL_LOG_ERROR );

            if ( file_exists( 'styles/web/basis/css/tvo.css' ) )
                echo '<link rel="stylesheet" href="styles/web/basis/css/tvo.css?cache_buster=' . uniqid() . '" type="text/css" />';
            echo '<div class="content content--error">';
                echo '<div class="header">';
                    echo '<h1 class="error">' . _TX( "Es ist ein Fehler aufgetreten" ) . '</h1>';
                    echo '<p>' . $e->getMessage() . '</p>';
                echo '</div>';
                echo '<a href="' . $siteurl . $urlAttach . '">' . _TX( 'Zurück zur Startseite der Online-Terminvergabe' ) . '</a>';
            echo '</div>';

            $skip_outputter = true;
            break;
    }

    session_destroy();
} catch ( Error $t ) {
    if ( function_exists( 'writeLog' ) && defined( 'SYS_GENERAL_LOG_ERROR' ) ) {
        writeLog( $t->getMessage(), SYS_GENERAL_LOG_ERROR );
        $tmp_trace = array_reverse( $t->getTrace() );
        foreach ( $tmp_trace as $tmp_trace_entry )
            writeLog( $tmp_trace_entry[ 'file' ] . '(' . $tmp_trace_entry[ 'line' ] . '): ' . $tmp_trace_entry[ 'function' ] . "()", SYS_GENERAL_LOG_ERROR );
        writeLog( $t->getFile() . '(' . $t->getLine() . ')', SYS_GENERAL_LOG_ERROR );
    } else {
        date_default_timezone_set( "Europe/Berlin" );
        $logfile = 'logs/' . 'error.' . date( "Y-m-d" ) . '.log';
        $handle = fopen( $logfile, 'a+' );
        if ( !$handle )
            die( "Fehler beim Schreiben des Error-Logs: '$logfile'" );

        $err_msg = $t->getMessage() . " at " . $t->getFile() . ":" . $t->getLine();
        fwrite( $handle, date( 'Y-m-d H:i:s' ) . ' | ' . $_SERVER['REMOTE_ADDR'] . ' | ' . $err_msg . "\n" );
        fclose( $handle );
    }

    if ( file_exists( 'styles/web/basis/css/tvo.css' ) )
        echo '<link rel="stylesheet" href="styles/web/basis/css/tvo.css?cache_buster=' . uniqid() . '" type="text/css" />';
    echo '<h1 class="error" style="max-width: 300px; margin-left: auto; margin-right: auto; text-align: center;">Kritischer Fehler</h1>';
    $skip_outputter = true;
}

if ( !$skip_outputter && Outputter()->makeOutput ) {
    if ( !!DEBUG_NETWORK )
        writeLog( 'index (' . __LINE__ . '), url \'' . g_GET( 'url' ) . '\', output_start', 'network.log' );

    if ( $config[ 'debug' ] ) {
        Outputter()->Add( '<!-- DEBUG-MODUS AKTIVIERT -->' );
    }

    if ( $config[ 'debug' ] && Outputter()->isHtml ) {
        Outputter()->Add( '<!--' );
        Outputter()->Add( Htmlify_TA( implode( "\r\n", Database()->GetProtocol() ) ) );
        Outputter()->Add( '-->' );
    }

    if ( strlen( $main_Error_String ) > 0 ) {
        if ( $config[ 'debug' ] ) {
            Outputter()->Add( '<!--' );
            Outputter()->Add( $main_Error_String );
            Outputter()->Add( '-->' );
        }

        foreach ( $php_errors as $php_error ) {
            writeLog( $php_error, SYS_PHP_ERRORS );
        }
    }

    Outputter()->OutputHeader();
    Outputter()->OutputText( true );
    Outputter()->OutputFooter();
    if ( !!DEBUG_NETWORK )
        writeLog( 'index (' . __LINE__ . '), url \'' . g_GET( 'url' ) . '\', output_end' . "\n", 'network.log' );
}

Database::CloseInstance();
_TXfinish();