// SPDX-License-Identifier: LGPL-2.1-or-later
//
// SPDX-FileCopyrightText: 2011 Dennis Nienhüser <nienhueser@kde.org>
//

#include "OsmRegionTree.h"

namespace Marble
{

OsmRegionTree::OsmRegionTree(const OsmRegion &node)
    : m_node(node)
{
    // nothing to do
}

const OsmRegion &OsmRegionTree::node() const
{
    return m_node;
}

void OsmRegionTree::setChildren(const QList<OsmRegionTree> &children)
{
    m_children = children;
}

const QList<OsmRegionTree> &OsmRegionTree::children() const
{
    return m_children;
}

void OsmRegionTree::append(QList<OsmRegion> &regions)
{
    for (const OsmRegion &candidate : regions) {
        if (candidate.parentIdentifier() == m_node.identifier()) {
            m_children << OsmRegionTree(candidate);
        }
    }

    for (const OsmRegionTree &child : m_children) {
        regions.removeAll(child.node());
    }

    for (int i = 0; i < m_children.size(); ++i) {
        m_children[i].append(regions);
    }
}

void OsmRegionTree::traverse(int &counter)
{
    ++counter;
    m_node.setLeft(counter);

    for (int i = 0; i < m_children.size(); ++i) {
        m_children[i].traverse(counter);
    }

    ++counter;
    m_node.setRight(counter);
}

OsmRegionTree::operator QList<OsmRegion>() const
{
    QList<OsmRegion> result;
    enumerate(result);
    return result;
}

void OsmRegionTree::enumerate(QList<OsmRegion> &list) const
{
    list << m_node;
    for (const OsmRegionTree &child : m_children) {
        child.enumerate(list);
    }
}

int OsmRegionTree::smallestRegionId(const GeoDataCoordinates &coordinates) const
{
    int rootLevel = m_node.adminLevel();
    return smallestRegionId(coordinates, rootLevel);
}

int OsmRegionTree::smallestRegionId(const GeoDataCoordinates &coordinates, int &level) const
{
    int maxLevel = m_node.adminLevel();
    int minId = m_node.identifier();
    for (const OsmRegionTree &child : m_children) {
        if (child.node().geometry().contains(coordinates)) {
            int childLevel = level;
            int id = child.smallestRegionId(coordinates, childLevel);
            if (childLevel >= maxLevel) {
                maxLevel = childLevel;
                minId = id;
            }
        }
    }

    level = maxLevel;
    return minId;
}

}
