/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.res;

import com.android.SdkConstants;
import com.android.ide.common.rendering.api.ArrayResourceValue;
import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.DensityBasedResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.PluralsResourceValue;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceNamespace;
import com.android.ide.common.rendering.api.ResourceNamespace.Resolver;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.ResourceValueImpl;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.android.UnresolvedResourceValue;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.ResourceHelper;
import com.android.layoutlib.bridge.util.NinePatchInputStream;
import com.android.ninepatch.NinePatch;
import com.android.resources.ResourceType;
import com.android.resources.ResourceUrl;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import com.android.tools.layoutlib.annotations.VisibleForTesting;
import com.android.util.Pair;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.icu.text.PluralRules;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.LruCache;
import android.util.TypedValue;
import android.view.DisplayAdjustments;
import android.view.ViewGroup.LayoutParams;

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.WeakHashMap;

import static android.content.res.AssetManager.ACCESS_STREAMING;
import static com.android.SdkConstants.ANDROID_PKG;
import static com.android.SdkConstants.PREFIX_RESOURCE_REF;

@SuppressWarnings("deprecation")
public class Resources_Delegate {
    private static WeakHashMap<Resources, LayoutlibCallback> sLayoutlibCallbacks =
            new WeakHashMap<>();
    private static WeakHashMap<Resources, BridgeContext> sContexts = new WeakHashMap<>();

    // TODO: This cache is cleared every time a render session is disposed. Look into making this
    // more long lived.
    private static LruCache<String, Drawable.ConstantState> sDrawableCache = new LruCache<>(50);

    public static Resources initSystem(@NonNull BridgeContext context,
            @NonNull AssetManager assets,
            @NonNull DisplayMetrics metrics,
            @NonNull Configuration config,
            @NonNull LayoutlibCallback layoutlibCallback) {
        assert Resources.mSystem == null  :
                "Resources_Delegate.initSystem called twice before disposeSystem was called";
        Resources resources = new Resources(Resources_Delegate.class.getClassLoader());
        resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()));
        sContexts.put(resources, Objects.requireNonNull(context));
        sLayoutlibCallbacks.put(resources, Objects.requireNonNull(layoutlibCallback));
        return Resources.mSystem = resources;
    }

    /** Returns the {@link BridgeContext} associated to the given {@link Resources} */
    @VisibleForTesting
    @NonNull
    public static BridgeContext getContext(@NonNull Resources resources) {
        assert sContexts.containsKey(resources) :
                "Resources_Delegate.getContext called before initSystem";
        return sContexts.get(resources);
    }

    /** Returns the {@link LayoutlibCallback} associated to the given {@link Resources} */
    @VisibleForTesting
    @NonNull
    public static LayoutlibCallback getLayoutlibCallback(@NonNull Resources resources) {
        assert sLayoutlibCallbacks.containsKey(resources) :
                "Resources_Delegate.getLayoutlibCallback called before initSystem";
        return sLayoutlibCallbacks.get(resources);
    }

    /**
     * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects around that
     * would prevent us from unloading the library.
     */
    public static void disposeSystem() {
        sDrawableCache.evictAll();
        sContexts.clear();
        sLayoutlibCallbacks.clear();
        Resources.mSystem = null;
    }

    public static BridgeTypedArray newTypeArray(Resources resources, int numEntries) {
        return new BridgeTypedArray(resources, getContext(resources), numEntries);
    }

    private static ResourceReference getResourceInfo(Resources resources, int id) {
        // first get the String related to this id in the framework
        ResourceReference resourceInfo = Bridge.resolveResourceId(id);

        assert Resources.mSystem != null : "Resources_Delegate.initSystem wasn't called";
        // Set the layoutlib callback and context for resources
        if (resources != Resources.mSystem &&
                (!sContexts.containsKey(resources) || !sLayoutlibCallbacks.containsKey(resources))) {
            sLayoutlibCallbacks.put(resources, getLayoutlibCallback(Resources.mSystem));
            sContexts.put(resources, getContext(Resources.mSystem));
        }

        if (resourceInfo == null) {
            // Didn't find a match in the framework? Look in the project.
            resourceInfo = getLayoutlibCallback(resources).resolveResourceId(id);
        }

        return resourceInfo;
    }

    private static Pair<String, ResourceValue> getResourceValue(Resources resources, int id) {
        ResourceReference resourceInfo = getResourceInfo(resources, id);

        if (resourceInfo != null) {
            String attributeName = resourceInfo.getName();
            RenderResources renderResources = getContext(resources).getRenderResources();
            ResourceValue value = renderResources.getResolvedResource(resourceInfo);
            if (value == null) {
                // Unable to resolve the attribute, just leave the unresolved value.
                value = new ResourceValueImpl(resourceInfo.getNamespace(),
                        resourceInfo.getResourceType(), attributeName, attributeName);
            }
            return Pair.of(attributeName, value);
        }

        return null;
    }

    @LayoutlibDelegate
    static Drawable getDrawable(Resources resources, int id) {
        return getDrawable(resources, id, null);
    }

    @LayoutlibDelegate
    static Drawable getDrawable(Resources resources, int id, Theme theme) {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);
        if (value != null) {
            String key = value.getSecond().getValue();

            Drawable.ConstantState constantState = key != null ? sDrawableCache.get(key) : null;
            Drawable drawable;
            if (constantState != null) {
                drawable = constantState.newDrawable(resources, theme);
            } else {
                drawable =
                        ResourceHelper.getDrawable(value.getSecond(), getContext(resources), theme);

                if (key != null) {
                    sDrawableCache.put(key, drawable.getConstantState());
                }
            }

            return drawable;
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static int getColor(Resources resources, int id) {
        return getColor(resources, id, null);
    }

    @LayoutlibDelegate
    static int getColor(Resources resources, int id, Theme theme) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resourceValue = value.getSecond();
            try {
                return ResourceHelper.getColor(resourceValue.getValue());
            } catch (NumberFormatException e) {
                // Check if the value passed is a file. If it is, mostly likely, user is referencing
                // a color state list from a place where they should reference only a pure color.
                AssetRepository repository = getAssetRepository(resources);
                String message;
                if (repository.isFileResource(resourceValue.getValue())) {
                    String resource = (resourceValue.isFramework() ? "@android:" : "@") + "color/"
                            + resourceValue.getName();
                    message = "Hexadecimal color expected, found Color State List for " + resource;
                } else {
                    message = e.getMessage();
                }
                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, message, e, null);
                return 0;
            }
        }

        // Suppress possible NPE. getColorStateList will never return null, it will instead
        // throw an exception, but intelliJ can't figure that out
        //noinspection ConstantConditions
        return getColorStateList(resources, id, theme).getDefaultColor();
    }

    @LayoutlibDelegate
    static ColorStateList getColorStateList(Resources resources, int id) throws NotFoundException {
        return getColorStateList(resources, id, null);
    }

    @LayoutlibDelegate
    static ColorStateList getColorStateList(Resources resources, int id, Theme theme)
            throws NotFoundException {
        Pair<String, ResourceValue> resValue = getResourceValue(resources, id);

        if (resValue != null) {
            ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
                    getContext(resources), theme);
            if (stateList != null) {
                return stateList;
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static CharSequence getText(Resources resources, int id, CharSequence def) {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            assert resValue != null;
            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    return v;
                }
            }
        }

        return def;
    }

    @LayoutlibDelegate
    static CharSequence getText(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            assert resValue != null;
            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    return v;
                }
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static CharSequence[] getTextArray(Resources resources, int id) throws NotFoundException {
        ResourceValue resValue = getArrayResourceValue(resources, id);
        if (resValue == null) {
            // Error already logged by getArrayResourceValue.
            return new CharSequence[0];
        }
        if (resValue instanceof ArrayResourceValue) {
            ArrayResourceValue arrayValue = (ArrayResourceValue) resValue;
            return resolveValues(resources, arrayValue);
        }
        RenderResources renderResources = getContext(resources).getRenderResources();
        return new CharSequence[] { renderResources.resolveResValue(resValue).getValue() };
    }

    @LayoutlibDelegate
    static String[] getStringArray(Resources resources, int id) throws NotFoundException {
        ResourceValue resValue = getArrayResourceValue(resources, id);
        if (resValue == null) {
            // Error already logged by getArrayResourceValue.
            return new String[0];
        }
        if (resValue instanceof ArrayResourceValue) {
            ArrayResourceValue arv = (ArrayResourceValue) resValue;
            return resolveValues(resources, arv);
        }
        return new String[] { resolveReference(resources, resValue) };
    }

    /**
     * Resolves each element in resValue and returns an array of resolved values. The returned array
     * may contain nulls.
     */
    @NonNull
    static String[] resolveValues(@NonNull Resources resources,
            @NonNull ArrayResourceValue resValue) {
        String[] result = new String[resValue.getElementCount()];
        for (int i = 0; i < resValue.getElementCount(); i++) {
            String value = resValue.getElement(i);
            result[i] = resolveReference(resources, value,
                    resValue.getNamespace(), resValue.getNamespaceResolver());
        }
        return result;
    }

    @LayoutlibDelegate
    static int[] getIntArray(Resources resources, int id) throws NotFoundException {
        ResourceValue rv = getArrayResourceValue(resources, id);
        if (rv == null) {
            // Error already logged by getArrayResourceValue.
            return new int[0];
        }
        if (rv instanceof ArrayResourceValue) {
            ArrayResourceValue resValue = (ArrayResourceValue) rv;
            int n = resValue.getElementCount();
            int[] values = new int[n];
            for (int i = 0; i < n; i++) {
                String element = resolveReference(resources, resValue.getElement(i),
                        resValue.getNamespace(), resValue.getNamespaceResolver());
                if (element != null) {
                    try {
                        if (element.startsWith("#")) {
                            // This integer represents a color (starts with #).
                            values[i] = Color.parseColor(element);
                        } else {
                            values[i] = getInt(element);
                        }
                    } catch (NumberFormatException e) {
                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
                                "Integer resource array contains non-integer value: \"" + element +
                                        "\"", null);
                    } catch (IllegalArgumentException e) {
                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
                                "Integer resource array contains wrong color format: \"" + element +
                                        "\"", null);
                    }
                } else {
                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
                            "Integer resource array contains non-integer value: \"" +
                                    resValue.getElement(i) + "\"", null);
                }
            }
            return values;
        }

        // This is an older IDE that can only give us the first element of the array.
        String firstValue = resolveReference(resources, rv);
        if (firstValue != null) {
            try {
                return new int[]{getInt(firstValue)};
            } catch (NumberFormatException e) {
                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
                        "Integer resource array contains non-integer value: \"" + firstValue + "\"",
                        null);
                return new int[1];
            }
        } else {
            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
                    "Integer resource array contains non-integer value: \"" +
                            rv.getValue() + "\"", null);
            return new int[1];
        }
    }

    /**
     * Try to find the ArrayResourceValue for the given id.
     * <p/>
     * If the ResourceValue found is not of type {@link ResourceType#ARRAY}, the method logs an
     * error and return null. However, if the ResourceValue found has type {@code
     * ResourceType.ARRAY}, but the value is not an instance of {@link ArrayResourceValue}, the
     * method returns the ResourceValue. This happens on older versions of the IDE, which did not
     * parse the array resources properly.
     * <p/>
     *
     * @throws NotFoundException if no resource if found
     */
    @Nullable
    private static ResourceValue getArrayResourceValue(Resources resources, int id)
            throws NotFoundException {
        Pair<String, ResourceValue> v = getResourceValue(resources, id);

        if (v != null) {
            ResourceValue resValue = v.getSecond();

            assert resValue != null;
            if (resValue != null) {
                final ResourceType type = resValue.getResourceType();
                if (type != ResourceType.ARRAY) {
                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
                            String.format(
                                    "Resource with id 0x%1$X is not an array resource, but %2$s",
                                    id, type == null ? "null" : type.getDisplayName()),
                            null);
                    return null;
                }
                if (!(resValue instanceof ArrayResourceValue)) {
                    Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED,
                            "Obtaining resource arrays via getTextArray, getStringArray or getIntArray is not fully supported in this version of the IDE.",
                            null);
                }
                return resValue;
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @Nullable
    private static String resolveReference(@NonNull Resources resources, @Nullable String value,
            @NonNull ResourceNamespace contextNamespace,
            @NonNull ResourceNamespace.Resolver resolver) {
        if (value != null) {
            ResourceValue resValue = new UnresolvedResourceValue(value, contextNamespace, resolver);
            return resolveReference(resources, resValue);
        }
        return null;
    }

    @Nullable
    private static String resolveReference(@NonNull Resources resources,
            @NonNull ResourceValue value) {
        RenderResources renderResources = getContext(resources).getRenderResources();
        ResourceValue resolvedValue = renderResources.resolveResValue(value);
        return resolvedValue == null ? null : resolvedValue.getValue();
    }

    @LayoutlibDelegate
    static XmlResourceParser getLayout(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> v = getResourceValue(resources, id);

        if (v != null) {
            ResourceValue value = v.getSecond();

            try {
                BridgeXmlBlockParser parser =
                        ResourceHelper.getXmlBlockParser(getContext(resources), value);
                if (parser != null) {
                    return parser;
                }
            } catch (XmlPullParserException e) {
                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
                        "Failed to parse " + value.getValue(), e, null /*data*/);
                // we'll return null below.
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id, "layout");

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static XmlResourceParser getAnimation(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> v = getResourceValue(resources, id);

        if (v != null) {
            ResourceValue value = v.getSecond();

            try {
                return ResourceHelper.getXmlBlockParser(getContext(resources), value);
            } catch (XmlPullParserException e) {
                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
                        "Failed to parse " + value.getValue(), e, null /*data*/);
                // we'll return null below.
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static TypedArray obtainAttributes(Resources resources, AttributeSet set, int[] attrs) {
        return getContext(resources).obtainStyledAttributes(set, attrs);
    }

    @LayoutlibDelegate
    static TypedArray obtainAttributes(Resources resources, Resources.Theme theme, AttributeSet
            set, int[] attrs) {
        return Resources.obtainAttributes_Original(resources, theme, set, attrs);
    }

    @LayoutlibDelegate
    static TypedArray obtainTypedArray(Resources resources, int id) throws NotFoundException {
        BridgeContext context = getContext(resources);
        ResourceReference reference = context.resolveId(id);
        RenderResources renderResources = context.getRenderResources();
        ResourceValue value = renderResources.getResolvedResource(reference);

        if (!(value instanceof ArrayResourceValue)) {
            throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
        }

        ArrayResourceValue arrayValue = (ArrayResourceValue) value;
        int length = arrayValue.getElementCount();
        ResourceNamespace namespace = arrayValue.getNamespace();
        BridgeTypedArray typedArray = newTypeArray(resources, length);

        for (int i = 0; i < length; i++) {
            ResourceValue elementValue;
            ResourceUrl resourceUrl = ResourceUrl.parse(arrayValue.getElement(i));
            if (resourceUrl != null) {
                ResourceReference elementRef =
                  resourceUrl.resolve(namespace, arrayValue.getNamespaceResolver());
                elementValue = renderResources.getResolvedResource(elementRef);
            } else {
                elementValue = new ResourceValueImpl(namespace, ResourceType.STRING, "element" + i,
                  arrayValue.getElement(i));
            }
            typedArray.bridgeSetValue(i, elementValue.getName(), namespace, i, elementValue);
        }

        typedArray.sealArray();
        return typedArray;
    }

    @LayoutlibDelegate
    static float getDimension(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            assert resValue != null;
            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    if (v.equals(BridgeConstants.MATCH_PARENT) ||
                            v.equals(BridgeConstants.FILL_PARENT)) {
                        return LayoutParams.MATCH_PARENT;
                    } else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
                        return LayoutParams.WRAP_CONTENT;
                    }
                    TypedValue tmpValue = new TypedValue();
                    if (ResourceHelper.parseFloatAttribute(
                            value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
                            tmpValue.type == TypedValue.TYPE_DIMENSION) {
                        return tmpValue.getDimension(resources.getDisplayMetrics());
                    }
                }
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return 0;
    }

    @LayoutlibDelegate
    static int getDimensionPixelOffset(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            assert resValue != null;
            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    TypedValue tmpValue = new TypedValue();
                    if (ResourceHelper.parseFloatAttribute(
                            value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
                            tmpValue.type == TypedValue.TYPE_DIMENSION) {
                        return TypedValue.complexToDimensionPixelOffset(tmpValue.data,
                                resources.getDisplayMetrics());
                    }
                }
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return 0;
    }

    @LayoutlibDelegate
    static int getDimensionPixelSize(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            assert resValue != null;
            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    TypedValue tmpValue = new TypedValue();
                    if (ResourceHelper.parseFloatAttribute(
                            value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
                            tmpValue.type == TypedValue.TYPE_DIMENSION) {
                        return TypedValue.complexToDimensionPixelSize(tmpValue.data,
                                resources.getDisplayMetrics());
                    }
                }
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return 0;
    }

    @LayoutlibDelegate
    static int getInteger(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            assert resValue != null;
            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    try {
                        return getInt(v);
                    } catch (NumberFormatException e) {
                        // return exception below
                    }
                }
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return 0;
    }

    @LayoutlibDelegate
    static float getFloat(Resources resources, int id) {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    try {
                        return Float.parseFloat(v);
                    } catch (NumberFormatException ignore) {
                    }
                }
            }
        }
        return 0;
    }

    @LayoutlibDelegate
    static boolean getBoolean(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resValue = value.getSecond();

            if (resValue != null) {
                String v = resValue.getValue();
                if (v != null) {
                    return Boolean.parseBoolean(v);
                }
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return false;
    }

    @LayoutlibDelegate
    static String getResourceEntryName(Resources resources, int resid) throws NotFoundException {
        ResourceReference resourceInfo = getResourceInfo(resources, resid);
        if (resourceInfo != null) {
            return resourceInfo.getName();
        }
        throwException(resid, null);
        return null;
    }

    @LayoutlibDelegate
    static String getResourceName(Resources resources, int resid) throws NotFoundException {
        ResourceReference resourceInfo = getResourceInfo(resources, resid);
        if (resourceInfo != null) {
            String packageName = getPackageName(resourceInfo, resources);
            return packageName + ':' + resourceInfo.getResourceType().getName() + '/' +
                    resourceInfo.getName();
        }
        throwException(resid, null);
        return null;
    }

    @LayoutlibDelegate
    static String getResourcePackageName(Resources resources, int resid) throws NotFoundException {
        ResourceReference resourceInfo = getResourceInfo(resources, resid);
        if (resourceInfo != null) {
            return getPackageName(resourceInfo, resources);
        }
        throwException(resid, null);
        return null;
    }

    @LayoutlibDelegate
    static String getResourceTypeName(Resources resources, int resid) throws NotFoundException {
        ResourceReference resourceInfo = getResourceInfo(resources, resid);
        if (resourceInfo != null) {
            return resourceInfo.getResourceType().getName();
        }
        throwException(resid, null);
        return null;
    }

    private static String getPackageName(ResourceReference resourceInfo, Resources resources) {
        String packageName = resourceInfo.getNamespace().getPackageName();
        if (packageName == null) {
            packageName = getContext(resources).getPackageName();
            if (packageName == null) {
                packageName = SdkConstants.APP_PREFIX;
            }
        }
        return packageName;
    }

    @LayoutlibDelegate
    static String getString(Resources resources, int id, Object... formatArgs)
            throws NotFoundException {
        String s = getString(resources, id);
        if (s != null) {
            return String.format(s, formatArgs);

        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static String getString(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null && value.getSecond().getValue() != null) {
            return value.getSecond().getValue();
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static String getQuantityString(Resources resources, int id, int quantity) throws
            NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            if (value.getSecond() instanceof PluralsResourceValue) {
                PluralsResourceValue pluralsResourceValue = (PluralsResourceValue) value.getSecond();
                PluralRules pluralRules = PluralRules.forLocale(resources.getConfiguration().getLocales()
                        .get(0));
                String strValue = pluralsResourceValue.getValue(pluralRules.select(quantity));
                if (strValue == null) {
                    strValue = pluralsResourceValue.getValue(PluralRules.KEYWORD_OTHER);
                }

                return strValue;
            }
            else {
                return value.getSecond().getValue();
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static String getQuantityString(Resources resources, int id, int quantity, Object... formatArgs)
            throws NotFoundException {
        String raw = getQuantityString(resources, id, quantity);
        return String.format(resources.getConfiguration().getLocales().get(0), raw, formatArgs);
    }

    @LayoutlibDelegate
    static CharSequence getQuantityText(Resources resources, int id, int quantity) throws
            NotFoundException {
        return getQuantityString(resources, id, quantity);
    }

    @LayoutlibDelegate
    static Typeface getFont(Resources resources, int id) throws
            NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);
        if (value != null) {
            return ResourceHelper.getFont(value.getSecond(), getContext(resources), null);
        }

        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static Typeface getFont(Resources resources, TypedValue outValue, int id) throws
            NotFoundException {
        ResourceValue resVal = getResourceValue(resources, id, outValue);
        if (resVal != null) {
            return ResourceHelper.getFont(resVal, getContext(resources), null);
        }

        throwException(resources, id);
        return null; // This is not used since the method above always throws.
    }

    @LayoutlibDelegate
    static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs)
            throws NotFoundException {
        getResourceValue(resources, id, outValue);
    }

    private static ResourceValue getResourceValue(Resources resources, int id, TypedValue outValue)
            throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            ResourceValue resVal = value.getSecond();
            String v = resVal != null ? resVal.getValue() : null;

            if (v != null) {
                if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue,
                        false /*requireUnit*/)) {
                    return resVal;
                }
                if (resVal instanceof DensityBasedResourceValue) {
                    outValue.density =
                            ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue();
                }

                // else it's a string
                outValue.type = TypedValue.TYPE_STRING;
                outValue.string = v;
                return resVal;
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);
        return null; // This is not used since the method above always throws.
    }

    @LayoutlibDelegate
    static void getValue(Resources resources, String name, TypedValue outValue, boolean resolveRefs)
            throws NotFoundException {
        throw new UnsupportedOperationException();
    }

    @LayoutlibDelegate
    static void getValueForDensity(Resources resources, int id, int density, TypedValue outValue,
            boolean resolveRefs) throws NotFoundException {
        getValue(resources, id, outValue, resolveRefs);
    }

    @LayoutlibDelegate
    static int getAttributeSetSourceResId(@Nullable AttributeSet set) {
        // Not supported in layoutlib
        return Resources.ID_NULL;
    }

    @LayoutlibDelegate
    static XmlResourceParser getXml(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> v = getResourceValue(resources, id);

        if (v != null) {
            ResourceValue value = v.getSecond();

            try {
                return ResourceHelper.getXmlBlockParser(getContext(resources), value);
            } catch (XmlPullParserException e) {
                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
                        "Failed to parse " + value.getValue(), e, null /*data*/);
                // we'll return null below.
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static XmlResourceParser loadXmlResourceParser(Resources resources, int id,
            String type) throws NotFoundException {
        return resources.loadXmlResourceParser_Original(id, type);
    }

    @LayoutlibDelegate
    static XmlResourceParser loadXmlResourceParser(Resources resources, String file, int id,
            int assetCookie, String type) throws NotFoundException {
        // even though we know the XML file to load directly, we still need to resolve the
        // id so that we can know if it's a platform or project resource.
        // (mPlatformResouceFlag will get the result and will be used later).
        Pair<String, ResourceValue> result = getResourceValue(resources, id);

        ResourceNamespace layoutNamespace;
        if (result != null && result.getSecond() != null) {
            layoutNamespace = result.getSecond().getNamespace();
        } else {
            // We need to pick something, even though the resource system never heard about a layout
            // with this numeric id.
            layoutNamespace = ResourceNamespace.RES_AUTO;
        }

        try {
            XmlPullParser parser = ParserFactory.create(file);
            return new BridgeXmlBlockParser(parser, getContext(resources), layoutNamespace);
        } catch (XmlPullParserException e) {
            NotFoundException newE = new NotFoundException();
            newE.initCause(e);
            throw newE;
        }
    }

    @LayoutlibDelegate
    static InputStream openRawResource(Resources resources, int id) throws NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id);

        if (value != null) {
            String path = value.getSecond().getValue();
            if (path != null) {
                return openRawResource(resources, path);
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static InputStream openRawResource(Resources resources, int id, TypedValue value)
            throws NotFoundException {
        getValue(resources, id, value, true);

        String path = value.string.toString();
        return openRawResource(resources, path);
    }

    private static InputStream openRawResource(Resources resources, String path)
            throws NotFoundException {
        AssetRepository repository = getAssetRepository(resources);
        try {
            InputStream stream = repository.openNonAsset(0, path, ACCESS_STREAMING);
            if (stream == null) {
                throw new NotFoundException(path);
            }
            // If it's a nine-patch return a custom input stream so that
            // other methods (mainly bitmap factory) can detect it's a 9-patch
            // and actually load it as a 9-patch instead of a normal bitmap.
            if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
                return new NinePatchInputStream(stream);
            }
            return stream;
        } catch (IOException e) {
            NotFoundException exception = new NotFoundException();
            exception.initCause(e);
            throw exception;
        }
    }

    @LayoutlibDelegate
    static AssetFileDescriptor openRawResourceFd(Resources resources, int id)
            throws NotFoundException {
        throw new UnsupportedOperationException();
    }

    @VisibleForTesting
    @Nullable
    static ResourceUrl resourceUrlFromName(
            @NonNull String name, @Nullable String defType, @Nullable String defPackage) {
        int colonIdx = name.indexOf(':');
        int slashIdx = name.indexOf('/');

        if (colonIdx != -1 && slashIdx != -1) {
            // Easy case
            return ResourceUrl.parse(PREFIX_RESOURCE_REF + name);
        }

        if (colonIdx == -1 && slashIdx == -1) {
            if (defType == null) {
                throw new IllegalArgumentException("name does not define a type an no defType was" +
                        " passed");
            }

            // It does not define package or type
            return ResourceUrl.parse(
                    PREFIX_RESOURCE_REF + (defPackage != null ? defPackage + ":" : "") + defType +
                            "/" + name);
        }

        if (colonIdx != -1) {
            if (defType == null) {
                throw new IllegalArgumentException("name does not define a type an no defType was" +
                        " passed");
            }
            // We have package but no type
            String pkg = name.substring(0, colonIdx);
            ResourceType type = ResourceType.getEnum(defType);
            return type != null ? ResourceUrl.create(pkg, type, name.substring(colonIdx + 1)) :
                    null;
        }

        ResourceType type = ResourceType.getEnum(name.substring(0, slashIdx));
        if (type == null) {
            return null;
        }
        // We have type but no package
        return ResourceUrl.create(defPackage,
                type,
                name.substring(slashIdx + 1));
    }

    @LayoutlibDelegate
    static int getIdentifier(Resources resources, String name, String defType, String defPackage) {
        if (name == null) {
            return 0;
        }

        ResourceUrl url = resourceUrlFromName(name, defType, defPackage);
        if (url != null) {
            if (ANDROID_PKG.equals(url.namespace)) {
                return Bridge.getResourceId(url.type, url.name);
            }

            if (getContext(resources).getPackageName().equals(url.namespace)) {
                return getLayoutlibCallback(resources).getOrGenerateResourceId(
                        new ResourceReference(ResourceNamespace.RES_AUTO, url.type, url.name));
            }
        }

        return 0;
    }

    /**
     * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource
     * type.
     *
     * @param id the id of the resource
     * @param expectedType the type of resource that was expected
     *
     * @throws NotFoundException
     */
    private static void throwException(Resources resources, int id, @Nullable String expectedType)
            throws NotFoundException {
        throwException(id, getResourceInfo(resources, id), expectedType);
    }

    private static void throwException(Resources resources, int id) throws NotFoundException {
        throwException(resources, id, null);
    }

    private static void throwException(int id, @Nullable ResourceReference resourceInfo) {
        throwException(id, resourceInfo, null);
    }
    private static void throwException(int id, @Nullable ResourceReference resourceInfo,
            @Nullable String expectedType) {
        String message;
        if (resourceInfo != null) {
            message = String.format(
                    "Could not find %1$s resource matching value 0x%2$X (resolved name: %3$s) in current configuration.",
                    resourceInfo.getResourceType(), id, resourceInfo.getName());
        } else {
            message = String.format("Could not resolve resource value: 0x%1$X.", id);
        }

        if (expectedType != null) {
            message += " Or the resolved value was not of type " + expectedType + " as expected.";
        }
        throw new NotFoundException(message);
    }

    private static int getInt(String v) throws NumberFormatException {
        int radix = 10;
        if (v.startsWith("0x")) {
            v = v.substring(2);
            radix = 16;
        } else if (v.startsWith("0")) {
            radix = 8;
        }
        return Integer.parseInt(v, radix);
    }

    private static AssetRepository getAssetRepository(Resources resources) {
        BridgeContext context = getContext(resources);
        BridgeAssetManager assetManager = context.getAssets();
        return assetManager.getAssetRepository();
    }
}
