namespace Graphics2DText {

    @localized('en', 'FontResource')
    @localized('es', 'ESFontResource')
    @localized('jp', 'JPFontResource')
    class FontResource {
        field _sourceType;
        field _source;

        @private
        constructor(sourceType, source) {
            this._sourceType = sourceType;
            this._source = source;
        }

        @localized('en', 'getRenderer')
        @localized('es', 'ESgetRenderer')
        @localized('jp', 'JPgetRenderer')
        function getRenderer() {
            return new FontRenderer(this);
        }

        static field _cache = {};

        static function _getKey(sourceType, source) {
            return sourceType + source;
        }

        static function _get(sourceType, source) {
            key = sourceType + source;
            font = FontResource._cache.get(key);
            if (font == null) {
                font = new FontResource(sourceType, source);
                FontResource._cache[key] = font;
            }
            return font;
        }

        @localized('en', 'fromResource')
        @localized('es', 'ESfromResource')
        @localized('jp', 'JPfromResource')
        static function fromResource(path) {
            if (!$lib_graphics2dtext_isResourceAvailable(path)) {
                throw new FontNotFoundException("Font resource not found: '" + path + "'");
            }
            return FontResource._get(FontSourceType.RESOURCE, path);
        }

        @localized('en', 'fromDisk')
        @localized('es', 'ESfromDisk')
        @localized('jp', 'JPfromDisk')
        static function fromDisk(path) {
            throw new NotImplementedException();
        }

        @localized('en', 'fromSystem')
        @localized('es', 'ESfromSystem')
        @localized('jp', 'JPfromSystem')
        static function fromSystem(name) {
            if (!FontResource.isSystemFontPresent(name)) {
                throw new FontNotFoundException("Font not installed: '" + name + "'");
            }
            return FontResource._get(FontSourceType.SYSTEM, name);
        }

        @localized('en', 'isSystemFontPresent')
        @localized('es', 'ESisSystemFontPresent')
        @localized('jp', 'JPisSystemFontPresent')
        static function isSystemFontPresent(name) {
            return $lib_graphics2dtext_isSystemFontPresent(name);
        }

        // TODO: implement this
        @localized('en', 'getDefaultSerifFont')
        @localized('es', 'ESgetDefaultSerifFont')
        @localized('jp', 'JPgetDefaultSerifFont')
        static function getDefaultSerifFont() {
            return FontResource._get(FontSourceType.DEFAULT, FontClass.SERIF);
        }

        // TODO: implement this
        @localized('en', 'getDefaultSansSerifFont')
        @localized('es', 'ESgetDefaultSansSerifFont')
        @localized('jp', 'JPgetDefaultSansSerifFont')
        static function getDefaultSansSerifFont() {
            return FontResource._get(FontSourceType.DEFAULT, FontClass.SANS_SERIF);
        }

        // TODO: implement this
        @localized('en', 'getDefaultMonospaceFont')
        @localized('es', 'ESgetDefaultMonospaceFont')
        @localized('jp', 'JPgetDefaultMonospaceFont')
        static function getDefaultMonospaceFont() {
            return FontResource._get(FontSourceType.DEFAULT, FontClass.MONOSPACE);
        }
    }
}
