/*******************************************************************************
 * Copyright (c) 2012, 2020 Original authors and others.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
package org.eclipse.nebula.widgets.nattable.layer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;

import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.coordinate.Range;
import org.eclipse.nebula.widgets.nattable.layer.cell.IConfigLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.layer.cell.TranslatedLayerCell;
import org.eclipse.nebula.widgets.nattable.layer.event.IStructuralChangeEvent;
import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;
import org.eclipse.nebula.widgets.nattable.painter.layer.ILayerPainter;
import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider;

/**
 * Abstract base class for layers that expose transformed views of an underlying
 * unique index layer. By default the AbstractLayerTransform behaves as an
 * identity transform of its underlying layer; that is, it exposes its
 * underlying layer as is without any changes. Subclasses are expected to
 * override methods in this class to implement specific kinds of layer
 * transformations.
 */
public class AbstractIndexLayerTransform extends AbstractLayer implements IUniqueIndexLayer {

    private IUniqueIndexLayer underlyingLayer;

    public AbstractIndexLayerTransform() {
    }

    public AbstractIndexLayerTransform(IUniqueIndexLayer underlyingLayer) {
        setUnderlyingLayer(underlyingLayer);
    }

    protected void setUnderlyingLayer(IUniqueIndexLayer underlyingLayer) {
        if (this.underlyingLayer != null) {
            this.underlyingLayer.removeLayerListener(this);
        }
        this.underlyingLayer = underlyingLayer;
        this.underlyingLayer.setClientAreaProvider(getClientAreaProvider());
        this.underlyingLayer.addLayerListener(this);
    }

    protected final IUniqueIndexLayer getUnderlyingLayer() {
        return this.underlyingLayer;
    }

    // Dispose

    @Override
    public void dispose() {
        this.underlyingLayer.dispose();
    }

    // Persistence

    @Override
    public void saveState(String prefix, Properties properties) {
        this.underlyingLayer.saveState(prefix, properties);
        super.saveState(prefix, properties);
    }

    /**
     * Underlying layers <i>must</i> load state first. If this is not done,
     * {@link IStructuralChangeEvent} from underlying layers will reset caches
     * after state has been loaded
     */
    @Override
    public void loadState(String prefix, Properties properties) {
        super.loadState(prefix, properties);
        this.underlyingLayer.loadState(prefix, properties);
    }

    // Configuration

    @Override
    public void configure(IConfigRegistry configRegistry, UiBindingRegistry uiBindingRegistry) {
        super.configure(configRegistry, uiBindingRegistry);
        this.underlyingLayer.configure(configRegistry, uiBindingRegistry);
    }

    @Override
    public ILayerPainter getLayerPainter() {
        return (this.layerPainter != null) ? this.layerPainter : this.underlyingLayer.getLayerPainter();
    }

    // Command

    @Override
    public boolean doCommand(ILayerCommand command) {
        if (super.doCommand(command)) {
            return true;
        }

        return this.underlyingLayer.doCommand(command);
    }

    // Client area

    @Override
    public void setClientAreaProvider(IClientAreaProvider clientAreaProvider) {
        super.setClientAreaProvider(clientAreaProvider);
        if (this.underlyingLayer != null) {
            this.underlyingLayer.setClientAreaProvider(clientAreaProvider);
        }
    }

    // Horizontal features

    // Columns

    @Override
    public int getColumnCount() {
        return this.underlyingLayer.getColumnCount();
    }

    @Override
    public int getPreferredColumnCount() {
        return this.underlyingLayer.getPreferredColumnCount();
    }

    @Override
    public int getColumnIndexByPosition(int columnPosition) {
        return this.underlyingLayer.getColumnIndexByPosition(localToUnderlyingColumnPosition(columnPosition));
    }

    @Override
    public int localToUnderlyingColumnPosition(int localColumnPosition) {
        return localColumnPosition;
    }

    @Override
    public int underlyingToLocalColumnPosition(ILayer sourceUnderlyingLayer, int underlyingColumnPosition) {
        if (sourceUnderlyingLayer != this.underlyingLayer) {
            return -1;
        }
        return underlyingColumnPosition;
    }

    @Override
    public Collection<Range> underlyingToLocalColumnPositions(
            ILayer sourceUnderlyingLayer, Collection<Range> underlyingColumnPositionRanges) {

        Collection<Range> localColumnPositionRanges = new ArrayList<>(underlyingColumnPositionRanges.size());
        for (Range underlyingColumnPositionRange : underlyingColumnPositionRanges) {
            localColumnPositionRanges.add(new Range(
                    underlyingToLocalColumnPosition(sourceUnderlyingLayer, underlyingColumnPositionRange.start),
                    underlyingToLocalColumnPosition(sourceUnderlyingLayer, underlyingColumnPositionRange.end)));
        }
        return localColumnPositionRanges;
    }

    @Override
    public int getColumnPositionByIndex(int columnIndex) {
        return underlyingToLocalColumnPosition(
                this.underlyingLayer,
                this.underlyingLayer.getColumnPositionByIndex(columnIndex));
    }

    // Width

    @Override
    public int getWidth() {
        return this.underlyingLayer.getWidth();
    }

    @Override
    public int getPreferredWidth() {
        return this.underlyingLayer.getPreferredWidth();
    }

    @Override
    public int getColumnWidthByPosition(int columnPosition) {
        return this.underlyingLayer.getColumnWidthByPosition(localToUnderlyingColumnPosition(columnPosition));
    }

    // Column resize

    @Override
    public boolean isColumnPositionResizable(int columnPosition) {
        return this.underlyingLayer.isColumnPositionResizable(localToUnderlyingColumnPosition(columnPosition));
    }

    // X

    @Override
    public int getColumnPositionByX(int x) {
        return this.underlyingLayer.getColumnPositionByX(x);
    }

    @Override
    public int getStartXOfColumnPosition(int columnPosition) {
        return this.underlyingLayer.getStartXOfColumnPosition(localToUnderlyingColumnPosition(columnPosition));
    }

    // Underlying

    @Override
    public Collection<ILayer> getUnderlyingLayersByColumnPosition(int columnPosition) {
        Collection<ILayer> underlyingLayers = new HashSet<>();
        underlyingLayers.add(this.underlyingLayer);
        return underlyingLayers;
    }

    // Vertical features

    // Rows

    @Override
    public int getRowCount() {
        return this.underlyingLayer.getRowCount();
    }

    @Override
    public int getPreferredRowCount() {
        return this.underlyingLayer.getPreferredRowCount();
    }

    @Override
    public int getRowIndexByPosition(int rowPosition) {
        return this.underlyingLayer.getRowIndexByPosition(localToUnderlyingRowPosition(rowPosition));
    }

    @Override
    public int localToUnderlyingRowPosition(int localRowPosition) {
        return localRowPosition;
    }

    @Override
    public int underlyingToLocalRowPosition(ILayer sourceUnderlyingLayer, int underlyingRowPosition) {
        if (sourceUnderlyingLayer != this.underlyingLayer) {
            return -1;
        }
        return underlyingRowPosition;
    }

    @Override
    public Collection<Range> underlyingToLocalRowPositions(
            ILayer sourceUnderlyingLayer,
            Collection<Range> underlyingRowPositionRanges) {
        Collection<Range> localRowPositionRanges = new ArrayList<>(underlyingRowPositionRanges.size());
        for (Range underlyingRowPositionRange : underlyingRowPositionRanges) {
            localRowPositionRanges.add(new Range(
                    underlyingToLocalRowPosition(sourceUnderlyingLayer, underlyingRowPositionRange.start),
                    underlyingToLocalRowPosition(sourceUnderlyingLayer, underlyingRowPositionRange.end)));
        }
        return localRowPositionRanges;
    }

    @Override
    public int getRowPositionByIndex(int rowIndex) {
        return underlyingToLocalRowPosition(
                this.underlyingLayer,
                this.underlyingLayer.getRowPositionByIndex(rowIndex));
    }

    // Height

    @Override
    public int getHeight() {
        return this.underlyingLayer.getHeight();
    }

    @Override
    public int getPreferredHeight() {
        return this.underlyingLayer.getPreferredHeight();
    }

    @Override
    public int getRowHeightByPosition(int rowPosition) {
        return this.underlyingLayer.getRowHeightByPosition(localToUnderlyingRowPosition(rowPosition));
    }

    // Row resize

    @Override
    public boolean isRowPositionResizable(int rowPosition) {
        return this.underlyingLayer.isRowPositionResizable(localToUnderlyingRowPosition(rowPosition));
    }

    // Y

    @Override
    public int getRowPositionByY(int y) {
        return this.underlyingLayer.getRowPositionByY(y);
    }

    @Override
    public int getStartYOfRowPosition(int rowPosition) {
        return this.underlyingLayer.getStartYOfRowPosition(localToUnderlyingRowPosition(rowPosition));
    }

    // Underlying

    @Override
    public Collection<ILayer> getUnderlyingLayersByRowPosition(int rowPosition) {
        Collection<ILayer> underlyingLayers = new HashSet<>();
        underlyingLayers.add(this.underlyingLayer);
        return underlyingLayers;
    }

    // Cell features

    @Override
    public ILayerCell getCellByPosition(int columnPosition, int rowPosition) {
        ILayerCell cell = this.underlyingLayer.getCellByPosition(
                localToUnderlyingColumnPosition(columnPosition),
                localToUnderlyingRowPosition(rowPosition));
        if (cell == null) {
            return null;
        }
        return new TranslatedLayerCell(cell, this,
                underlyingToLocalColumnPosition(this.underlyingLayer, cell.getOriginColumnPosition()),
                underlyingToLocalRowPosition(this.underlyingLayer, cell.getOriginRowPosition()),
                underlyingToLocalColumnPosition(this.underlyingLayer, cell.getColumnPosition()),
                underlyingToLocalRowPosition(this.underlyingLayer, cell.getRowPosition()));
    }

    @Override
    public String getDisplayModeByPosition(int columnPosition, int rowPosition) {
        return this.underlyingLayer.getDisplayModeByPosition(
                localToUnderlyingColumnPosition(columnPosition),
                localToUnderlyingRowPosition(rowPosition));
    }

    @Override
    public LabelStack getConfigLabelsByPosition(int columnPosition, int rowPosition) {
        LabelStack configLabels = this.underlyingLayer.getConfigLabelsByPosition(
                localToUnderlyingColumnPosition(columnPosition),
                localToUnderlyingRowPosition(rowPosition));
        IConfigLabelAccumulator configLabelAccumulator = getConfigLabelAccumulator();
        if (configLabelAccumulator != null) {
            configLabelAccumulator.accumulateConfigLabels(configLabels, columnPosition, rowPosition);
        }
        String regionName = getRegionName();
        if (regionName != null) {
            configLabels.addLabel(regionName);
        }
        return configLabels;
    }

    @Override
    public Object getDataValueByPosition(int columnPosition, int rowPosition) {
        return this.underlyingLayer.getDataValueByPosition(
                localToUnderlyingColumnPosition(columnPosition),
                localToUnderlyingRowPosition(rowPosition));
    }

    @Override
    public ICellPainter getCellPainter(
            int columnPosition, int rowPosition,
            ILayerCell cell, IConfigRegistry configRegistry) {
        return this.underlyingLayer.getCellPainter(columnPosition, rowPosition, cell, configRegistry);
    }

    // IRegionResolver

    @Override
    public LabelStack getRegionLabelsByXY(int x, int y) {
        LabelStack regionLabels = this.underlyingLayer.getRegionLabelsByXY(x, y);
        String regionName = getRegionName();
        if (regionName != null) {
            regionLabels.addLabel(regionName);
        }
        return regionLabels;
    }

    @Override
    public ILayer getUnderlyingLayerByPosition(int columnPosition, int rowPosition) {
        return this.underlyingLayer;
    }

    @Override
    public boolean isDynamicSizeLayer() {
        return this.underlyingLayer.isDynamicSizeLayer();
    }
}
