/*
 * Copyright (C) 2011 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 HOLDER "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 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 "LayerFragment.h"
#include "PODIntervalTree.h"
#include "RenderBlockFlow.h"
#include "RenderFragmentContainer.h"
#include <wtf/ListHashSet.h>

namespace WebCore {

class CurrentRenderFragmentContainerMaintainer;
class RenderFragmentedFlow;
class RenderStyle;
class RenderFragmentContainer;
class LegacyRootInlineBox;

typedef ListHashSet<RenderFragmentContainer*> RenderFragmentContainerList;
typedef Vector<RenderLayer*> RenderLayerList;
typedef HashMap<const LegacyRootInlineBox*, RenderFragmentContainer*> ContainingFragmentMap;

// RenderFragmentedFlow is used to collect all the render objects that participate in a
// flow thread. It will also help in doing the layout. However, it will not render
// directly to screen. Instead, RenderFragmentContainer objects will redirect their paint 
// and nodeAtPoint methods to this object. Each RenderFragmentContainer will actually be a viewPort
// of the RenderFragmentedFlow.

class RenderFragmentedFlow: public RenderBlockFlow {
    WTF_MAKE_ISO_ALLOCATED(RenderFragmentedFlow);
public:
    virtual ~RenderFragmentedFlow() = default;

    virtual void removeFlowChildInfo(RenderElement&);
#ifndef NDEBUG
    bool hasChildInfo(RenderObject* child) const { return is<RenderBox>(child) && m_fragmentRangeMap.contains(downcast<RenderBox>(child)); }
#endif

#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
    bool checkLinesConsistency(const RenderBlockFlow&) const;
#endif
    
    void deleteLines() override;

    virtual void addFragmentToThread(RenderFragmentContainer*) = 0;
    virtual void removeFragmentFromThread(RenderFragmentContainer*);
    const RenderFragmentContainerList& renderFragmentContainerList() const { return m_fragmentList; }

    void updateLogicalWidth() final;
    LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const override;

    bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;

    bool hasFragments() const { return m_fragmentList.size(); }
    virtual void fragmentChangedWritingMode(RenderFragmentContainer*) { }

    void validateFragments();
    void invalidateFragments(MarkingBehavior = MarkContainingBlockChain);
    bool hasValidFragmentInfo() const { return !m_fragmentsInvalidated && !m_fragmentList.isEmpty(); }
    
    // Called when a descendant box's layout is finished and it has been positioned within its container.
    virtual void fragmentedFlowDescendantBoxLaidOut(RenderBox*) { }

    void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;

    void repaintRectangleInFragments(const LayoutRect&) const;
    
    LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject&, const LayoutPoint&) const;

    LayoutUnit pageLogicalTopForOffset(LayoutUnit) const;
    LayoutUnit pageLogicalWidthForOffset(LayoutUnit) const;
    LayoutUnit pageLogicalHeightForOffset(LayoutUnit) const;
    LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary) const;

    virtual void setPageBreak(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { }
    virtual void updateMinimumPageHeight(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { }

    virtual void updateSpaceShortageForSizeContainment(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*shortage*/) { }

    virtual RenderFragmentContainer* fragmentAtBlockOffset(const RenderBox*, LayoutUnit, bool extendLastFragment = false) const;

    bool fragmentsHaveUniformLogicalWidth() const { return m_fragmentsHaveUniformLogicalWidth; }
    bool fragmentsHaveUniformLogicalHeight() const { return m_fragmentsHaveUniformLogicalHeight; }

    virtual RenderFragmentContainer* mapFromFlowToFragment(TransformState&) const;

    void logicalWidthChangedInFragmentsForBlock(const RenderBlock*, bool&);

    LayoutUnit contentLogicalWidthOfFirstFragment() const;
    LayoutUnit contentLogicalHeightOfFirstFragment() const;
    LayoutUnit contentLogicalLeftOfFirstFragment() const;
    
    RenderFragmentContainer* firstFragment() const;
    RenderFragmentContainer* lastFragment() const;

    virtual void setFragmentRangeForBox(const RenderBox&, RenderFragmentContainer*, RenderFragmentContainer*);
    bool getFragmentRangeForBox(const RenderBox*, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const;
    bool computedFragmentRangeForBox(const RenderBox*, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const;
    bool hasCachedFragmentRangeForBox(const RenderBox&) const;

    // Check if the object is in fragment and the fragment is part of this flow thread.
    bool objectInFlowFragment(const RenderObject*, const RenderFragmentContainer*) const;
    
    // Check if the object should be painted in this fragment and if the fragment is part of this flow thread.
    bool objectShouldFragmentInFlowFragment(const RenderObject*, const RenderFragmentContainer*) const;

    void markFragmentsForOverflowLayoutIfNeeded();

    virtual bool addForcedFragmentBreak(const RenderBlock*, LayoutUnit, RenderBox* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0);
    virtual void applyBreakAfterContent(LayoutUnit) { }

    virtual bool isPageLogicalHeightKnown() const { return true; }
    bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }

    void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
    LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox);

    LayoutUnit offsetFromLogicalTopOfFirstFragment(const RenderBlock*) const;
    void clearRenderBoxFragmentInfoAndCustomStyle(const RenderBox&, const RenderFragmentContainer*, const RenderFragmentContainer*, const RenderFragmentContainer*, const RenderFragmentContainer*);

    void addFragmentsVisualEffectOverflow(const RenderBox*);
    void addFragmentsVisualOverflowFromTheme(const RenderBlock*);
    void addFragmentsOverflowFromChild(const RenderBox*, const RenderBox*, const LayoutSize&);
    void addFragmentsLayoutOverflow(const RenderBox*, const LayoutRect&);
    void addFragmentsVisualOverflow(const RenderBox*, const LayoutRect&);
    void clearFragmentsOverflow(const RenderBox*);

    LayoutRect mapFromFragmentedFlowToLocal(const RenderBox*, const LayoutRect&) const;
    LayoutRect mapFromLocalToFragmentedFlow(const RenderBox*, const LayoutRect&) const;

    void flipForWritingModeLocalCoordinates(LayoutRect&) const;

    // Used to estimate the maximum height of the flow thread.
    static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; }

    bool fragmentInRange(const RenderFragmentContainer* targetFragment, const RenderFragmentContainer* startFragment, const RenderFragmentContainer* endFragment) const;

    bool absoluteQuadsForBox(Vector<FloatQuad>&, bool*, const RenderBox*) const;

    void layout() override;

    void setCurrentFragmentMaintainer(CurrentRenderFragmentContainerMaintainer* currentFragmentMaintainer) { m_currentFragmentMaintainer = currentFragmentMaintainer; }
    RenderFragmentContainer* currentFragment() const;

    ContainingFragmentMap& containingFragmentMap();

    bool cachedEnclosingFragmentedFlowNeedsUpdate() const override { return false; }

    // FIXME: Eventually as column and fragment flow threads start nesting, this may end up changing.
    virtual bool shouldCheckColumnBreaks() const { return false; }

private:
    // Always create a RenderLayer for the RenderFragmentedFlow so that we
    // can easily avoid drawing the children directly.
    bool requiresLayer() const final { return true; }

protected:
    RenderFragmentedFlow(Document&, RenderStyle&&);

    RenderFragmentedFlow* locateEnclosingFragmentedFlow() const override { return const_cast<RenderFragmentedFlow*>(this); }

    ASCIILiteral renderName() const override = 0;

    // Overridden by columns/pages to set up an initial logical width of the page width even when
    // no fragments have been generated yet.
    virtual LayoutUnit initialLogicalWidth() const { return 0; };
    
    void clearLinesToFragmentMap();
    void willBeDestroyed() override;

    void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const override;

    void updateFragmentsFragmentedFlowPortionRect();
    bool shouldRepaint(const LayoutRect&) const;

    bool getFragmentRangeForBoxFromCachedInfo(const RenderBox*, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const;

    void removeRenderBoxFragmentInfo(RenderBox&);
    void removeLineFragmentInfo(const RenderBlockFlow&);

    class RenderFragmentContainerRange {
    public:
        RenderFragmentContainerRange() = default;
        RenderFragmentContainerRange(RenderFragmentContainer* start, RenderFragmentContainer* end)
        {
            setRange(start, end);
        }
        
        void setRange(RenderFragmentContainer* start, RenderFragmentContainer* end)
        {
            m_startFragment = start;
            m_endFragment = end;
            m_rangeInvalidated = true;
        }

        RenderFragmentContainer* startFragment() const { return m_startFragment.get(); }
        RenderFragmentContainer* endFragment() const { return m_endFragment.get(); }
        bool rangeInvalidated() const { return m_rangeInvalidated; }
        void clearRangeInvalidated() { m_rangeInvalidated = false; }

    private:
        WeakPtr<RenderFragmentContainer> m_startFragment;
        WeakPtr<RenderFragmentContainer> m_endFragment;
        bool m_rangeInvalidated;
    };

    class FragmentSearchAdapter;

    RenderFragmentContainerList m_fragmentList;

    // Map a line to its containing fragment.
    std::unique_ptr<ContainingFragmentMap> m_lineToFragmentMap;

    // Map a box to the list of fragments in which the box is rendered.
    using RenderFragmentContainerRangeMap = HashMap<const RenderBox*, RenderFragmentContainerRange>;
    RenderFragmentContainerRangeMap m_fragmentRangeMap;

    // Map a box with a fragment break to the auto height fragment affected by that break. 
    using RenderBoxToFragmentMap = HashMap<RenderBox*, RenderFragmentContainer*>;
    RenderBoxToFragmentMap m_breakBeforeToFragmentMap;
    RenderBoxToFragmentMap m_breakAfterToFragmentMap;

    using FragmentIntervalTree = PODIntervalTree<LayoutUnit, WeakPtr<RenderFragmentContainer>>;
    FragmentIntervalTree m_fragmentIntervalTree;

    CurrentRenderFragmentContainerMaintainer* m_currentFragmentMaintainer;

    bool m_fragmentsInvalidated : 1;
    bool m_fragmentsHaveUniformLogicalWidth : 1;
    bool m_fragmentsHaveUniformLogicalHeight : 1;
    bool m_pageLogicalSizeChanged : 1;
};

} // namespace WebCore

SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderFragmentedFlow, isRenderFragmentedFlow())
