/*
 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2013 ChangSeok Oh <shivamidow@gmail.com>
 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE
 * COPYRIGHT HOLDER 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 "LayoutRect.h"
#include "RenderBlockFlow.h"
#include <wtf/RefCounted.h>

namespace WebCore {

class FloatWithRect : public RefCounted<FloatWithRect> {
    WTF_MAKE_FAST_ALLOCATED;
public:
    static Ref<FloatWithRect> create(RenderBox& renderer)
    {
        return adoptRef(*new FloatWithRect(renderer));
    }
    
    RenderBox& renderer() const { return m_renderer; }
    LayoutRect rect() const { return m_rect; }
    bool everHadLayout() const { return m_everHadLayout; }

    void adjustRect(const LayoutRect& rect) { m_rect = rect; }

private:
    FloatWithRect(RenderBox& renderer)
        : m_renderer(renderer)
        , m_rect(LayoutRect(renderer.x() - renderer.marginLeft(), renderer.y() - renderer.marginTop(), renderer.width() + renderer.horizontalMarginExtent(), renderer.height() + renderer.verticalMarginExtent()))
        , m_everHadLayout(renderer.everHadLayout())
    {
    }
    
    RenderBox& m_renderer;
    LayoutRect m_rect;
    bool m_everHadLayout { false };
};

// Like LayoutState for layout(), LineLayoutState keeps track of global information
// during an entire linebox tree layout pass (aka layoutInlineChildren).
class LineLayoutState {
public:
    class FloatList {
    public:
        void append(Ref<FloatWithRect>&& floatWithRect)
        {
            m_floats.add(floatWithRect.copyRef());
            m_floatWithRectMap.add(&floatWithRect->renderer(), WTFMove(floatWithRect));
        }
        void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
        FloatingObject* lastFloat() const { return m_lastFloat; }

        void setLastCleanFloat(RenderBox& floatBox) { m_lastCleanFloat = &floatBox; }
        RenderBox* lastCleanFloat() const { return m_lastCleanFloat; }

        FloatWithRect* floatWithRect(RenderBox& floatBox) const { return m_floatWithRectMap.get(&floatBox); }

        using Iterator = ListHashSet<Ref<FloatWithRect>>::iterator;
        Iterator begin() { return m_floats.begin(); }
        Iterator end() { return m_floats.end(); }
        Iterator find(FloatWithRect& floatBoxWithRect) { return m_floats.find(floatBoxWithRect); }
        bool isEmpty() const { return m_floats.isEmpty(); }

    private:
        ListHashSet<Ref<FloatWithRect>> m_floats;
        HashMap<RenderBox*, Ref<FloatWithRect>> m_floatWithRectMap;
        FloatingObject* m_lastFloat { nullptr };
        RenderBox* m_lastCleanFloat { nullptr };
    };

    LineLayoutState(const RenderBlockFlow& blockFlow, bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFragmentedFlow* fragmentedFlow)
        : m_fragmentedFlow(fragmentedFlow)
        , m_repaintLogicalTop(repaintLogicalTop)
        , m_repaintLogicalBottom(repaintLogicalBottom)
        , m_marginInfo(blockFlow, blockFlow.borderAndPaddingBefore(), blockFlow.borderAndPaddingAfter() + blockFlow.scrollbarLogicalHeight())
        , m_endLineMatched(false)
        , m_checkForFloatsFromLastLine(false)
        , m_isFullLayout(fullLayout)
        , m_usesRepaintBounds(false)
    {
    }

    LineInfo& lineInfo() { return m_lineInfo; }
    const LineInfo& lineInfo() const { return m_lineInfo; }

    LayoutUnit endLineLogicalTop() const { return m_endLineLogicalTop; }
    void setEndLineLogicalTop(LayoutUnit logicalTop) { m_endLineLogicalTop = logicalTop; }

    RootInlineBox* endLine() const { return m_endLine; }
    void setEndLine(RootInlineBox* line) { m_endLine = line; }

    LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; }
    void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; }

    RenderFragmentedFlow* fragmentedFlow() const { return m_fragmentedFlow; }
    void setFragmentedFlow(RenderFragmentedFlow* thread) { m_fragmentedFlow = thread; }

    bool endLineMatched() const { return m_endLineMatched; }
    void setEndLineMatched(bool endLineMatched) { m_endLineMatched = endLineMatched; }

    bool checkForFloatsFromLastLine() const { return m_checkForFloatsFromLastLine; }
    void setCheckForFloatsFromLastLine(bool check) { m_checkForFloatsFromLastLine = check; }

    void markForFullLayout() { m_isFullLayout = true; }
    bool isFullLayout() const { return m_isFullLayout; }

    bool usesRepaintBounds() const { return m_usesRepaintBounds; }

    void setRepaintRange(LayoutUnit logicalHeight)
    {
        m_usesRepaintBounds = true;
        m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight;
    }

    void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0_lu)
    {
        m_usesRepaintBounds = true;
        m_repaintLogicalTop = std::min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + std::min<LayoutUnit>(paginationDelta, 0));
        m_repaintLogicalBottom = std::max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + std::max<LayoutUnit>(paginationDelta, 0));
    }

    RenderBlockFlow::MarginInfo& marginInfo() { return m_marginInfo; }

    FloatList& floatList() { return m_floatList; }

private:
    LineInfo m_lineInfo;
    LayoutUnit m_endLineLogicalTop;
    RootInlineBox* m_endLine { nullptr };

    LayoutUnit m_adjustedLogicalLineTop;

    RenderFragmentedFlow* m_fragmentedFlow { nullptr };

    FloatList m_floatList;
    // FIXME: Should this be a range object instead of two ints?
    LayoutUnit& m_repaintLogicalTop;
    LayoutUnit& m_repaintLogicalBottom;

    RenderBlockFlow::MarginInfo m_marginInfo;

    bool m_endLineMatched : 1;
    bool m_checkForFloatsFromLastLine : 1;
    bool m_isFullLayout : 1;
    bool m_usesRepaintBounds : 1;
};

} // namespace WebCore
