/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pivot.wtk.skin;

import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.Dictionary;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Dimensions;
import org.apache.pivot.wtk.FlowPane;
import org.apache.pivot.wtk.HorizontalAlignment;
import org.apache.pivot.wtk.Insets;

/**
 * Flow pane skin.
 */
public class FlowPaneSkin extends ContainerSkin {
    private HorizontalAlignment alignment;
    private Insets padding;
    private int horizontalSpacing;
    private int verticalSpacing;
    private boolean alignToBaseline;

    public FlowPaneSkin() {
        alignment = HorizontalAlignment.LEFT;
        padding = Insets.NONE;
        horizontalSpacing = 2;
        verticalSpacing = 2;
        alignToBaseline = true;
    }

    @Override
    public int getPreferredWidth(int height) {
        FlowPane flowPane = (FlowPane) getComponent();

        int preferredWidth = 0;

        // Preferred width is the sum of the preferred widths of all components
        // (height constraint is ignored)
        int j = 0;
        for (int i = 0, n = flowPane.getLength(); i < n; i++) {
            Component component = flowPane.get(i);

            if (component.isVisible()) {
                preferredWidth += component.getPreferredWidth();
                j++;
            }
        }

        // Include spacing
        if (j > 1) {
            preferredWidth += horizontalSpacing * (j - 1);
        }

        // Include left and right padding values
        preferredWidth += padding.left + padding.right;

        return preferredWidth;
    }

    @Override
    public int getPreferredHeight(int width) {
        FlowPane flowPane = (FlowPane) getComponent();

        int preferredHeight;

        if (width == -1) {
            if (alignToBaseline) {
                // Delegate to preferred size calculations
                Dimensions preferredSize = getPreferredSize();
                preferredHeight = preferredSize.height;
            } else {
                // Preferred height is the maximum preferred height of all
                // components
                preferredHeight = 0;

                for (int i = 0, n = flowPane.getLength(); i < n; i++) {
                    Component component = flowPane.get(i);

                    if (component.isVisible()) {
                        preferredHeight = Math.max(preferredHeight, component.getPreferredHeight());
                    }
                }
            }
        } else {
            // Break the components into multiple rows
            preferredHeight = 0;

            int contentWidth = Math.max(width - (padding.left + padding.right), 0);

            int rowCount = 0;

            int rowWidth = 0;
            int rowAscent = 0;
            int rowDescent = 0;

            for (int i = 0, n = flowPane.getLength(); i < n; i++) {
                Component component = flowPane.get(i);

                if (component.isVisible()) {
                    Dimensions size = component.getPreferredSize();

                    if (rowWidth + size.width > contentWidth && rowWidth > 0) {
                        // The component is too big to fit in the remaining
                        // space,
                        // and it is not the only component in this row; wrap
                        preferredHeight += rowAscent + rowDescent;

                        rowCount++;
                        rowWidth = 0;
                        rowAscent = 0;
                        rowDescent = 0;
                    }

                    rowWidth += size.width + horizontalSpacing;

                    if (alignToBaseline) {
                        int baseline = component.getBaseline(size.width, size.height);
                        rowAscent = Math.max(rowAscent, baseline);
                        rowDescent = Math.max(rowDescent, size.height - baseline);
                    } else {
                        rowAscent = Math.max(rowAscent, size.height);
                    }
                }
            }

            // Add the last row
            int lastRowHeight = rowAscent + rowDescent;
            if (lastRowHeight > 0) {
                preferredHeight += lastRowHeight;
                rowCount++;
            }

            // Include spacing
            if (rowCount > 0) {
                preferredHeight += verticalSpacing * (rowCount - 1);
            }
        }

        // Include top and bottom padding values
        preferredHeight += padding.top + padding.bottom;

        return preferredHeight;
    }

    @Override
    public Dimensions getPreferredSize() {
        FlowPane flowPane = (FlowPane) getComponent();

        int preferredWidth = 0;

        int ascent = 0;
        int descent = 0;

        int j = 0;
        for (int i = 0, n = flowPane.getLength(); i < n; i++) {
            Component component = flowPane.get(i);

            if (component.isVisible()) {
                Dimensions size = component.getPreferredSize();
                preferredWidth += size.width;

                if (alignToBaseline) {
                    int baseline = component.getBaseline(size.width, size.height);
                    ascent = Math.max(ascent, baseline);
                    descent = Math.max(descent, size.height - baseline);
                } else {
                    ascent = Math.max(ascent, size.height);
                }

                j++;
            }
        }

        // Include horizontal spacing
        if (j > 1) {
            preferredWidth += horizontalSpacing * (j - 1);
        }

        // Include padding
        preferredWidth += padding.left + padding.right;

        return new Dimensions(preferredWidth, ascent + descent + padding.top + padding.bottom);
    }

    @Override
    public int getBaseline(int width, int height) {
        FlowPane flowPane = (FlowPane) getComponent();

        int baseline = -1;

        if (alignToBaseline) {
            int contentWidth = Math.max(width - (padding.left + padding.right), 0);

            // Break the components into multiple rows, and calculate the
            // baseline of the
            // first row
            int rowWidth = 0;
            for (int i = 0, n = flowPane.getLength(); i < n; i++) {
                Component component = flowPane.get(i);

                if (component.isVisible()) {
                    Dimensions size = component.getPreferredSize();

                    if (rowWidth + size.width > contentWidth && rowWidth > 0) {
                        // The component is too big to fit in the remaining
                        // space,
                        // and it is not the only component in this row; wrap
                        break;
                    }

                    baseline = Math.max(baseline, component.getBaseline(size.width, size.height));
                    rowWidth += size.width + horizontalSpacing;
                }
            }

            // Include top padding value
            baseline += padding.top;
        }

        return baseline;
    }

    @Override
    public void layout() {
        FlowPane flowPane = (FlowPane) getComponent();
        int width = getWidth();
        int contentWidth = Math.max(width - (padding.left + padding.right), 0);

        // Break the components into multiple rows
        ArrayList<ArrayList<Component>> rows = new ArrayList<>();

        ArrayList<Component> row = new ArrayList<>();
        int rowWidth = 0;

        for (int i = 0, n = flowPane.getLength(); i < n; i++) {
            Component component = flowPane.get(i);

            if (component.isVisible()) {
                Dimensions componentSize = component.getPreferredSize();
                component.setSize(componentSize);

                if (rowWidth + componentSize.width > contentWidth && rowWidth > 0) {
                    // The component is too big to fit in the remaining space,
                    // and it is not the only component in this row
                    rows.add(row);
                    row = new ArrayList<>();
                    rowWidth = 0;
                }

                // Add the component to the row
                row.add(component);
                rowWidth += componentSize.width + horizontalSpacing;
            }
        }

        // Add the last row
        if (row.getLength() > 0) {
            rows.add(row);
        }

        // Lay out the rows
        int rowY = padding.top;

        for (int i = 0, n = rows.getLength(); i < n; i++) {
            row = rows.get(i);

            // Determine the row dimensions
            rowWidth = 0;
            int rowHeight = 0;
            int baseline = -1;
            for (Component component : row) {
                rowWidth += component.getWidth();
                rowHeight = Math.max(rowHeight, component.getHeight());
                baseline = Math.max(baseline,
                    component.getBaseline(component.getWidth(), component.getHeight()));
            }

            rowWidth += horizontalSpacing * (row.getLength() - 1);

            int x = 0;
            switch (alignment) {
                case LEFT: {
                    x = padding.left;
                    break;
                }
                case CENTER: {
                    x = (width - rowWidth) / 2;
                    break;
                }
                case RIGHT: {
                    x = width - rowWidth - padding.right;
                    break;
                }
                default: {
                    break;
                }
            }

            for (Component component : row) {
                int y;
                int componentBaseline = component.getBaseline(component.getWidth(),
                    component.getHeight());
                if (alignToBaseline && baseline != -1 && componentBaseline != -1) {
                    // Align to baseline
                    y = baseline - componentBaseline;
                } else {
                    // Align to bottom
                    y = rowHeight - component.getHeight();
                }

                component.setLocation(x, y + rowY);
                x += (component.getWidth() + horizontalSpacing);
            }

            rowY += (rowHeight + verticalSpacing);
        }
    }

    public HorizontalAlignment getAlignment() {
        return alignment;
    }

    public void setAlignment(HorizontalAlignment alignment) {
        if (alignment == null) {
            throw new IllegalArgumentException("alignment is null.");
        }

        this.alignment = alignment;
        invalidateComponent();
    }

    /**
     * @return The amount of space between the edge of the FlowPane and its
     * components.
     */
    public Insets getPadding() {
        return padding;
    }

    /**
     * Sets the amount of space to leave between the edge of the FlowPane and
     * its components.
     *
     * @param padding The individual padding values for each edge.
     */
    public void setPadding(Insets padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        this.padding = padding;
        invalidateComponent();
    }

    /**
     * Sets the amount of space to leave between the edge of the FlowPane and
     * its components.
     *
     * @param padding A dictionary with keys in the set {left, top, bottom,
     * right}.
     */
    public final void setPadding(Dictionary<String, ?> padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(new Insets(padding));
    }

    /**
     * Sets the amount of space to leave between the edge of the FlowPane and
     * its components, uniformly on all four edges.
     *
     * @param padding The single padding value for all four sides.
     */
    public final void setPadding(int padding) {
        setPadding(new Insets(padding));
    }

    /**
     * Sets the amount of space to leave between the edge of the FlowPane and
     * its components, uniformly on all four edges.
     *
     * @param padding The single padding value for all four sides.
     */
    public final void setPadding(Number padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(padding.intValue());
    }

    /**
     * Sets the amount of space to leave between the edge of the FlowPane and
     * its components.
     *
     * @param padding A string containing an integer or a JSON dictionary with
     * keys left, top, bottom, and/or right.
     */
    public final void setPadding(String padding) {
        if (padding == null) {
            throw new IllegalArgumentException("padding is null.");
        }

        setPadding(Insets.decode(padding));
    }

    public int getHorizontalSpacing() {
        return horizontalSpacing;
    }

    public void setHorizontalSpacing(int horizontalSpacing) {
        if (horizontalSpacing < 0) {
            throw new IllegalArgumentException("horizontalSpacing is negative.");
        }
        this.horizontalSpacing = horizontalSpacing;
        invalidateComponent();
    }

    public final void setHorizontalSpacing(Number horizontalSpacing) {
        if (horizontalSpacing == null) {
            throw new IllegalArgumentException("horizontalSpacing is null.");
        }

        setHorizontalSpacing(horizontalSpacing.intValue());
    }

    public int getVerticalSpacing() {
        return verticalSpacing;
    }

    public void setVerticalSpacing(int verticalSpacing) {
        if (verticalSpacing < 0) {
            throw new IllegalArgumentException("verticalSpacing is negative.");
        }
        this.verticalSpacing = verticalSpacing;
        invalidateComponent();
    }

    public final void setVerticalSpacing(Number verticalSpacing) {
        if (verticalSpacing == null) {
            throw new IllegalArgumentException("verticalSpacing is null.");
        }

        setVerticalSpacing(verticalSpacing.intValue());
    }

    public boolean getAlignToBaseline() {
        return alignToBaseline;
    }

    public void setAlignToBaseline(boolean alignToBaseline) {
        this.alignToBaseline = alignToBaseline;
        invalidateComponent();
    }
}
