package com.oracle.truffle.js.runtime.builtins.intl;
import java.util.LinkedList;
import java.util.List;
import com.ibm.icu.number.FormattedNumber;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.text.PluralRules.PluralType;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.js.builtins.intl.PluralRulesFunctionBuiltins;
import com.oracle.truffle.js.builtins.intl.PluralRulesPrototypeBuiltins;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.JSRealm;
import com.oracle.truffle.js.runtime.JSRuntime;
import com.oracle.truffle.js.runtime.builtins.JSConstructor;
import com.oracle.truffle.js.runtime.builtins.JSConstructorFactory;
import com.oracle.truffle.js.runtime.builtins.JSNonProxy;
import com.oracle.truffle.js.runtime.builtins.JSObjectFactory;
import com.oracle.truffle.js.runtime.builtins.PrototypeSupplier;
import com.oracle.truffle.js.runtime.objects.JSAttributes;
import com.oracle.truffle.js.runtime.objects.JSObjectUtil;
import com.oracle.truffle.js.runtime.util.IntlUtil;
public final class JSPluralRules extends JSNonProxy implements JSConstructorFactory.Default.WithFunctions, PrototypeSupplier {
public static final String CLASS_NAME = "PluralRules";
public static final String PROTOTYPE_NAME = "PluralRules.prototype";
public static final JSPluralRules INSTANCE = new JSPluralRules();
private JSPluralRules() {
}
public static boolean isJSPluralRules(Object obj) {
return obj instanceof JSPluralRulesObject;
}
@Override
public String getClassName() {
return CLASS_NAME;
}
@Override
public String getClassName(DynamicObject object) {
return getClassName();
}
@Override
public DynamicObject createPrototype(JSRealm realm, DynamicObject ctor) {
JSContext ctx = realm.getContext();
DynamicObject pluralRulesPrototype = JSObjectUtil.createOrdinaryPrototypeObject(realm);
JSObjectUtil.putConstructorProperty(ctx, pluralRulesPrototype, ctor);
JSObjectUtil.putFunctionsFromContainer(realm, pluralRulesPrototype, PluralRulesPrototypeBuiltins.BUILTINS);
JSObjectUtil.putToStringTag(pluralRulesPrototype, "Intl.PluralRules");
return pluralRulesPrototype;
}
@Override
public Shape makeInitialShape(JSContext ctx, DynamicObject prototype) {
Shape initialShape = JSObjectUtil.getProtoChildShape(prototype, INSTANCE, ctx);
return initialShape;
}
public static JSConstructor createConstructor(JSRealm realm) {
return INSTANCE.createConstructorAndPrototype(realm, PluralRulesFunctionBuiltins.BUILTINS);
}
public static DynamicObject create(JSContext context) {
InternalState state = new InternalState();
JSRealm realm = context.getRealm();
JSObjectFactory factory = context.getPluralRulesFactory();
JSPluralRulesObject obj = new JSPluralRulesObject(factory.getShape(realm), state);
factory.initProto(obj, realm);
assert isJSPluralRules(obj);
return context.trackAllocation(obj);
}
public static PluralRules getPluralRulesProperty(DynamicObject obj) {
return getInternalState(obj).getPluralRules();
}
public static LocalizedNumberFormatter getNumberFormatter(DynamicObject obj) {
return getInternalState(obj).getNumberFormatter();
}
@TruffleBoundary
public static String select(DynamicObject pluralRulesObj, Object n) {
PluralRules pluralRules = getPluralRulesProperty(pluralRulesObj);
LocalizedNumberFormatter numberFormatter = getNumberFormatter(pluralRulesObj);
Number number = JSRuntime.toNumber(n);
FormattedNumber formattedNumber = numberFormatter.format(number);
return pluralRules.select(formattedNumber);
}
public static class InternalState extends JSNumberFormat.BasicInternalState {
private String type;
private PluralRules pluralRules;
private final List<Object> pluralCategories = new LinkedList<>();
@Override
void fillResolvedOptions(JSContext context, DynamicObject result) {
JSObjectUtil.defineDataProperty(result, IntlUtil.LOCALE, getLocale(), JSAttributes.getDefault());
JSObjectUtil.defineDataProperty(result, IntlUtil.TYPE, type, JSAttributes.getDefault());
super.fillResolvedOptions(context, result);
JSObjectUtil.defineDataProperty(result, "pluralCategories", JSRuntime.createArrayFromList(context, pluralCategories), JSAttributes.getDefault());
}
@TruffleBoundary
public void initializePluralRules() {
pluralRules = PluralRules.forLocale(getJavaLocale(), IntlUtil.ORDINAL.equals(type) ? PluralType.ORDINAL : PluralType.CARDINAL);
pluralCategories.addAll(pluralRules.getKeywords());
}
public PluralRules getPluralRules() {
return pluralRules;
}
public void setType(String type) {
this.type = type;
}
}
@TruffleBoundary
public static DynamicObject resolvedOptions(JSContext context, DynamicObject pluralRulesObj) {
InternalState state = getInternalState(pluralRulesObj);
return state.toResolvedOptionsObject(context);
}
public static InternalState getInternalState(DynamicObject obj) {
assert isJSPluralRules(obj);
return ((JSPluralRulesObject) obj).getInternalState();
}
@Override
public DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getPluralRulesPrototype();
}
}