// format page size according to locale (e.g. "29.7 x 21.0 cm" or "11.69 x 8.27 in")
// Caller needs to free the result
static WCHAR *FormatPageSize(BaseEngine *engine, int pageNo, int rotation)
{
    RectD mediabox = engine->PageMediabox(pageNo);
    SizeD size = engine->Transform(mediabox, pageNo, 1.0f / engine->GetFileDPI(), rotation).Size();

    const WCHAR *formatName = L"";
    switch (GetPaperFormat(size)) {
    case Paper_A4: formatName = L" (A4)"; break;
    case Paper_A3: formatName = L" (A3)"; break;
    case Paper_A5: formatName = L" (A5)"; break;
    case Paper_Letter: formatName = L" (Letter)"; break;
    case Paper_Legal: formatName = L" (Legal)"; break;
    case Paper_Tabloid: formatName = L" (Tabloid)"; break;
    case Paper_Statement: formatName = L" (Statement)"; break;
    }

    bool isMetric = GetMeasurementSystem() == 0;
    double unitsPerInch = isMetric ? 2.54 : 1.0;
    const WCHAR *unit = isMetric ? L"cm" : L"in";

    double width = size.dx * unitsPerInch;
    double height = size.dy * unitsPerInch;
    if (((int)(width * 100)) % 100 == 99)
        width += 0.01;
    if (((int)(height * 100)) % 100 == 99)
        height += 0.01;

    ScopedMem<WCHAR> strWidth(str::FormatFloatWithThousandSep(width));
    ScopedMem<WCHAR> strHeight(str::FormatFloatWithThousandSep(height));

    return str::Format(L"%s x %s %s%s", strWidth.Get(), strHeight.Get(), unit, formatName);
}
/*
PAL Function:
GetLocaleInfoInt

Obtains integer locale information
Returns 1 for success, 0 otherwise
*/
extern "C" int32_t GlobalizationNative_GetLocaleInfoInt(
    const UChar* localeName, LocaleNumberData localeNumberData, int32_t* value)
{
    UErrorCode status = U_ZERO_ERROR;
    char locale[ULOC_FULLNAME_CAPACITY];
    GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &status);

    if (U_FAILURE(status))
    {
        return UErrorCodeToBool(U_ILLEGAL_ARGUMENT_ERROR);
    }

    switch (localeNumberData)
    {
    case LanguageId:
        *value = uloc_getLCID(locale);
        break;
    case MeasurementSystem:
        status = GetMeasurementSystem(locale, value);
        break;
    case FractionalDigitsCount:
    {
        UNumberFormat* numformat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status);
        if (U_SUCCESS(status))
        {
            *value = unum_getAttribute(numformat, UNUM_MAX_FRACTION_DIGITS);
            unum_close(numformat);
        }
        break;
    }
    case NegativeNumberFormat:
        *value = GetNumberNegativePattern(locale);
        break;
    case MonetaryFractionalDigitsCount:
    {
        UNumberFormat* numformat = unum_open(UNUM_CURRENCY, NULL, 0, locale, NULL, &status);
        if (U_SUCCESS(status))
        {
            *value = unum_getAttribute(numformat, UNUM_MAX_FRACTION_DIGITS);
            unum_close(numformat);
        }
        break;
    }
    case PositiveMonetaryNumberFormat:
        *value = GetCurrencyPositivePattern(locale);
        break;
    case NegativeMonetaryNumberFormat:
        *value = GetCurrencyNegativePattern(locale);
        break;
    case FirstWeekOfYear:
    {
        // corresponds to DateTimeFormat.CalendarWeekRule
        UCalendar* pCal = ucal_open(nullptr, 0, locale, UCAL_TRADITIONAL, &status);
        UCalendarHolder calHolder(pCal, status);

        if (U_SUCCESS(status))
        {
            // values correspond to LOCALE_IFIRSTWEEKOFYEAR
            int minDaysInWeek = ucal_getAttribute(pCal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
            if (minDaysInWeek == 1)
            {
                *value = CalendarWeekRule::FirstDay;
            }
            else if (minDaysInWeek == 7)
            {
                *value = CalendarWeekRule::FirstFullWeek;
            }
            else if (minDaysInWeek >= 4)
            {
                *value = CalendarWeekRule::FirstFourDayWeek;
            }
            else
            {
                status = U_UNSUPPORTED_ERROR;
            }
        }
        break;
    }
    case ReadingLayout:
    {
        // coresponds to values 0 and 1 in LOCALE_IREADINGLAYOUT (values 2 and 3 not
        // used in coreclr)
        //  0 - Left to right (such as en-US)
        //  1 - Right to left (such as arabic locales)
        ULayoutType orientation = uloc_getCharacterOrientation(locale, &status);
        // alternative implementation in ICU 54+ is uloc_isRightToLeft() which
        // also supports script tags in locale
        if (U_SUCCESS(status))
        {
            *value = (orientation == ULOC_LAYOUT_RTL) ? 1 : 0;
        }
        break;
    }
    case FirstDayofWeek:
    {
        UCalendar* pCal = ucal_open(nullptr, 0, locale, UCAL_TRADITIONAL, &status);
        UCalendarHolder calHolder(pCal, status);

        if (U_SUCCESS(status))
        {
            *value = ucal_getAttribute(pCal, UCAL_FIRST_DAY_OF_WEEK) - 1; // .NET is 0-based and ICU is 1-based
        }
        break;
    }
    case NegativePercentFormat:
        *value = GetPercentNegativePattern(locale);
        break;
    case PositivePercentFormat:
        *value = GetPercentPositivePattern(locale);
        break;
    default:
        status = U_UNSUPPORTED_ERROR;
        assert(false);
        break;
    }

    return UErrorCodeToBool(status);
}