/*
 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
 *           (C) 1997 Torben Weis (weis@kde.org)
 *           (C) 1998 Waldo Bastian (bastian@kde.org)
 *           (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/layout/LayoutTableCol.h"

#include "core/HTMLNames.h"
#include "core/html/HTMLTableColElement.h"
#include "core/layout/LayoutTable.h"
#include "core/layout/LayoutTableCell.h"

namespace blink {

using namespace HTMLNames;

LayoutTableCol::LayoutTableCol(Element* element)
    : LayoutTableBoxComponent(element)
    , m_span(1)
{
    // init LayoutObject attributes
    setInline(true); // our object is not Inline
    updateFromElement();
}

void LayoutTableCol::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    DCHECK(style()->display() == EDisplay::TableColumn || style()->display() == EDisplay::TableColumnGroup);

    LayoutTableBoxComponent::styleDidChange(diff, oldStyle);

    if (!oldStyle)
        return;

    LayoutTable* table = this->table();
    if (!table)
        return;

    // TODO(dgrogan): Is the "else" necessary for correctness or just a brittle optimization? The optimization would be:
    // if the first branch is taken then the next one can't be, so don't even check its condition.
    if (!table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle->border() != style()->border()) {
        table->invalidateCollapsedBorders();
    } else if ((oldStyle->logicalWidth() != style()->logicalWidth()) || LayoutTableBoxComponent::doCellsHaveDirtyWidth(*this, *table, diff, *oldStyle)) {
        // TODO(dgrogan): Optimization opportunities:
        // (1) Only mark cells which are affected by this col, not every cell in the table.
        // (2) If only the col width changes and its border width doesn't, do the cells need to be marked as
        //     needing layout or just given dirty widths?
        table->markAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTable::MarkDirtyAndNeedsLayout);
    }
}

void LayoutTableCol::updateFromElement()
{
    unsigned oldSpan = m_span;
    Node* n = node();
    if (isHTMLTableColElement(n)) {
        HTMLTableColElement& tc = toHTMLTableColElement(*n);
        m_span = tc.span();
    } else {
        m_span = 1;
    }
    if (m_span != oldSpan && style() && parent())
        setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::AttributeChanged);
}

void LayoutTableCol::insertedIntoTree()
{
    LayoutTableBoxComponent::insertedIntoTree();
    table()->addColumn(this);
}

void LayoutTableCol::willBeRemovedFromTree()
{
    LayoutTableBoxComponent::willBeRemovedFromTree();
    table()->removeColumn(this);
}

bool LayoutTableCol::isChildAllowed(LayoutObject* child, const ComputedStyle& style) const
{
    // We cannot use isTableColumn here as style() may return 0.
    return child->isLayoutTableCol() && style.display() == EDisplay::TableColumn;
}

bool LayoutTableCol::canHaveChildren() const
{
    // Cols cannot have children. This is actually necessary to fix a bug
    // with libraries.uc.edu, which makes a <p> be a table-column.
    return isTableColumnGroup();
}

LayoutRect LayoutTableCol::localOverflowRectForPaintInvalidation() const
{
    // Entire table gets invalidated, instead of invalidating
    // every cell in the column.
    // This is simpler, but suboptimal.

    LayoutTable* table = this->table();
    if (!table)
        return LayoutRect();

    // The correctness of this method depends on the fact that LayoutTableCol's
    // location is always zero.
    ASSERT(this->location() == LayoutPoint());

    return table->localOverflowRectForPaintInvalidation();
}

void LayoutTableCol::clearPreferredLogicalWidthsDirtyBits()
{
    clearPreferredLogicalWidthsDirty();

    for (LayoutObject* child = firstChild(); child; child = child->nextSibling())
        child->clearPreferredLogicalWidthsDirty();
}

LayoutTable* LayoutTableCol::table() const
{
    LayoutObject* table = parent();
    if (table && !table->isTable())
        table = table->parent();
    return table && table->isTable() ? toLayoutTable(table) : nullptr;
}

LayoutTableCol* LayoutTableCol::enclosingColumnGroup() const
{
    if (!parent()->isLayoutTableCol())
        return nullptr;

    LayoutTableCol* parentColumnGroup = toLayoutTableCol(parent());
    ASSERT(parentColumnGroup->isTableColumnGroup());
    ASSERT(isTableColumn());
    return parentColumnGroup;
}

LayoutTableCol* LayoutTableCol::nextColumn() const
{
    // If |this| is a column-group, the next column is the colgroup's first child column.
    if (LayoutObject* firstChild = this->firstChild())
        return toLayoutTableCol(firstChild);

    // Otherwise it's the next column along.
    LayoutObject* next = nextSibling();

    // Failing that, the child is the last column in a column-group, so the next column is the next column/column-group after its column-group.
    if (!next && parent()->isLayoutTableCol())
        next = parent()->nextSibling();

    for (; next && !next->isLayoutTableCol(); next = next->nextSibling()) { }

    return toLayoutTableCol(next);
}

const BorderValue& LayoutTableCol::borderAdjoiningCellStartBorder(const LayoutTableCell*) const
{
    return style()->borderStart();
}

const BorderValue& LayoutTableCol::borderAdjoiningCellEndBorder(const LayoutTableCell*) const
{
    return style()->borderEnd();
}

const BorderValue& LayoutTableCol::borderAdjoiningCellBefore(const LayoutTableCell* cell) const
{
    ASSERT_UNUSED(cell, table()->colElementAtAbsoluteColumn(cell->absoluteColumnIndex() + cell->colSpan()).innermostColOrColGroup() == this);
    return style()->borderStart();
}

const BorderValue& LayoutTableCol::borderAdjoiningCellAfter(const LayoutTableCell* cell) const
{
    ASSERT_UNUSED(cell, table()->colElementAtAbsoluteColumn(cell->absoluteColumnIndex() - 1).innermostColOrColGroup() == this);
    return style()->borderEnd();
}

} // namespace blink
