import { Font as FontBase, parseFontFamily, genericFontFamilies, FontWeight, FontVariationSettings, FONTS_BASE_PATH } from './font-common';
import { getNativeApp } from '../../application/helpers-common';
import { Trace } from '../../trace';
import { SDK_VERSION } from '../../utils/constants';
import * as fs from '../../file-system';
export * from './font-common';
const typefaceCache = new Map();
let appAssets;
export class Font extends FontBase {
    withFontFamily(family) {
        return new Font(family, this.fontSize, this.fontStyle, this.fontWeight, 1, this.fontVariationSettings);
    }
    withFontStyle(style) {
        return new Font(this.fontFamily, this.fontSize, style, this.fontWeight, 1, this.fontVariationSettings);
    }
    withFontWeight(weight) {
        return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight, 1, this.fontVariationSettings);
    }
    withFontSize(size) {
        return new Font(this.fontFamily, size, this.fontStyle, this.fontWeight, 1, this.fontVariationSettings);
    }
    withFontScale(scale) {
        return new Font(this.fontFamily, this.fontSize, this.fontStyle, this.fontWeight, 1, this.fontVariationSettings);
    }
    withFontVariationSettings(variationSettings) {
        return new Font(this.fontFamily, this.fontSize, this.fontStyle, this.fontWeight, 1, variationSettings);
    }
    getAndroidTypeface() {
        if (!this._typeface) {
            this._typeface = SDK_VERSION >= 28 ? createTypeface(this) : createTypefaceLegacy(this);
        }
        return this._typeface;
    }
    getUIFont(defaultFont) {
        return undefined;
    }
}
Font.default = new Font(undefined, undefined);
function computeFontCacheKey(fontFamily, font) {
    const sep = ':';
    return [fontFamily, String(FontVariationSettings.toString(font.fontVariationSettings)).replace(/'/g, '').replace(/[\s,]/g, '_')].join(sep);
}
function loadFontFromFile(fontFamily, font) {
    const cacheKey = SDK_VERSION >= 26 ? computeFontCacheKey(fontFamily, font) : fontFamily;
    appAssets = appAssets || getNativeApp().getApplicationContext().getAssets();
    if (!appAssets) {
        return null;
    }
    let result;
    if (typefaceCache.has(cacheKey)) {
        result = typefaceCache.get(cacheKey);
    }
    else {
        const basePath = fs.path.join(fs.knownFolders.currentApp().path, FONTS_BASE_PATH, fontFamily);
        let fontAssetPath;
        if (fs.File.exists(basePath + '.ttf')) {
            fontAssetPath = basePath + '.ttf';
        }
        else if (fs.File.exists(basePath + '.otf')) {
            fontAssetPath = basePath + '.otf';
        }
        else {
            fontAssetPath = null;
            if (Trace.isEnabled()) {
                Trace.write('Could not find font file for ' + fontFamily, Trace.categories.Error, Trace.messageType.error);
            }
        }
        result = null; // Default
        if (fontAssetPath) {
            try {
                if (SDK_VERSION >= 26) {
                    const builder = new android.graphics.Typeface.Builder(fontAssetPath);
                    if (builder) {
                        builder.setFontVariationSettings(font.fontVariationSettings?.length ? FontVariationSettings.toString(font.fontVariationSettings) : '');
                        result = builder.build();
                    }
                    else {
                        result = android.graphics.Typeface.createFromFile(fontAssetPath);
                        if (Trace.isEnabled()) {
                            Trace.write('Could not create builder for ' + fontFamily, Trace.categories.Error, Trace.messageType.error);
                        }
                    }
                }
                else {
                    result = android.graphics.Typeface.createFromFile(fontAssetPath);
                }
            }
            catch (e) {
                if (Trace.isEnabled()) {
                    Trace.write('Error loading font asset: ' + fontAssetPath, Trace.categories.Error, Trace.messageType.error);
                }
            }
        }
        // The value will be null if there has already been an attempt to load the font but failed
        typefaceCache.set(cacheKey, result);
    }
    return result;
}
function createTypeface(font) {
    const fontFamilies = parseFontFamily(font.fontFamily);
    const fontWeightNum = getNumericFontWeight(font.fontWeight);
    let result;
    for (const fontFamily of fontFamilies) {
        switch (fontFamily.toLowerCase()) {
            case genericFontFamilies.serif:
                result = android.graphics.Typeface.create(android.graphics.Typeface.SERIF, fontWeightNum, font.isItalic);
                break;
            case genericFontFamilies.sansSerif:
            case genericFontFamilies.system:
                result = android.graphics.Typeface.create(android.graphics.Typeface.SANS_SERIF, fontWeightNum, font.isItalic);
                break;
            case genericFontFamilies.monospace:
                result = android.graphics.Typeface.create(android.graphics.Typeface.MONOSPACE, fontWeightNum, font.isItalic);
                break;
            default: {
                result = loadFontFromFile(fontFamily, font);
                if (result) {
                    result = android.graphics.Typeface.create(result, fontWeightNum, font.isItalic);
                }
                break;
            }
        }
        // Found the font!
        if (result) {
            break;
        }
    }
    if (!result) {
        result = android.graphics.Typeface.create(android.graphics.Typeface.SANS_SERIF, fontWeightNum, font.isItalic);
    }
    return result;
}
function createTypefaceLegacy(font) {
    const fontFamilies = parseFontFamily(font.fontFamily);
    const fontWeight = font.fontWeight;
    // https://stackoverflow.com/questions/19691530/valid-values-for-androidfontfamily-and-what-they-map-to
    const fontSuffix = getFontWeightSuffix(fontWeight);
    let result;
    let fontStyle = 0;
    if (font.isBold) {
        fontStyle |= android.graphics.Typeface.BOLD;
    }
    if (font.isItalic) {
        fontStyle |= android.graphics.Typeface.ITALIC;
    }
    for (const fontFamily of fontFamilies) {
        switch (fontFamily.toLowerCase()) {
            case genericFontFamilies.serif:
                result = android.graphics.Typeface.create('serif' + fontSuffix, fontStyle);
                break;
            case genericFontFamilies.sansSerif:
            case genericFontFamilies.system:
                result = android.graphics.Typeface.create('sans-serif' + fontSuffix, fontStyle);
                break;
            case genericFontFamilies.monospace:
                result = android.graphics.Typeface.create('monospace' + fontSuffix, fontStyle);
                break;
            default: {
                result = loadFontFromFile(fontFamily, font);
                if (result && fontStyle) {
                    result = android.graphics.Typeface.create(result, fontStyle);
                }
                break;
            }
        }
        // Found the font!
        if (result) {
            break;
        }
    }
    if (!result) {
        result = android.graphics.Typeface.create('sans-serif' + fontSuffix, fontStyle);
    }
    return result;
}
function getFontWeightSuffix(fontWeight) {
    if (typeof fontWeight === 'number') {
        fontWeight = (fontWeight + '');
    }
    switch (fontWeight) {
        case FontWeight.THIN:
            return SDK_VERSION >= 16 ? '-thin' : '';
        case FontWeight.EXTRA_LIGHT:
        case FontWeight.LIGHT:
            return SDK_VERSION >= 16 ? '-light' : '';
        case FontWeight.NORMAL:
        case '400':
        case undefined:
        case null:
            return '';
        case FontWeight.MEDIUM:
        case FontWeight.SEMI_BOLD:
            return SDK_VERSION >= 21 ? '-medium' : '';
        case FontWeight.BOLD:
        case '700':
        case FontWeight.EXTRA_BOLD:
            return '';
        case FontWeight.BLACK:
            return SDK_VERSION >= 21 ? '-black' : '';
        default:
            throw new Error(`Invalid font weight: "${fontWeight}"`);
    }
}
function getNumericFontWeight(fontWeight) {
    let value;
    if (typeof fontWeight === 'number') {
        value = fontWeight;
    }
    else {
        switch (fontWeight) {
            case FontWeight.NORMAL:
            case undefined:
            case null:
                value = 400;
                break;
            case FontWeight.BOLD:
                value = 700;
                break;
            default:
                value = parseInt(fontWeight);
                break;
        }
    }
    return value;
}
//# sourceMappingURL=font.android.js.map