package org.wikipedia;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.util.LruCache;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * An LRU Cache that can be parcelled.
 *
 * Will throw up a RuntimeError if passed things that are not parcellable.
 *
 * Can be considered sortof a messy hack, but grrr Android.
 *
 * FIXME: This also resets the LRUcounters when recreated.
 *
 * V can either be a String, Parcelable or a List<Parcelable>
 */
public class ParcelableLruCache<V> extends LruCache<String, V>  implements Parcelable {
    private static final int TYPE_LIST = 1;
    private static final int TYPE_PARCELABLE = 2;
    private static final int TYPE_STRING = 3;

    private final int type;
    public ParcelableLruCache(int maxSize, Class valueClass) {
        super(maxSize);
        if (valueClass.equals(String.class)) {
            type = TYPE_STRING;
        } else if (valueClass.isAssignableFrom(List.class)) {
            type = TYPE_LIST;
        } else {
            type = TYPE_PARCELABLE;
        }
    }

    private ParcelableLruCache(Parcel in) {
        super(in.readInt());
        type = in.readInt();
        Bundle contents = in.readBundle();
        contents.setClassLoader(getClass().getClassLoader());
        Set<String> keys = contents.keySet();
        for (String key : keys) {
            switch (type) {
                case TYPE_LIST:
                    put(key, (V) contents.getParcelableArrayList(key));
                    break;
                case TYPE_PARCELABLE:
                    put(key, (V) contents.getParcelable(key));
                    break;
                case TYPE_STRING:
                    put(key, (V) contents.getString(key));
                    break;
                default:
                    throw new RuntimeException("Unknown key type encountered " + type);
            }
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(maxSize());
        dest.writeInt(type);
        Map<String, V> snapshot = snapshot();
        Bundle bundle = new Bundle();
        for (Map.Entry<String, V> entry : snapshot.entrySet()) {
            switch (type) {
                case TYPE_LIST:
                    bundle.putParcelableArrayList(entry.getKey(), (ArrayList)entry.getValue());
                    break;
                case TYPE_PARCELABLE:
                    bundle.putParcelable(entry.getKey(), (Parcelable) entry.getValue());
                    break;
                case TYPE_STRING:
                    bundle.putString(entry.getKey(), (String) entry.getValue());
                    break;
                default:
                    throw new RuntimeException("Unknown key type encountered " + type);
            }
        }
        dest.writeBundle(bundle);
    }

    public static final Parcelable.Creator<ParcelableLruCache> CREATOR
            = new Parcelable.Creator<ParcelableLruCache>() {
        @Override
        public ParcelableLruCache createFromParcel(Parcel in) {
            return new ParcelableLruCache(in);
        }

        @Override
        public ParcelableLruCache[] newArray(int size) {
            return new ParcelableLruCache[size];
        }
    };
}

@@ -614,17 +614,16 @@
 ring, V%3E
- 
  impleme
@@ -856,16 +856,19 @@
 e, Class
+%3C?%3E
  valueCl
@@ -1478,32 +1478,77 @@
 case TYPE_LIST:%0A
+                    //noinspection unchecked%0A
                 
@@ -1660,32 +1660,77 @@
 YPE_PARCELABLE:%0A
+                    //noinspection unchecked%0A
                 
@@ -1829,32 +1829,77 @@
 se TYPE_STRING:%0A
+                    //noinspection unchecked%0A
                 
@@ -2553,65 +2553,161 @@
     
-bundle.putParcelableArrayList(entry.getKey(), (ArrayList)
+//noinspection unchecked%0A                    bundle.putParcelableArrayList(entry.getKey(),%0A                            (ArrayList%3C? extends Parcelable%3E) 
 entr
@@ -3283,16 +3283,19 @@
 LruCache
+%3C?%3E
 %3E CREATO
@@ -3351,16 +3351,19 @@
 LruCache
+%3C?%3E
 %3E() %7B%0A  
@@ -3411,16 +3411,19 @@
 LruCache
+%3C?%3E
  createF
@@ -3486,16 +3486,18 @@
 LruCache
+%3C%3E
 (in);%0A  
@@ -3556,16 +3556,19 @@
 LruCache
+%3C?%3E
 %5B%5D newAr
@@ -3624,16 +3624,19 @@
 LruCache
+%3C?%3E
 %5Bsize%5D;%0A

add parameters to raw types