<?PHP
/**
 * Generic collection of functions used in CSVXML.
 *
 * @file
 *
 * @author
 */
declare(strict_types = 1);

/**
 * Function lang_getfrombrowser gets the browser language based on HTTP headers.
 *
 * @param array   $allowed_languages Array containing all the languages for which
 *                                   there are translations.
 * @param string  $default_language  Default language of the instance of MD.
 * @param string  $lang_variable     Currently set language variable. Optional.
 * @param boolean $strict_mode       Whether to demand "de-de" (true) or "de" (false) Optional.
 *
 * @return string
 */
function lang_getfrombrowser(array $allowed_languages, string $default_language, string $lang_variable = "", bool $strict_mode = true):string {

    // $_SERVER['HTTP_ACCEPT_LANGUAGE'] verwenden, wenn keine Sprachvariable mitgegeben wurde
    if ($lang_variable === "") {
        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $lang_variable = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
    }

    // wurde irgendwelche Information mitgeschickt?
    if (empty($lang_variable)) {
        // Nein? => Standardsprache zurückgeben
        return $default_language;
    }

    // Den Header auftrennen
    $accepted_languages = preg_split('/,\s*/', $lang_variable);

    // Die Standardwerte einstellen
    $current_lang = $default_language;
    $current_q = 0;

    // Nun alle mitgegebenen Sprachen abarbeiten
    foreach ($accepted_languages as $accepted_language) {

        // Alle Infos über diese Sprache rausholen
        // phpcs:disable Generic.Strings.UnnecessaryStringConcat
        $res = preg_match('/^([a-z]{1,8}(?:-[a-z]{1,8})*)' . '(?:;\s*q=(0(?:\.[0-9]{1,3})?|1(?:\.0{1,3})?))?$/i', $accepted_language, $matches);
        // phpcs:enable

        // war die Syntax gültig?
        if (!$res) {
            // Nein? Dann ignorieren
            continue;
        }

        // Sprachcode holen und dann sofort in die Einzelteile trennen
        $lang_code = explode('-', $matches[1]);

        // Wurde eine Qualität mitgegeben?
        if (isset($matches[2])) {
            // die Qualität benutzen
            $lang_quality = (float)$matches[2];
        } else {
            // Kompabilitätsmodus: Qualität 1 annehmen
            $lang_quality = 1.0;
        }

        // Bis der Sprachcode leer ist...
        // phpcs:disable Squiz.PHP.DisallowSizeFunctionsInLoops
        while (count($lang_code)) {
            // phpcs:enable
            // mal sehen, ob der Sprachcode angeboten wird
            if (in_array(strtolower(join('-', $lang_code)), $allowed_languages)) {
                // Qualität anschauen
                if ($lang_quality > $current_q) {
                    // diese Sprache verwenden
                    $current_lang = strtolower(join('-', $lang_code));
                    $current_q = $lang_quality;
                    // Hier die innere while-Schleife verlassen
                    break;
                }
            }
            // Wenn wir im strengen Modus sind, die Sprache nicht versuchen zu minimalisieren
            if ($strict_mode) {
                // innere While-Schleife aufbrechen
                break;
            }
            // den rechtesten Teil des Sprachcodes abschneiden
            array_pop($lang_code);
        }
    }

    // die gefundene Sprache zurückgeben
    return $current_lang;

}

/**
 * Function for generating the HTML head.
 *
 * @param string $injected Additional code to inject into the head, e.g. a
 *                         reference to JS files.
 *
 * @return string
 */
function printHTMLHead(string $injected = "") {

    $output = '<!DOCTYPE HTML>
<html lang="en">
<head>

    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>

    <meta name="theme-color" content="#FFF" />
    <link rel="stylesheet" type="text/css" href="assets/css/csvxml.css" />
    <link rel="shortcut icon" sizes="128x128" href="assets/img/mdlogo-csvxml.svg" />
    <script src="assets/js/csvxml-overview.js" type="text/javascript" defer></script>

    <title>CSVXML :: museum-digital</title>

    <meta name="keywords" content="Imports, museum-digital" />
';

    $output .= $injected;

    $output .= '

</head>
<body>

<h1>
    <img src="assets/img/mdlogo-csvxml.svg" />
    <span>museum-digital:csvxml</span>
</h1>
';

    return $output;

}

/**
 * Function generateHelpTooltip returns a tooltip for hovering over using the common settings.
 *
 * @param string  $identifier   ID attribute of the tooltip.
 * @param string  $title        Title of the tooltip.
 * @param string  $explica      More in-depth explanation: body of the tooltip.
 * @param boolean $setParagraph If set to true (default), the content of the tooltip will be put into a <p> element. Optional.
 *
 * @return array
 */
function generateHelpTooltip(string $identifier, string $title, string $explica, bool $setParagraph = true):array {

    $outputTag = '<a class="newToolTipTag icons iconsHelp" data-for="' . $identifier . '" title="Help"></a>';
    $output = '<span class="newToolTip" id="tooltip_' . $identifier . '" data-title="' . $title . '">';
    if ($setParagraph) $output .= '<p class="toolTipCont">';
    $output .= $explica;
    if ($setParagraph) $output .= '</p>';
    $output .= '</span>';

    return [$output, $outputTag];

}

/**
 * Outputs a DOMDocument with correct header and then aborts.
 * Used mainly for debugging.
 *
 * @param DOMDocument $xmlDoc XML object.
 *
 * @return string
 */
function printDOMDocToXML(DOMDocument $xmlDoc):string {

    return '<?xml version="1.0" encoding="UTF-8"?>' . $xmlDoc->saveXML($xmlDoc->documentElement);

}

/**
 * Function for creating a DOMElement with a text node inside.
 *
 * @param DOMDocument $xmlDoc  XML document.
 * @param string      $tag     Tag.
 * @param string      $content Text content.
 *
 * @return DOMElement
 */
function createTextDomElement(DOMDocument $xmlDoc, string $tag, string $content):DOMElement {

    try {
        $element = $xmlDoc->createElement($tag);
    }
    catch (DOMException $e) {
        echo "Error at " . __FILE__ . ", line #" . __LINE__ . PHP_EOL . "<br/>";
        echo "Cannot create DOM element for $tag / $content";
        exit;
    }

    $element->appendChild($xmlDoc->createTextNode($content));

    return $element;

}

/**
 * Function for creating a DOMDocument record channel.
 *
 * @return array
 */
function getBlankRecordChannel():array {

    $xmlDoc = new DOMDocument("1.0", "UTF-8");
    $xmlMainElem = $xmlDoc->createElement("record");
    $record_node = $xmlDoc->appendChild($xmlMainElem); //add RSS element to XML node

    return [$xmlDoc, $record_node];

}

/**
 * Function for removing a directory with all its contents.
 *
 * @param string $dir File path of the directory to remove.
 *
 * @return void
 */
function rrmdir(string $dir) {
    if (is_dir($dir)) {
        $objects = scandir($dir);
        foreach ($objects as $object) {
            if ($object != "." && $object != "..") {
                if (filetype($dir . "/" . $object) == "dir") rrmdir($dir . "/" . $object); else unlink($dir . "/" . $object);
            }
        }
        reset($objects);
        rmdir($dir);
    }

}

/**
 * Function for checking if two arrays have identical values / contents.
 *
 * @param array $arrayA First array to compare.
 * @param array $arrayB Second array to compare.
 *
 * @return boolean
 */
function identical_values(array $arrayA, array $arrayB):bool {
    sort($arrayA);
    sort($arrayB);
    return $arrayA == $arrayB;

}