/*
 * Copyright (C) 2017 Igalia S.L.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "GridPositionsResolver.h"
#include "OrderIterator.h"
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>

namespace WebCore {

typedef Vector<RenderBox*, 1> GridCell;
typedef Vector<Vector<GridCell>> GridAsMatrix;
typedef ListHashSet<size_t> OrderedTrackIndexSet;

class GridArea;
class GridPositionsResolver;
class RenderGrid;

class Grid final {
public:
    explicit Grid(RenderGrid&);

    unsigned numTracks(GridTrackSizingDirection) const;

    void ensureGridSize(unsigned maximumRowSize, unsigned maximumColumnSize);
    void insert(RenderBox&, const GridArea&);

    // Note that each in flow child of a grid container becomes a grid item. This means that
    // this method will return false for a grid container with only out of flow children.
    bool hasGridItems() const { return !m_gridItemArea.isEmpty(); }

    // FIXME: move this to SizingData once placeItemsOnGrid() takes it as argument.
    bool hasAnyOrthogonalGridItem() const { return m_hasAnyOrthogonalGridItem; }
    void setHasAnyOrthogonalGridItem(bool hasAnyOrthogonalGridItem) { m_hasAnyOrthogonalGridItem = hasAnyOrthogonalGridItem; }

    GridArea gridItemArea(const RenderBox& item) const;
    void setGridItemArea(const RenderBox& item, GridArea);

    GridSpan gridItemSpan(const RenderBox&, GridTrackSizingDirection) const;

    const GridCell& cell(unsigned row, unsigned column) const { return m_grid[row][column]; }

    int smallestTrackStart(GridTrackSizingDirection) const;
    void setSmallestTracksStart(int rowStart, int columnStart);

    unsigned autoRepeatTracks(GridTrackSizingDirection) const;
    void setAutoRepeatTracks(unsigned autoRepeatRows, unsigned autoRepeatColumns);

    void setAutoRepeatEmptyColumns(std::unique_ptr<OrderedTrackIndexSet>);
    void setAutoRepeatEmptyRows(std::unique_ptr<OrderedTrackIndexSet>);

    unsigned autoRepeatEmptyTracksCount(GridTrackSizingDirection) const;
    bool hasAutoRepeatEmptyTracks(GridTrackSizingDirection) const;
    bool isEmptyAutoRepeatTrack(GridTrackSizingDirection, unsigned) const;

    OrderedTrackIndexSet* autoRepeatEmptyTracks(GridTrackSizingDirection) const;

    OrderIterator& orderIterator() { return m_orderIterator; }

    void setNeedsItemsPlacement(bool);
    bool needsItemsPlacement() const { return m_needsItemsPlacement; };

private:
    friend class GridIterator;

    OrderIterator m_orderIterator;

    int m_smallestColumnStart { 0 };
    int m_smallestRowStart { 0 };

    unsigned m_autoRepeatColumns { 0 };
    unsigned m_autoRepeatRows { 0 };

    bool m_hasAnyOrthogonalGridItem { false };
    bool m_needsItemsPlacement { true };

    GridAsMatrix m_grid;

    HashMap<const RenderBox*, GridArea> m_gridItemArea;
    HashMap<const RenderBox*, size_t> m_gridItemsIndexesMap;

    std::unique_ptr<OrderedTrackIndexSet> m_autoRepeatEmptyColumns;
    std::unique_ptr<OrderedTrackIndexSet> m_autoRepeatEmptyRows;
};

class GridIterator {
    WTF_MAKE_NONCOPYABLE(GridIterator);
public:
    // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
    // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd column.
    GridIterator(const Grid&, GridTrackSizingDirection, unsigned fixedTrackIndex, unsigned varyingTrackIndex = 0);

    RenderBox* nextGridItem();
    bool isEmptyAreaEnough(unsigned rowSpan, unsigned columnSpan) const;
    std::unique_ptr<GridArea> nextEmptyGridArea(unsigned fixedTrackSpan, unsigned varyingTrackSpan);

private:
    const GridAsMatrix& m_grid;
    GridTrackSizingDirection m_direction;
    unsigned m_rowIndex;
    unsigned m_columnIndex;
    unsigned m_childIndex;
};

} // namespace WebCore
