package com.insidesecure.drm.android.reference.activities;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.util.AttributeSet;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;

public class MultiSelectionSpinner extends Spinner implements OnMultiChoiceClickListener
{
    String[] _items = null;
    boolean[] mSelection = null;

    private boolean mEnableNoneValue = false;
    private boolean mAtLeastOneMustBeSelected = false;
    private ListView mListViewInAlertDialog;

    ArrayAdapter<String> simple_adapter;

    public MultiSelectionSpinner(Context context)
    {
        super(context);

        simple_adapter = new ArrayAdapter<String>(context,
                android.R.layout.simple_spinner_item);
        super.setAdapter(simple_adapter);
    }

    public MultiSelectionSpinner(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        simple_adapter = new ArrayAdapter<String>(context,
                android.R.layout.simple_spinner_item);
        super.setAdapter(simple_adapter);
    }

    public void setAtLeastOneMustBeSelected(final boolean atLeastOneMustBeSelected) {
        mAtLeastOneMustBeSelected = atLeastOneMustBeSelected;
    }

    public void setEnableNoneValue(final boolean enableNoneValue) {
        mEnableNoneValue = enableNoneValue;
    }

    public void onClick(DialogInterface dialog, int which, boolean isChecked)
    {
        if (mSelection != null && which < mSelection.length)
        {
            mSelection[which] = isChecked;

            if (isChecked && mEnableNoneValue) {

                if (which != 0) {
                    // if any of the item is selected,
                    // None should be automatically deselected
                    mSelection[0] = false;
                    mListViewInAlertDialog.setItemChecked(0, false);
                } else {
                    // if None is selected,
                    // All items should be automatically deselected
                    for(int i = 1;i<mSelection.length;i++) {
                        mSelection[i] = false;
                        mListViewInAlertDialog.setItemChecked(i, false);
                    }
                }
            }

            if (mAtLeastOneMustBeSelected) {
                boolean isAnySelected = false;
                for(boolean selectedItems : mSelection) {
                    if(selectedItems) {
                        isAnySelected = true;
                    }
                }
                if(!isAnySelected){
                    mSelection[0] = true;
                    mListViewInAlertDialog.setItemChecked(0, true);
                }
            }

            simple_adapter.clear();
            simple_adapter.add(buildSelectedItemString());
        }
        else
        {
            throw new IllegalArgumentException(
                    "Argument 'which' is out of bounds.");
        }
    }

    @Override
    public boolean performClick()
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setMultiChoiceItems(_items, mSelection, this);
        mListViewInAlertDialog = builder.show().getListView();
        return true;
    }

    @Override
    public void setAdapter(SpinnerAdapter adapter)
    {
        throw new RuntimeException(
                "setAdapter is not supported by MultiSelectSpinner.");
    }

    public void setItems(String[] items)
    {
        _items = items;
        mSelection = new boolean[_items.length];
        simple_adapter.clear();
        simple_adapter.add(_items[0]);
        Arrays.fill(mSelection, false);
    }

    public void setItems(List<String> items)
    {
        _items = items.toArray(new String[items.size()]);
        mSelection = new boolean[_items.length];
        simple_adapter.clear();
        simple_adapter.add(_items[0]);
        Arrays.fill(mSelection, false);
    }

    public void setSelection(String[] selection)
    {
        for (String cell : selection)
        {
            for (int j = 0; j < _items.length; ++j)
            {
                if (_items[j].equals(cell))
                {
                    mSelection[j] = true;
                }
            }
        }
    }

    public void setSelection(List<String> selection)
    {
        for (int i = 0; i < mSelection.length; i++)
        {
            mSelection[i] = false;
        }
        for (String sel : selection)
        {
            for (int j = 0; j < _items.length; ++j)
            {
                if (_items[j].equals(sel))
                {
                    mSelection[j] = true;
                }
            }
        }
        simple_adapter.clear();
        simple_adapter.add(buildSelectedItemString());
    }

    public void setSelection(int index)
    {
        for (int i = 0; i < mSelection.length; i++)
        {
            mSelection[i] = false;
        }
        if (index >= 0 && index < mSelection.length)
        {
            mSelection[index] = true;
        }
        else
        {
            throw new IllegalArgumentException("Index " + index
                    + " is out of bounds.");
        }
        simple_adapter.clear();
        simple_adapter.add(buildSelectedItemString());
    }

    public void setSelection(int[] selectedIndicies)
    {
        for (int i = 0; i < mSelection.length; i++)
        {
            mSelection[i] = false;
        }
        for (int index : selectedIndicies)
        {
            if (index >= 0 && index < mSelection.length)
            {
                mSelection[index] = true;
            }
            else
            {
                throw new IllegalArgumentException("Index " + index
                        + " is out of bounds.");
            }
        }
        simple_adapter.clear();
        simple_adapter.add(buildSelectedItemString());
    }

    public List<String> getSelectedStrings()
    {
        List<String> selection = new LinkedList<String>();
        for (int i = 0; i < _items.length; ++i)
        {
            if (mSelection[i])
            {
                selection.add(_items[i]);
            }
        }
        return selection;
    }

    public List<Integer> getSelectedIndicies()
    {
        List<Integer> selection = new LinkedList<Integer>();
        for (int i = 0; i < _items.length; ++i)
        {
            if (mSelection[i])
            {
                selection.add(i);
            }
        }
        return selection;
    }

    private String buildSelectedItemString()
    {
        StringBuilder sb = new StringBuilder();
        boolean foundOne = false;

        for (int i = 0; i < _items.length; ++i)
        {
            if (mSelection[i])
            {
                if (foundOne)
                {
                    sb.append(", ");
                }
                foundOne = true;

                sb.append(_items[i]);
            }
        }
        return sb.toString();
    }

    public String getSelectedItemsAsString()
    {
        StringBuilder sb = new StringBuilder();
        boolean foundOne = false;

        for (int i = 0; i < _items.length; ++i)
        {
            if (mSelection[i])
            {
                if (foundOne)
                {
                    sb.append(", ");
                }
                foundOne = true;
                sb.append(_items[i]);
            }
        }
        return sb.toString();
    }
}
