# Script to generate Localization.h from resources.resw


param( [Parameter(Mandatory=$true)] $OutFile)

$ErrorActionPreference = "Stop"

$resourceFolder = "$($PSScriptRoot)\..\localization\strings"
$defaultLanguage = "en-US"
$languages = @($defaultLanguage) + (Get-ChildItem -Path $resourceFolder | % { $_.name} | Where { $_ -Ne $defaultLanguage })

$content = @"
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// This file is generated by generateLocalizationHeader.ps1, do not edit it manually.

#pragma once

#include <vector>
#include <stringshared.h>

namespace wsl::shared {

class Localization
{
public:

#ifdef WIN32

#define ARGS std::make_wformat_args
using TChar = wchar_t;

#else

#define ARGS std::make_format_args
using TChar = char;

#define TEXT(X) X

#endif

using TString = std::basic_string<TChar>;

enum class Options
{
    Default = 0,
    DontImpersonate = 1
};
"@

function getArgumentsFromInserts
{
    param(
        [string]$Name,
        [string]$Content)

    [System.Collections.ArrayList]$Arguments = @()

    $Content = $Content -Replace '{{', ''
    
    return ([regex]::Matches($Content, "{" )).count
}

function generateEntry
{
    param(
        [string]$Name,
        [hashtable]$AllStrings)

    $content = $AllStrings[$defaultLanguage][$Name]
    $map = "static const std::vector<std::pair<TString, const TChar*>> strings {`r`n              {TEXT(`"$defaultLanguage`"), TEXT(R`"($content)`")}"

    foreach ($language in $AllStrings.Keys)
    {
        if ($language -eq $defaultLanguage)
        {
            continue
        }

        $strings = $AllStrings[$language]

        if (!$strings.ContainsKey($Name))
        {
            Write-Host "Warning: string $Name not found in language: $language"
            continue
        }
        
        $map += ",`r`n              {TEXT(`"$language`"), TEXT(R`"($($strings[$Name]))`")}"
    }

    $map += "}"


    $ArgumentsCount = getArgumentsFromInserts -Name $Name -Content $Content
    if ($ArgumentsCount -eq 0)
    {
        return '
        /* Message: {1}*/
        static inline TString {0}(Options options = Options::Default)
        {{
            {2};

            return LookupString(strings, options);
        }}
        ' -f $Name, $Content.split("`n")[0], $map
    }
    else
    {
        $ArgumentTypes = [string]::Join(', ', ((1..$ArgumentsCount) |% {"typename T$_"}))
        $ArgumentHeaders = [string]::Join(', ', ((1..$ArgumentsCount) |% {"const T$_& arg$_"}))
        $Arguments = [string]::Join(', ', ((1..$ArgumentsCount) |% {"arg$_"}))
        return '
        /* Message: {4}*/
        
        template <{1}>
        static TString {0}({2}, Options options = Options::Default)
        {{
            {5};

            auto message = LookupString(strings, options);
            return std::vformat(message, ARGS({3}));
        }}
        ' -f $Name, $ArgumentTypes, $ArgumentHeaders, $Arguments, $Content.split("`n")[0], $map

    }
}

function loadStrings
{
    param([string]$language)
    $xml = [xml](Get-Content "$resourceFolder/$language/Resources.resw" -raw)

    $strings = @{}

    foreach($entry in $xml.root.data)
    {
        if ($strings.ContainsKey($entry.name))
        {
            throw "Entry $($entry.name) duplicated in resource for: $language"
        }

        # Skip generating strings intended for WSL Settings. These strings are
        # unused in native C++ code. Further, their naming is incompatible with
        # the function names generated for the localization header (contain '.').
        if ($entry.name.StartsWith("Settings_"))
        {
            continue
        }

        $strings[$entry.name] = $entry.value
    }

    return $strings
}

$allStrings = @{}

foreach ($language in $languages)
{
    $allStrings[$language] = loadStrings -language $language
}

foreach($entry in $allStrings[$defaultLanguage].Keys)
{
    $content += generateEntry -Name $entry -allStrings $allStrings
}

$content += @"
private:
    static const TChar* LookupString(const std::vector<std::pair<TString, const TChar*>>& strings, Options options);
};

} // namespace wsl::windows::common

#undef ARGS
"@


Set-Content -Path $OutFile -Encoding UTF8 $content