/*******************************************************************************
 * Copyright (c) 2010 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 ******************************************************************************/
package org.eclipse.scout.rt.client.ui.form.fields.listbox;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.scout.commons.CollectionUtility;
import org.eclipse.scout.commons.ConfigurationUtility;
import org.eclipse.scout.commons.TriState;
import org.eclipse.scout.commons.TypeCastUtility;
import org.eclipse.scout.commons.annotations.ClassId;
import org.eclipse.scout.commons.annotations.ConfigOperation;
import org.eclipse.scout.commons.annotations.ConfigProperty;
import org.eclipse.scout.commons.annotations.Order;
import org.eclipse.scout.commons.annotations.OrderedComparator;
import org.eclipse.scout.commons.exception.ProcessingException;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.rt.client.extension.ui.form.fields.IFormFieldExtension;
import org.eclipse.scout.rt.client.extension.ui.form.fields.listbox.IListBoxExtension;
import org.eclipse.scout.rt.client.extension.ui.form.fields.listbox.ListBoxChains.ListBoxFilterLookupResultChain;
import org.eclipse.scout.rt.client.extension.ui.form.fields.listbox.ListBoxChains.ListBoxLoadTableDataChain;
import org.eclipse.scout.rt.client.extension.ui.form.fields.listbox.ListBoxChains.ListBoxPopulateTableChain;
import org.eclipse.scout.rt.client.extension.ui.form.fields.listbox.ListBoxChains.ListBoxPrepareLookupChain;
import org.eclipse.scout.rt.client.services.lookup.FormFieldProvisioningContext;
import org.eclipse.scout.rt.client.services.lookup.ILookupCallProvisioningService;
import org.eclipse.scout.rt.client.ui.basic.cell.Cell;
import org.eclipse.scout.rt.client.ui.basic.cell.ICell;
import org.eclipse.scout.rt.client.ui.basic.table.AbstractTable;
import org.eclipse.scout.rt.client.ui.basic.table.AbstractTableRowBuilder;
import org.eclipse.scout.rt.client.ui.basic.table.ITable;
import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
import org.eclipse.scout.rt.client.ui.basic.table.ITableRowFilter;
import org.eclipse.scout.rt.client.ui.basic.table.TableAdapter;
import org.eclipse.scout.rt.client.ui.basic.table.TableEvent;
import org.eclipse.scout.rt.client.ui.basic.table.TableRow;
import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractBooleanColumn;
import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractColumn;
import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
import org.eclipse.scout.rt.client.ui.form.IForm;
import org.eclipse.scout.rt.client.ui.form.IFormFieldVisitor;
import org.eclipse.scout.rt.client.ui.form.fields.AbstractFormField;
import org.eclipse.scout.rt.client.ui.form.fields.AbstractValueField;
import org.eclipse.scout.rt.client.ui.form.fields.CompositeFieldUtility;
import org.eclipse.scout.rt.client.ui.form.fields.GridData;
import org.eclipse.scout.rt.client.ui.form.fields.ICompositeField;
import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
import org.eclipse.scout.rt.shared.ScoutTexts;
import org.eclipse.scout.rt.shared.data.basic.FontSpec;
import org.eclipse.scout.rt.shared.data.form.ValidationRule;
import org.eclipse.scout.rt.shared.data.form.fields.AbstractFormFieldData;
import org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData;
import org.eclipse.scout.rt.shared.services.common.code.ICodeType;
import org.eclipse.scout.rt.shared.services.common.exceptionhandler.IExceptionHandlerService;
import org.eclipse.scout.rt.shared.services.lookup.CodeLookupCall;
import org.eclipse.scout.rt.shared.services.lookup.ILookupCall;
import org.eclipse.scout.rt.shared.services.lookup.ILookupRow;
import org.eclipse.scout.rt.shared.services.lookup.LookupRow;
import org.eclipse.scout.service.SERVICES;

@ClassId("3dc8747d-19eb-4c0a-b5fc-c3dc2ad0783d")
public abstract class AbstractListBox<KEY> extends AbstractValueField<Set<KEY>> implements IListBox<KEY> {
  private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractListBox.class);

  private ITable m_table;
  private ILookupCall<KEY> m_lookupCall;
  private Class<? extends ICodeType<?, KEY>> m_codeTypeClass;
  private boolean m_valueTableSyncActive;
  private ITableRowFilter m_checkedRowsFilter;
  private ITableRowFilter m_activeRowsFilter;
  // children
  private List<IFormField> m_fields;
  private Map<Class<? extends IFormField>, IFormField> m_movedFormFieldsByClass;

  public AbstractListBox() {
    this(true);
  }

  public AbstractListBox(boolean callInitializer) {
    super(callInitializer);
  }

  /*
   * Configuration
   */
  /**
   * Configure a lookup call to fill listbox with values.
   *
   * @return Lookup call of listbox
   */
  @ConfigProperty(ConfigProperty.LOOKUP_CALL)
  @Order(240)
  @ValidationRule(ValidationRule.LOOKUP_CALL)
  protected Class<? extends ILookupCall<KEY>> getConfiguredLookupCall() {
    return null;
  }

  @ConfigProperty(ConfigProperty.CODE_TYPE)
  @Order(250)
  @ValidationRule(ValidationRule.CODE_TYPE)
  protected Class<? extends ICodeType<?, KEY>> getConfiguredCodeType() {
    return null;
  }

  @Override
  @Order(210)
  @ConfigProperty(ConfigProperty.BOOLEAN)
  protected boolean getConfiguredAutoAddDefaultMenus() {
    return false;
  }

  @ConfigProperty(ConfigProperty.ICON_ID)
  @Order(230)
  protected String getConfiguredIconId() {
    return null;
  }

  @ConfigProperty(ConfigProperty.BOOLEAN)
  @Order(260)
  protected boolean getConfiguredAutoLoad() {
    return true;
  }

  /**
   * @return true: a filter is added to the listbox table that only accepts rows
   *         that are active or checked.<br>
   *         Default is true<br>
   *         Affects {@link ITable#getFilteredRows()}
   */
  @ConfigProperty(ConfigProperty.BOOLEAN)
  @Order(270)
  protected boolean getConfiguredFilterActiveRows() {
    return false;
  }

  /**
   * @return true: a filter is added to the listbox table that only accepts
   *         checked rows<br>
   *         Default is false<br>
   *         Affects {@link ITable#getFilteredRows()}<br>
   */
  @ConfigProperty(ConfigProperty.BOOLEAN)
  @Order(280)
  protected boolean getConfiguredFilterCheckedRows() {
    return false;
  }

  @Override
  protected double getConfiguredGridWeightY() {
    return 1.0;
  }

  private List<Class<IFormField>> getConfiguredFields() {
    Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
    return ConfigurationUtility.filterClasses(dca, IFormField.class);
  }

  /**
   * On any value change or call to {@link #checkEmpty()} this method is called
   * to calculate if the field represents an empty state (semantics)
   * <p>
   */
  @Override
  protected boolean execIsEmpty() throws ProcessingException {
    return getValue().isEmpty();
  }

  /**
   * called before any lookup is performed
   */
  @ConfigOperation
  @Order(250)
  protected void execPrepareLookup(ILookupCall<KEY> call) throws ProcessingException {
  }

  /**
   * @param call
   *          that produced this result
   * @param result
   *          live list containing the result rows. Add, remove, set, replace
   *          and clear of entries in this list is supported
   */
  @ConfigOperation
  @Order(260)
  protected void execFilterLookupResult(ILookupCall<KEY> call, List<ILookupRow<KEY>> result) throws ProcessingException {
  }

  @ConfigOperation
  @Order(230)
  protected List<? extends ILookupRow<KEY>> execLoadTableData() throws ProcessingException {
    List<? extends ILookupRow<KEY>> data;
    // (1) get data by service
    if (getLookupCall() != null) {
      ILookupCall<KEY> call = SERVICES.getService(ILookupCallProvisioningService.class).newClonedInstance(getLookupCall(), new FormFieldProvisioningContext(AbstractListBox.this));
      prepareLookupCall(call);
      data = call.getDataByAll();
      data = filterLookupResult(call, data);
    }
    // (b) get data direct
    else {
      data = filterLookupResult(null, null);
    }
    return data;
  }

  /**
   * Intercepter is called after data was fetched from LookupCall and is adding
   * a table row for every LookupRow using IListBoxTable.createTableRow(row) and
   * ITable.addRows()
   * <p>
   * For most cases the override of just {@link #interceptLoadTableData()} is sufficient
   *
   * <pre>
   * List<ILookupRow<T>> data=execLoadTableData();
   * List<ITableRow> rows=new ArrayList();
   * if(data!=null){
   *   for(int i=0; i{@code<}data.length; i++){
   *     rows.add(createTableRow(data[i]));
   *   }
   * }
   * getTable().replaceRows(rows);
   * </pre>
   */
  @ConfigOperation
  @Order(240)
  protected void execPopulateTable() throws ProcessingException {
    List<? extends ILookupRow<KEY>> data = null;
    //sle Ticket 92'893: Listbox Master required. only run loadTable when master value is set
    if (!isMasterRequired() || getMasterValue() != null) {
      data = interceptLoadTableData();
    }
    List<ITableRow> rows = new ArrayList<ITableRow>();
    if (data != null) {
      for (ILookupRow<KEY> lr : data) {
        rows.add(getTableRowBuilder().createTableRow(lr));
      }
    }
    getTable().replaceRows(rows);
  }

  private Class<? extends ITable> getConfiguredTable() {
    Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
    List<Class<ITable>> tableClasses = ConfigurationUtility.filterClasses(dca, ITable.class);
    if (tableClasses.size() == 1) {
      return CollectionUtility.firstElement(tableClasses);
    }
    else {
      for (Class<ITable> tableClazz : tableClasses) {
        if (tableClazz.getDeclaringClass() != AbstractListBox.class) {
          return tableClazz;
        }
      }
      return null;
    }
  }

  @Override
  protected void execChangedMasterValue(Object newMasterValue) throws ProcessingException {
    setValue(null);
    loadListBoxData();
  }

  @Override
  protected void initConfig() {
    m_fields = CollectionUtility.emptyArrayList();
    m_movedFormFieldsByClass = new HashMap<Class<? extends IFormField>, IFormField>();
    super.initConfig();
    setFilterActiveRows(getConfiguredFilterActiveRows());
    setFilterActiveRowsValue(TriState.TRUE);
    setFilterCheckedRows(getConfiguredFilterCheckedRows());
    setFilterCheckedRowsValue(getConfiguredFilterCheckedRows());
    try {
      List<ITable> contributedTables = m_contributionHolder.getContributionsByClass(ITable.class);
      m_table = CollectionUtility.firstElement(contributedTables);
      if (m_table == null) {
        Class<? extends ITable> configuredTable = getConfiguredTable();
        if (configuredTable != null) {
          m_table = ConfigurationUtility.newInnerInstance(this, configuredTable);
        }
      }

      if (m_table != null) {
        if (m_table instanceof AbstractTable) {
          ((AbstractTable) m_table).setContainerInternal(this);
        }
        updateActiveRowsFilter();
        updateCheckedRowsFilter();
        m_table.addTableListener(new TableAdapter() {
          @Override
          public void tableChanged(TableEvent e) {
            switch (e.getType()) {
              case TableEvent.TYPE_ROWS_SELECTED: {
                if (!getTable().isCheckable()) {
                  syncTableToValue();
                }
                break;
              }
              case TableEvent.TYPE_ROWS_UPDATED: {
                if (getTable().isCheckable()) {
                  syncTableToValue();
                }
                break;
              }
            }
          }
        });
        // default icon
        if (m_table.getDefaultIconId() == null && this.getConfiguredIconId() != null) {
          m_table.setDefaultIconId(this.getConfiguredIconId());
        }
        m_table.setEnabled(isEnabled());
      }
      else {
        LOG.warn("there is no inner class of type ITable in " + getClass().getName());
      }
    }
    catch (Exception e) {
      SERVICES.getService(IExceptionHandlerService.class).handleException(new ProcessingException("error creating instance of class '" + getConfiguredTable().getName() + "'.", e));
    }
    // lookup call
    if (getConfiguredLookupCall() != null) {
      try {
        ILookupCall<KEY> call = getConfiguredLookupCall().newInstance();
        setLookupCall(call);
      }
      catch (Exception e) {
        SERVICES.getService(IExceptionHandlerService.class).handleException(new ProcessingException("error creating instance of class '" + getConfiguredLookupCall().getName() + "'.", e));
      }
    }
    // code type
    if (getConfiguredCodeType() != null) {
      setCodeTypeClass(getConfiguredCodeType());
    }
    // local property listener
    addPropertyChangeListener(new PropertyChangeListener() {
      @Override
      public void propertyChange(PropertyChangeEvent e) {
        if (m_table != null) {
          String name = e.getPropertyName();
          if (PROP_ENABLED.equals(name)) {
            m_table.setEnabled(isEnabled());
          }
          else if (PROP_FILTER_CHECKED_ROWS_VALUE.equals(name)) {
            updateCheckedRowsFilter();
          }
          else if (PROP_FILTER_ACTIVE_ROWS_VALUE.equals(name)) {
            updateActiveRowsFilter();
          }
        }
      }
    });
    // add fields
    List<Class<IFormField>> fieldClasses = getConfiguredFields();
    List<IFormField> contributedFields = m_contributionHolder.getContributionsByClass(IFormField.class);

    List<IFormField> fieldList = new ArrayList<IFormField>(fieldClasses.size() + contributedFields.size());
    for (Class<? extends IFormField> fieldClazz : fieldClasses) {
      try {
        IFormField f = ConfigurationUtility.newInnerInstance(this, fieldClazz);
        fieldList.add(f);
      }// end try
      catch (Throwable t) {
        SERVICES.getService(IExceptionHandlerService.class).handleException(new ProcessingException("error creating instance of class '" + fieldClazz.getName() + "'.", t));
      }
    }
    fieldList.addAll(contributedFields);
    Collections.sort(fieldList, new OrderedComparator());

    for (IFormField f : fieldList) {
      f.setParentFieldInternal(this);
    }
    m_fields = fieldList;
  }

  @Override
  public void addField(IFormField f) {
    CompositeFieldUtility.addField(f, this, m_fields);
  }

  @Override
  public void removeField(IFormField f) {
    CompositeFieldUtility.removeField(f, this, m_fields);
  }

  @Override
  public void moveFieldTo(IFormField f, ICompositeField newContainer) {
    CompositeFieldUtility.moveFieldTo(f, this, newContainer, m_movedFormFieldsByClass);
  }

  @Override
  public Map<Class<? extends IFormField>, IFormField> getMovedFields() {
    return Collections.unmodifiableMap(m_movedFormFieldsByClass);
  }

  @SuppressWarnings("unchecked")
  public ListBoxFilterBox getListBoxFilterBox() {
    return getFieldByClass(ListBoxFilterBox.class);
  }

  @Override
  protected void initFieldInternal() throws ProcessingException {
    getTable().initTable();
    if (getConfiguredAutoLoad()) {
      try {
        setValueChangeTriggerEnabled(false);
        //
        loadListBoxData();
      }
      finally {
        setValueChangeTriggerEnabled(true);
      }
    }
    super.initFieldInternal();
  }

  @Override
  protected void disposeFieldInternal() {
    super.disposeFieldInternal();
    getTable().disposeTable();
  }

  public AbstractTableRowBuilder<KEY> getTableRowBuilder() {
    return new P_TableRowBuilder();
  }

  @Override
  public final ITable getTable() {
    return m_table;
  }

  @Override
  public boolean isFilterCheckedRows() {
    return propertySupport.getPropertyBool(PROP_FILTER_CHECKED_ROWS);
  }

  @Override
  public void setFilterCheckedRows(boolean b) {
    propertySupport.setPropertyBool(PROP_FILTER_CHECKED_ROWS, b);
  }

  @Override
  public boolean getFilterCheckedRowsValue() {
    return propertySupport.getPropertyBool(PROP_FILTER_CHECKED_ROWS_VALUE);
  }

  @Override
  public void setFilterCheckedRowsValue(boolean b) {
    propertySupport.setPropertyBool(PROP_FILTER_CHECKED_ROWS_VALUE, b);
  }

  @Override
  public boolean isFilterActiveRows() {
    return propertySupport.getPropertyBool(PROP_FILTER_ACTIVE_ROWS);
  }

  @Override
  public void setFilterActiveRows(boolean b) {
    propertySupport.setPropertyBool(PROP_FILTER_ACTIVE_ROWS, b);
  }

  @Override
  public TriState getFilterActiveRowsValue() {
    return (TriState) propertySupport.getProperty(PROP_FILTER_ACTIVE_ROWS_VALUE);
  }

  @Override
  public void setFilterActiveRowsValue(TriState t) {
    if (t == null) {
      t = TriState.TRUE;
    }
    propertySupport.setProperty(PROP_FILTER_ACTIVE_ROWS_VALUE, t);
  }

  private void updateActiveRowsFilter() {
    try {
      getTable().setTableChanging(true);
      //
      if (m_activeRowsFilter != null) {
        getTable().removeRowFilter(m_activeRowsFilter);
        m_activeRowsFilter = null;
      }
      m_activeRowsFilter = new ActiveOrCheckedRowsFilter(getActiveColumnInternal(), getFilterActiveRowsValue());
      getTable().addRowFilter(m_activeRowsFilter);
    }
    finally {
      getTable().setTableChanging(false);
    }
  }

  private void updateCheckedRowsFilter() {
    try {
      getTable().setTableChanging(true);
      //
      if (m_checkedRowsFilter != null) {
        getTable().removeRowFilter(m_checkedRowsFilter);
        m_checkedRowsFilter = null;
      }
      if (getFilterCheckedRowsValue()) {
        m_checkedRowsFilter = new CheckedRowsFilter();
        getTable().addRowFilter(m_checkedRowsFilter);
      }
    }
    finally {
      getTable().setTableChanging(false);
    }
  }

  @Override
  public void loadListBoxData() throws ProcessingException {
    if (getTable() != null) {
      try {
        m_valueTableSyncActive = true;
        getTable().setTableChanging(true);
        //
        interceptPopulateTable();
      }
      finally {
        getTable().setTableChanging(false);
        m_valueTableSyncActive = false;
      }
      syncValueToTable();
    }
  }

  /**
   * do not use this internal method directly
   */
  @Override
  public final void prepareLookupCall(ILookupCall<KEY> call) throws ProcessingException {
    prepareLookupCallInternal(call);
    interceptPrepareLookup(call);
  }

  private List<ILookupRow<KEY>> filterLookupResult(ILookupCall<KEY> call, List<? extends ILookupRow<KEY>> data) throws ProcessingException {
    // create a copy for the custom filter method
    List<ILookupRow<KEY>> result = CollectionUtility.arrayList(data);
    interceptFilterLookupResult(call, result);
    Iterator<ILookupRow<KEY>> resultIt = result.iterator();
    while (resultIt.hasNext()) {
      ILookupRow<KEY> row = resultIt.next();
      if (row == null) {
        resultIt.remove();
      }
      else if (row.getKey() == null) {
        LOG.warn("The key of a lookup row may not be null. Row has been removed for list box '" + getClass().getName() + "'.");
        resultIt.remove();
      }
    }
    return result;
  }

  /**
   * do not use this internal method directly
   */
  private void prepareLookupCallInternal(ILookupCall<KEY> call) {
    call.setActive(TriState.UNDEFINED);
    //when there is a master value defined in the original call, don't set it to null when no master value is available
    if (getMasterValue() != null || getLookupCall() == null || getLookupCall().getMaster() == null) {
      call.setMaster(getMasterValue());
    }
  }

  @Override
  public final ILookupCall<KEY> getLookupCall() {
    return m_lookupCall;
  }

  @Override
  public void setLookupCall(ILookupCall<KEY> call) {
    m_lookupCall = call;
  }

  @Override
  public Class<? extends ICodeType<?, KEY>> getCodeTypeClass() {
    return m_codeTypeClass;
  }

  @Override
  public void setCodeTypeClass(Class<? extends ICodeType<?, KEY>> codeTypeClass) {
    m_codeTypeClass = codeTypeClass;
    // create lookup service call
    m_lookupCall = null;
    if (m_codeTypeClass != null) {
      m_lookupCall = CodeLookupCall.newInstanceByService(m_codeTypeClass);
    }
  }

  @Override
  protected void valueChangedInternal() {
    super.valueChangedInternal();
    syncValueToTable();
  }

  @Override
  protected String formatValueInternal(Set<KEY> validValue) {
    if (!CollectionUtility.hasElements(validValue)) {
      return "";
    }
    StringBuilder b = new StringBuilder();
    List<ITableRow> rows = getKeyColumnInternal().findRows(validValue);
    if (CollectionUtility.hasElements(rows)) {
      Iterator<ITableRow> rowIt = rows.iterator();
      b.append(getTextColumnInternal().getValue(rowIt.next()));
      while (rowIt.hasNext()) {
        b.append(", ");
        b.append(getTextColumnInternal().getValue(rowIt.next()));
      }
    }
    return b.toString();
  }

  @Override
  protected final Set<KEY> validateValueInternal(Set<KEY> rawValue0) throws ProcessingException {
    Set<KEY> rawValue = CollectionUtility.hashSet(rawValue0);
    return doValidateValueInternal(rawValue);
  }

  /**
   * override this method to perform detailed validation in subclasses
   */
  protected Set<KEY> doValidateValueInternal(Set<KEY> rawValue) throws ProcessingException {
    if (CollectionUtility.isEmpty(rawValue)) {
      // fast return empty set
      return rawValue;
    }
    ITable table = getTable();
    if (table != null) {
      if ((table.isCheckable() && !table.isMultiCheck()) || (!table.isCheckable() && !table.isMultiSelect())) {
        //only single value
        if (rawValue.size() > 1) {
          LOG.warn(getClass().getName() + " only accepts a single value. Got " + CollectionUtility.format(rawValue) + ". Using only first value.");
          return CollectionUtility.hashSet(CollectionUtility.firstElement(rawValue));
        }
      }
    }
    return rawValue;
  }

  @Override
  public boolean isContentValid() {
    boolean valid = super.isContentValid();
    if (valid && isMandatory() && getValue().isEmpty()) {
      return false;
    }
    return valid;
  }

  /**
   * Value, empty {@link Set} in case of an empty value, never <code>null</code>.
   */
  @Override
  public Set<KEY> getValue() {
    return CollectionUtility.hashSet(super.getValue());
  }

  /**
   * Initial value, empty {@link Set} in case of an empty value, never <code>null</code>.
   */
  @Override
  public Set<KEY> getInitValue() {
    return CollectionUtility.hashSet(super.getInitValue());
  }

  @Override
  public KEY getSingleValue() {
    return CollectionUtility.firstElement(super.getValue());
  }

  @Override
  public void setSingleValue(KEY value) {
    Set<KEY> valueSet = new HashSet<KEY>();
    if (value != null) {
      valueSet.add(value);
    }
    setValue(valueSet);
  }

  @Override
  public int getCheckedKeyCount() {
    return getValue().size();
  }

  @Override
  public KEY getCheckedKey() {
    return CollectionUtility.firstElement(getCheckedKeys());
  }

  @Override
  public Set<KEY> getCheckedKeys() {
    return getValue();
  }

  @Override
  public ILookupRow<KEY> getCheckedLookupRow() {
    return CollectionUtility.firstElement(getCheckedLookupRows());
  }

  @SuppressWarnings("unchecked")
  @Override
  public Set<ILookupRow<KEY>> getCheckedLookupRows() {
    Collection<ITableRow> checkedRows = getTable().getCheckedRows();
    Set<ILookupRow<KEY>> result = new HashSet<ILookupRow<KEY>>(checkedRows.size());
    for (ITableRow row : checkedRows) {
      ICell cell = row.getCell(1);
      result.add(new LookupRow<KEY>((KEY) row.getCellValue(0), cell.getText(), cell.getIconId(), cell.getTooltipText(), cell.getBackgroundColor(), cell.getForegroundColor(), cell.getFont(), cell.isEnabled()));
    }
    return result;
  }

  @Override
  public void checkKey(KEY key) {
    if (key == null) {
      checkKeys(null);
    }
    else {
      checkKeys(CollectionUtility.hashSet(key));
    }
  }

  @Override
  public void checkKeys(Collection<? extends KEY> keys) {
    setValue(CollectionUtility.<KEY> hashSetWithoutNullElements(keys));
  }

  @Override
  public void setFormInternal(IForm form) {
    super.setFormInternal(form);
    getListBoxFilterBox().setFormInternal(form);
  }

  @Override
  public void uncheckAllKeys() {
    checkKeys(null);
  }

  @Override
  public Set<KEY> getUncheckedKeys() {
    Set<KEY> result = new HashSet<KEY>();
    Set<KEY> initValue = getInitValue();
    if (initValue != null) {
      result.addAll(initValue);
    }
    Set<KEY> checkedKeys = getCheckedKeys();
    if (checkedKeys != null) {
      result.removeAll(checkedKeys);
    }
    return result;
  }

  @Override
  public void checkAllKeys() {
    checkKeys(getKeyColumnInternal().getValues());
  }

  @Override
  public void checkAllActiveKeys() {
    checkKeys(getKeyColumnInternal().getValues(getActiveColumnInternal().findRows(true)));
  }

  @Override
  public void uncheckAllInactiveKeys() {
    checkKeys(getKeyColumnInternal().getValues(getActiveColumnInternal().findRows(false)));
  }

  @Override
  public void exportFormFieldData(AbstractFormFieldData target) throws ProcessingException {
    @SuppressWarnings("unchecked")
    AbstractValueFieldData<Set<KEY>> v = (AbstractValueFieldData<Set<KEY>>) target;
    Set<KEY> value = getValue();
    if (CollectionUtility.isEmpty(value)) {
      v.setValue(null);
    }
    else {
      v.setValue(CollectionUtility.hashSet(this.getValue()));
    }
  }

  @SuppressWarnings("unchecked")
  private IColumn<KEY> getKeyColumnInternal() {
    return getTable().getColumnSet().getColumn(0);
  }

  @SuppressWarnings("unchecked")
  private IColumn<String> getTextColumnInternal() {
    return getTable().getColumnSet().getColumn(1);
  }

  @SuppressWarnings("unchecked")
  private IColumn<Boolean> getActiveColumnInternal() {
    return getTable().getColumnSet().getColumn(2);
  }

  private void syncValueToTable() {
    if (m_valueTableSyncActive) {
      return;
    }
    try {
      m_valueTableSyncActive = true;
      getTable().setTableChanging(true);
      //
      Set<KEY> checkedKeys = getCheckedKeys();
      List<ITableRow> checkedRows = getKeyColumnInternal().findRows(checkedKeys);
      for (ITableRow row : getTable().getRows()) {
        row.setChecked(false);
      }
      for (ITableRow row : checkedRows) {
        row.setChecked(true);
      }
      if (!getTable().isCheckable()) {
        getTable().selectRows(checkedRows, false);
      }
    }
    finally {
      getTable().setTableChanging(false);
      m_valueTableSyncActive = false;
    }
  }

  private void syncTableToValue() {
    if (m_valueTableSyncActive) {
      return;
    }
    try {
      m_valueTableSyncActive = true;
      m_table.setTableChanging(true);
      //
      Collection<ITableRow> checkedRows;
      if (getTable().isCheckable()) {
        checkedRows = getTable().getCheckedRows();
      }
      else {
        checkedRows = getTable().getSelectedRows();
      }
      checkKeys(getKeyColumnInternal().getValues(checkedRows));
      if (!getTable().isCheckable()) {
        //checks follow selection
        for (ITableRow row : m_table.getRows()) {
          row.setChecked(row.isSelected());
        }
      }
    }
    finally {
      getTable().setTableChanging(false);
      m_valueTableSyncActive = false;
    }
    // check if row filter needs to change
    if (!m_table.getUIFacade().isUIProcessing()) {
      updateActiveRowsFilter();
    }
    updateCheckedRowsFilter();
  }

  /*
   * Implementation of ICompositeField
   */

  @Override
  public <F extends IFormField> F getFieldByClass(Class<F> c) {
    return CompositeFieldUtility.getFieldByClass(this, c);
  }

  @Override
  public IFormField getFieldById(String id) {
    return CompositeFieldUtility.getFieldById(this, id);
  }

  @Override
  public <X extends IFormField> X getFieldById(String id, Class<X> type) {
    return CompositeFieldUtility.getFieldById(this, id, type);
  }

  @Override
  public int getFieldCount() {
    return m_fields.size();
  }

  @Override
  public int getFieldIndex(IFormField f) {
    return m_fields.indexOf(f);
  }

  @Override
  public List<IFormField> getFields() {
    return CollectionUtility.arrayList(m_fields);
  }

  @Override
  public boolean visitFields(IFormFieldVisitor visitor, int startLevel) {
    // myself
    if (!visitor.visitField(this, startLevel, 0)) {
      return false;
    }
    // children
    int index = 0;
    for (IFormField field : m_fields) {
      if (field instanceof ICompositeField) {
        if (!((ICompositeField) field).visitFields(visitor, startLevel + 1)) {
          return false;
        }
      }
      else {
        if (!visitor.visitField(field, startLevel, index)) {
          return false;
        }
      }
      index++;
    }
    return true;
  }

  @Override
  public final int getGridColumnCount() {
    return 1;
  }

  @Override
  public final int getGridRowCount() {
    return 1;
  }

  @Override
  public void rebuildFieldGrid() {
    GridData gd = getListBoxFilterBox().getGridDataHints();
    gd.x = 0;
    gd.y = 0;
    getListBoxFilterBox().setGridDataInternal(gd);
  }

  @Order(1)
  @ClassId("a2e982d1-ea01-4d11-8655-d10c9935d8b9")
  public class ListBoxFilterBox extends AbstractListBoxFilterBox {
    @Override
    protected IListBox getListBox() {
      return AbstractListBox.this;
    }
  }

  public class DefaultListBoxTable extends AbstractTable {
    @Override
    protected boolean getConfiguredAutoResizeColumns() {
      return true;
    }

    @Override
    protected boolean getConfiguredHeaderVisible() {
      return false;
    }

    @Override
    protected boolean getConfiguredMultiSelect() {
      return false;
    }

    @Override
    protected boolean getConfiguredCheckable() {
      return true;
    }

    @SuppressWarnings("unchecked")
    public KeyColumn getKeyColumn() {
      return getColumnSet().getColumnByClass(KeyColumn.class);
    }

    @SuppressWarnings("unchecked")
    public TextColumn getTextColumn() {
      return getColumnSet().getColumnByClass(TextColumn.class);
    }

    @SuppressWarnings("unchecked")
    public ActiveColumn getActiveColumn() {
      return getColumnSet().getColumnByClass(ActiveColumn.class);
    }

    @Order(1)
    public class KeyColumn extends AbstractColumn<KEY> {
      @Override
      protected boolean getConfiguredPrimaryKey() {
        return true;
      }

      @Override
      protected boolean getConfiguredDisplayable() {
        return false;
      }

      @Override
      @SuppressWarnings("unchecked")
      public Class<KEY> getDataType() {
        return TypeCastUtility.getGenericsParameterClass(AbstractListBox.this.getClass(), IListBox.class);
      }
    }

    @Order(2)
    public class TextColumn extends AbstractStringColumn {

    }

    @Order(3)
    public class ActiveColumn extends AbstractBooleanColumn {
      @Override
      protected boolean getConfiguredDisplayable() {
        return false;
      }
    }
  }

  private class P_TableRowBuilder extends AbstractTableRowBuilder<KEY> {

    @Override
    protected ITableRow createEmptyTableRow() {
      return new TableRow(getTable().getColumnSet());
    }

    @Override
    public ITableRow createTableRow(ILookupRow<KEY> dataRow) throws ProcessingException {
      TableRow tableRow = (TableRow) super.createTableRow(dataRow);
      // fill values to tableRow
      getKeyColumnInternal().setValue(tableRow, dataRow.getKey());
      getTextColumnInternal().setValue(tableRow, dataRow.getText());
      getActiveColumnInternal().setValue(tableRow, dataRow.isActive());

      //enable/disabled row
      Cell cell = tableRow.getCellForUpdate(1);
      cell.setEnabled(dataRow.isEnabled());

      // hint for inactive codes
      if (!dataRow.isActive()) {
        if (cell.getFont() == null) {
          cell.setFont(FontSpec.parse("italic"));
        }
        getTextColumnInternal().setValue(tableRow, dataRow.getText() + " (" + ScoutTexts.get("InactiveState") + ")");
      }
      return tableRow;
    }
  }

  protected final void interceptPopulateTable() throws ProcessingException {
    List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions();
    ListBoxPopulateTableChain<KEY> chain = new ListBoxPopulateTableChain<KEY>(extensions);
    chain.execPopulateTable();
  }

  protected final List<? extends ILookupRow<KEY>> interceptLoadTableData() throws ProcessingException {
    List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions();
    ListBoxLoadTableDataChain<KEY> chain = new ListBoxLoadTableDataChain<KEY>(extensions);
    return chain.execLoadTableData();
  }

  protected final void interceptFilterLookupResult(ILookupCall<KEY> call, List<ILookupRow<KEY>> result) throws ProcessingException {
    List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions();
    ListBoxFilterLookupResultChain<KEY> chain = new ListBoxFilterLookupResultChain<KEY>(extensions);
    chain.execFilterLookupResult(call, result);
  }

  protected final void interceptPrepareLookup(ILookupCall<KEY> call) throws ProcessingException {
    List<? extends IFormFieldExtension<? extends AbstractFormField>> extensions = getAllExtensions();
    ListBoxPrepareLookupChain<KEY> chain = new ListBoxPrepareLookupChain<KEY>(extensions);
    chain.execPrepareLookup(call);
  }

  protected static class LocalListBoxExtension<KEY, OWNER extends AbstractListBox<KEY>> extends LocalValueFieldExtension<Set<KEY>, OWNER> implements IListBoxExtension<KEY, OWNER> {

    public LocalListBoxExtension(OWNER owner) {
      super(owner);
    }

    @Override
    public void execPopulateTable(ListBoxPopulateTableChain<KEY> chain) throws ProcessingException {
      getOwner().execPopulateTable();
    }

    @Override
    public List<? extends ILookupRow<KEY>> execLoadTableData(ListBoxLoadTableDataChain<KEY> chain) throws ProcessingException {
      return getOwner().execLoadTableData();
    }

    @Override
    public void execFilterLookupResult(ListBoxFilterLookupResultChain<KEY> chain, ILookupCall<KEY> call, List<ILookupRow<KEY>> result) throws ProcessingException {
      getOwner().execFilterLookupResult(call, result);
    }

    @Override
    public void execPrepareLookup(ListBoxPrepareLookupChain<KEY> chain, ILookupCall<KEY> call) throws ProcessingException {
      getOwner().execPrepareLookup(call);
    }
  }

  @Override
  protected IListBoxExtension<KEY, ? extends AbstractListBox<KEY>> createLocalExtension() {
    return new LocalListBoxExtension<KEY, AbstractListBox<KEY>>(this);
  }
}
