package hibergui.assoc;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;

import hibergui.Form;
import hibergui.I18n;

import org.apache.commons.beanutils.PropertyUtils;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.List;

public abstract class M2MEdit_List<T, C extends Collection<T>> extends M2MEdit<T, C> {

    protected List lst;
    protected Button btnRemove;

    protected ListViewer lsv;

    protected final String editProp;

    public M2MEdit_List(Form<?> form, Composite cptParent, int style, String prop, String name, String editProp) {
		super(form, cptParent, style, prop, name);

		this.editProp = editProp;
		
		lst.addKeyListener(lsn_WIDGET_KEY);
		lst.addFocusListener(lsn_WIDGET_FOCUS);
        lst.addTraverseListener(lsn_TRAVERSE);
		btnRemove.addKeyListener(lsn_WIDGET_KEY);
		btnRemove.addFocusListener(lsn_WIDGET_FOCUS);
        btnRemove.addTraverseListener(lsn_TRAVERSE);

		lsv = new ListViewer(lst);
        lsv.setContentProvider(new IStructuredContentProvider() {
            @SuppressWarnings("unchecked")
			public Object[] getElements(Object inputElement) {
                return ((C) inputElement).toArray();
            }
            public void dispose() {}
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
        });
        lsv.setLabelProvider(
                new LabelProvider() {
                    @SuppressWarnings("unchecked")
					public String getText(Object element) {
                        return M2MEdit_List.this.getItemText((T) element);
                    }
                }
        );
        lsv.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                M2MEdit_List.this.selectionChanged();
            }
        });
        
		btnAssoc.setEnabled(true);
        btnRemove.setEnabled(false);
	}

	protected void selectionChanged() {
        btnRemove.setEnabled(lst.getSelectionIndex() != -1);
    }
	
	protected List createList(final Composite cptParent) {
		return new List(cptParent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
	}
	
	@Override
	protected Button createAssocDialogButton(final Composite cptParent) {
		super.createAssocDialogButton(cptParent);
        btnAssoc.setText(I18n.get("add"));
        return btnAssoc;
	}
	
	protected Button createRemoveButton(final Composite cptParent) {
		btnRemove = new Button(cptParent, SWT.PUSH);
        btnRemove.setText(I18n.get("remove"));
        btnRemove.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
            	remove(lst.getSelectionIndices());
                set(extract());
            }
        });        
		return btnRemove;
	}
    
	protected final String getItemText(T item) {
		if (item == null)
			return "<NULL>";
    	try {
    		return PropertyUtils.getProperty(item, editProp).toString();
    	} catch (IllegalAccessException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	} catch (InvocationTargetException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	} catch (NoSuchMethodException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    	return "<N/A>";
    }
    
    public void add(T[] elements) {
    	if (elements == null)
    		return;
    	for (T t: elements)
    		value.add(t);
        lsv.refresh(false);
        markDirty();
    }
    
    public void remove(int[] indices) {
    	if (indices == null)
    		return;
    	for (int i: indices)
    		value.remove(lsv.getElementAt(i));
        lsv.refresh(false);
        markDirty();
    }

    @Override
    public C extract() {
//        return lsv.getInput();
    	return value;
    }
    
//  public void refresh(T element) {
//  	lsv.refresh(element);
//  }
    
    @Override
    public void setEnabled(boolean b) {
    	super.setEnabled(b);
        lst.setEnabled(b);
        if (lst.getSelectionCount() != 0)
        	btnRemove.setEnabled(b);
    }    

    @Override
    public boolean isEnabled() {
        return lst.isEnabled();
    }
    
    @Override
    public boolean setFocus() {
        return lst.setFocus();
    }
    
    @Override
	public void setBackground(Color clr) {
    	lsv.getControl().setBackground(clr);
	}
}
