package com.nullware.android.fortunequote;

import java.util.HashSet;

import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.ListPreference;
import android.util.AttributeSet;

/**
 * A {@link ListPreference} that displays a list of entries as a dialog and
 * allows multiple selections.  The selected items are stored as a string in
 * the SharedPreferences, using | (pipe) as a delimiter.
 */
public class ListPreferenceMultiSelect extends ListPreference {

    private boolean[] selectedEntries;

    public ListPreferenceMultiSelect(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.selectedEntries = new boolean[getEntries().length];
    }
    public ListPreferenceMultiSelect(Context context) {
        this(context, null);
    }

    @Override
    public void setEntries(CharSequence[] entries) {
        super.setEntries(entries);
        this.selectedEntries = new boolean[entries.length];
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        CharSequence[] entries = getEntries();
        CharSequence[] entryValues = getEntryValues();
        if (entries == null || entryValues == null || entries.length != entryValues.length) {
            throw new IllegalStateException("ListPreferenceMultiSelect requires an entries array and an entryValues array which are both the same length");
        }
        restoreCheckedEntries();
        builder.setMultiChoiceItems(entries, this.selectedEntries,
                new DialogInterface.OnMultiChoiceClickListener() {
                    public void onClick(DialogInterface dialog, int which, boolean val) {
                        selectedEntries[which] = val;
                    }
        });
    }

    /**
     * Return an array of strings parsed from a single pipe delimited string.
     *
     * @param value Pipe delimited string
     * @return parsed string array
     */
    public static String[] parseValue(CharSequence value) {
        if (value.length() > 0) {
            return ((String)value).split("\\|");
        } else {
            return new String[0];
        }
    }

    private void restoreCheckedEntries() {
        CharSequence[] entryValues = getEntryValues();
        String[] values = parseValue(getValue());
        HashSet<String> valuesSet = new HashSet<String>();
        for (int i = 0; i < values.length; i++) {
            valuesSet.add(values[i]);
        }
        for (int i = 0; i < entryValues.length; i++) {
            if (valuesSet.contains(entryValues[i])) {
                this.selectedEntries[i] = true;
            }
        }
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        CharSequence[] entryValues = getEntryValues();
        if (positiveResult && entryValues != null) {
            StringBuffer value = new StringBuffer();
            for (int i = 0; i < entryValues.length; i++) {
                if (this.selectedEntries[i]) {
                    value.append(entryValues[i]).append("|");
                }
            }
            String str = value.toString();
            if (str.length() > 0) str = str.substring(0, str.length() - 1);
            if (callChangeListener(str)) {
                setValue(str);
            }
        }
    }

}