package org.ccci.gto.android.common.util;

import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import org.ccci.gto.android.common.compat.util.LocaleCompat;
import org.jetbrains.annotations.Contract;

import java.lang.reflect.Array;
import java.util.Locale;

public class BundleUtils {
    @Nullable
    @SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"})
    public static <T extends Parcelable> T[] getParcelableArray(@NonNull final Bundle bundle,
                                                                @Nullable final String key,
                                                                @NonNull final Class<T> clazz) {
        final Parcelable[] raw = bundle.getParcelableArray(key);
        if (raw == null) {
            return null;
        }

        // copy all objects to typed array
        final T[] arr = (T[]) Array.newInstance(clazz, raw.length);
        System.arraycopy(raw, 0, arr, 0, raw.length);
        return arr;
    }

    public static void putEnum(@NonNull final Bundle bundle, @Nullable final String key,
                               @Nullable final Enum<?> value) {
        bundle.putString(key, value != null ? value.name() : null);
    }

    @Nullable
    public static <T extends Enum<T>> T getEnum(@NonNull final Bundle bundle, @NonNull final Class<T> type,
                                                @Nullable final String key) {
        return getEnum(bundle, type, key, null);
    }

    @Nullable
    @Contract("_, _, _, !null -> !null")
    public static <T extends Enum<T>> T getEnum(@NonNull final Bundle bundle, @NonNull final Class<T> type,
                                                @Nullable final String key, @Nullable final T defValue) {
        final String raw = bundle.getString(key);
        if (raw == null) {
            return defValue;
        }

        try {
            return Enum.valueOf(type, raw);
        } catch (final IllegalArgumentException e) {
            return defValue;
        }
    }

    public static void putLocale(@NonNull final Bundle bundle, @Nullable final String key,
                                 @Nullable final Locale locale) {
        bundle.putString(key, locale != null ? LocaleCompat.toLanguageTag(locale) : null);
    }

    @Nullable
    public static Locale getLocale(@NonNull final Bundle bundle, @Nullable final String key) {
        return getLocale(bundle, key, null);
    }

    @Nullable
    @Contract("_, _, !null -> !null")
    public static Locale getLocale(@NonNull final Bundle bundle, @Nullable final String key,
                                   @Nullable final Locale defValue) {
        final String raw = bundle.getString(key);
        if (raw == null) {
            return defValue;
        }
        return LocaleCompat.forLanguageTag(raw);
    }

    public static void putLocaleArray(@NonNull final Bundle bundle, @Nullable final String key,
                                      @Nullable final Locale[] locales) {
        final String[] array;
        if (locales != null) {
            array = new String[locales.length];
            for (int i = 0; i < locales.length; i++) {
                array[i] = locales[i] != null ? LocaleCompat.toLanguageTag(locales[i]) : null;
            }
        } else {
            array = null;
        }
        bundle.putStringArray(key, array);
    }

    @Nullable
    public static Locale[] getLocaleArray(@NonNull final Bundle bundle, @Nullable final String key) {
        final String[] raw = bundle.getStringArray(key);
        final Locale[] locales;
        if (raw != null) {
            locales = new Locale[raw.length];
            for (int i = 0; i < raw.length; i++) {
                locales[i] = raw[i] != null ? LocaleCompat.forLanguageTag(raw[i]) : null;
            }
        } else {
            locales = null;
        }
        return locales;
    }
}

@@ -178,16 +178,47 @@
 ullable;
+%0Aimport android.text.TextUtils;
 %0A%0Aimport
@@ -3080,24 +3080,657 @@
  locales) %7B%0A
+        putLocaleArray(bundle, key, locales, false);%0A    %7D%0A%0A    /**%0A     * Store an array of Locales in the provided Bundle%0A     *%0A     * @param bundle       The bundle to store the locale array in%0A     * @param key          The key to store the locale array under%0A     * @param locales      The locales being put in the bundle%0A     * @param singleString Flag indicating if the locale array should be stored as a single string%0A     */%0A    public static void putLocaleArray(@NonNull final Bundle bundle, @Nullable final String key,%0A                                      @Nullable final Locale%5B%5D locales, final boolean singleString) %7B%0A
         fina
@@ -4035,32 +4035,168 @@
 null;%0A        %7D%0A
+%0A        if (singleString) %7B%0A            bundle.putString(key, array != null ? TextUtils.join(%22,%22, array) : null);%0A        %7D else %7B%0A    
         bundle.p
@@ -4218,24 +4218,34 @@
 ey, array);%0A
+        %7D%0A
     %7D%0A%0A    @
@@ -4355,38 +4355,32 @@
  key) %7B%0A        
-final 
 String%5B%5D raw = b
@@ -4398,32 +4398,193 @@
 ringArray(key);%0A
+        if (raw == null) %7B%0A            final String flat = bundle.getString(key);%0A            raw = flat != null ? TextUtils.split(flat, %22,%22) : null;%0A        %7D%0A%0A
         final Lo

support using a single string for persisting an array of Locales.