// Copyright 2023 Google LLC
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "modules/bentleyottmann/include/SweepLine.h"

#include "include/private/SkAssert.h"
#include "modules/bentleyottmann/include/EventQueueInterface.h"
#include "modules/bentleyottmann/include/Point.h"
#include <algorithm>
#include <iterator>
#include <limits>
#include <optional>
#include <set>


namespace bentleyottmann {

SweepLine::SweepLine() {
    static constexpr Segment LeftSentinel = {{-std::numeric_limits<int32_t>::max(),
                                                     -std::numeric_limits<int32_t>::max()},
                                             {-std::numeric_limits<int32_t>::max(),
                                                     std::numeric_limits<int32_t>::max()}};
    static constexpr Segment RightSentinel = {{std::numeric_limits<int32_t>::max(),
                                                      -std::numeric_limits<int32_t>::max()},
                                              {std::numeric_limits<int32_t>::max(),
                                                      std::numeric_limits<int32_t>::max()}};

    fSweepLine.reserve(8);
    fSweepLine.push_back(LeftSentinel);
    fSweepLine.push_back(RightSentinel);
}

void SweepLine::verify(int32_t y) const {
    for(auto cursor = fSweepLine.begin(); (cursor + 1) != fSweepLine.end(); ++cursor) {
        [[maybe_unused]] const Segment& left = *cursor;
        [[maybe_unused]] const Segment& right = *(cursor + 1);
        SkASSERT(less_than_at(left, right, y));
    }
}

void SweepLine::handleDeletions(Point eventPoint, const DeletionSegmentSet& removing) {
    std::vector<Segment>::iterator newEnd;
    if (removing.empty()) {
        // Remove ending segments
        auto toRemove = [eventPoint](Segment s) {
            return s.lower() == eventPoint;
        };
        newEnd = std::remove_if(fSweepLine.begin(), fSweepLine.end(), toRemove);
    } else {
        // Remove all ending and crossing segments.
        auto toRemove = [eventPoint, &removing](Segment s) {
            return s.lower() == eventPoint || removing.find(s) != removing.end();
        };
        newEnd = std::remove_if(fSweepLine.begin(), fSweepLine.end(), toRemove);
    }
    fSweepLine.erase(newEnd, fSweepLine.end());
}

void SweepLine::handleInsertionsAndCheckForNewCrossings(
        Point eventPoint, const InsertionSegmentSet& inserting, EventQueueInterface* queue) {
    // The SlopeSegmentSet makes sure that these segments are in the right order for insertion.
    auto comp = [](const Segment& s, Point p) {
        return !point_less_than_segment_in_x(p, s);
    };

    const auto rightOfInsertion = std::lower_bound(
            fSweepLine.begin(), fSweepLine.end(), eventPoint, comp);
    SkASSERT(rightOfInsertion != fSweepLine.begin());
    const auto leftOfInsertion = rightOfInsertion - 1;

    if (inserting.empty()) {
        // There were deletions, but no insertions, so check if the two segments at the insertion
        // point cross.
        if (auto crossingPoint = intersect(*leftOfInsertion, *rightOfInsertion)) {
            queue->addCrossing(crossingPoint.value(), *leftOfInsertion, *rightOfInsertion);
        }
    } else {
        // Check if the left most inserted segment crosses the segment immediately to the left of
        // the insertion cursor.
        if (auto crossingPoint = intersect(*leftOfInsertion, *inserting.begin())) {
            queue->addCrossing(crossingPoint.value(), *leftOfInsertion, *inserting.begin());
        }

        // Check if the right most inserted segment crosses the segment immediately to the right of
        // the insertion cursor.
        if (auto crossingPoint = intersect(*inserting.rbegin(), *rightOfInsertion)) {
            queue->addCrossing(crossingPoint.value(), *inserting.rbegin(), *rightOfInsertion);
        }

        // Insert the set in the sweep line.
        fSweepLine.insert(rightOfInsertion, inserting.begin(), inserting.end());
    }
}
}  // namespace bentleyottmann
