import android.content.res.Resources;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.annotation.StyleRes;

import java.util.Random;

@SuppressWarnings("UnusedDeclaration")
public class Flow {
    public void testLiterals(Resources resources) {
        resources.getDrawable(0); // OK
        resources.getDrawable(-1); // OK
        resources.getDrawable(10); // ERROR
    }

    public void testConstants(Resources resources) {
        resources.getDrawable(R.drawable.my_drawable); // OK
        resources.getDrawable(R.string.my_string); // ERROR
    }

    public void testLocalAnnotation() {
        myMethod(R.string.my_string, null); // ERROR
    }

    private void myMethod(@DrawableRes int arg, Resources resources) {
        resources.getDrawable(R.string.my_string); // ERROR
    }

    private void testAnyRes() {
        myAnyResMethod(R.drawable.my_drawable); // OK
        myAnyResMethod(R.string.my_string); // OK
        myAnyResMethod(50); // ERROR
    }

    private void myAnyResMethod(@android.support.annotation.AnyRes int arg) {
    }

    public void testFields(String fileExt, Resources resources) {
        int mimeIconId = MimeTypes.styleAndDrawable;
        resources.getDrawable(mimeIconId); // OK

        int s1 = MimeTypes.style;
        resources.getDrawable(s1); // ERROR
        int s2 = MimeTypes.styleAndDrawable;
        resources.getDrawable(s2); // OK
        int w3 = MimeTypes.drawable;
        resources.getDrawable(w3); // OK

        // Direct reference
        resources.getDrawable(MimeTypes.style); // ERROR
        resources.getDrawable(MimeTypes.styleAndDrawable); // OK
        resources.getDrawable(MimeTypes.drawable); // OK
    }

    public void testCalls(String fileExt, Resources resources) {
        int mimeIconId = MimeTypes.getIconForExt(fileExt);
        resources.getDrawable(mimeIconId); // OK
        resources.getDrawable(MimeTypes.getInferredString()); // OK (wrong but can't infer type)
        resources.getDrawable(MimeTypes.getInferredDrawable()); // OK
        resources.getDrawable(MimeTypes.getAnnotatedString()); // Error
        resources.getDrawable(MimeTypes.getAnnotatedDrawable()); // OK
        resources.getDrawable(MimeTypes.getUnknownType()); // OK (unknown/uncertain)
    }

    public void testFlow() {
        int x = R.string.my_string;
        int z = x;
        myMethod(z, null); // ERROR

        int w = MY_RESOURCE;
        myMethod(w, null); // ERROR
    }

    private static final int MY_RESOURCE = R.string.my_string;

    private static class MimeTypes {
        @android.support.annotation.StyleRes
        @android.support.annotation.DrawableRes
        public static int styleAndDrawable;

        @android.support.annotation.StyleRes
        public static int style;

        @android.support.annotation.DrawableRes
        public static int drawable;

        @android.support.annotation.DrawableRes
        public static int getIconForExt(String ext) {
            return R.drawable.my_drawable;
        }

        public static int getInferredString() {
            // Implied string - can we handle this?
            return R.string.my_string;
        }

        public static int getInferredDrawable() {
            // Implied drawable - can we handle this?
            return R.drawable.my_drawable;
        }

        @android.support.annotation.StringRes
        public static int getAnnotatedString() {
            return R.string.my_string;
        }

        @android.support.annotation.DrawableRes
        public static int getAnnotatedDrawable() {
            return R.drawable.my_drawable;
        }

        public static int getUnknownType() {
            return new Random(1000).nextInt();
        }
    }

    public static final class R {
        public static final class drawable {
            public static final int my_drawable =0x7f020057;
        }
        public static final class string {
            public static final int my_string =0x7f0a000e;
        }
    }
}
