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

#include "include/core/SkPath.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkTypes.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTDArray.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkArenaAlloc.h"
#include "src/core/SkPathEnums.h"
#include "src/core/SkPathPriv.h"
#include "src/pathops/SkOpContour.h"
#include "src/pathops/SkOpEdgeBuilder.h"
#include "src/pathops/SkOpSegment.h"
#include "src/pathops/SkOpSpan.h"
#include "src/pathops/SkPathOpsCommon.h"
#include "src/pathops/SkPathOpsTypes.h"
#include "src/pathops/SkPathWriter.h"

#include <cstdint>

static bool one_contour(const SkPath& path) {
    const auto raw = SkPathPriv::Raw(path, SkResolveConvexity::kNo);
    if (!raw) {
        return false;
    }

    const auto verbs = raw->verbs();
    for (size_t i = 1; i < verbs.size(); ++i) {
        if (verbs[i] == SkPathVerb::kMove) {
            return false;
        }
    }

    return true;
}

void SkOpBuilder::ReversePath(SkPath* path) {
    auto lastPt = path->getLastPt();
    SkASSERT(lastPt.has_value());
    SkPathBuilder temp;
    temp.moveTo(*lastPt);
    SkPathPriv::ReversePathTo(&temp, *path);
    temp.close();
    *path = temp.detach();
}

bool SkOpBuilder::FixWinding(SkPath* path) {
    SkPathFillType fillType = path->getFillType();
    if (fillType == SkPathFillType::kInverseEvenOdd) {
        fillType = SkPathFillType::kInverseWinding;
    } else if (fillType == SkPathFillType::kEvenOdd) {
        fillType = SkPathFillType::kWinding;
    }
    if (one_contour(*path)) {
        SkPathFirstDirection dir = SkPathPriv::ComputeFirstDirection(*path);
        if (dir != SkPathFirstDirection::kUnknown) {
            if (dir == SkPathFirstDirection::kCW) {
                ReversePath(path);
            }
            path->setFillType(fillType);
            return true;
        }
    }
    SkSTArenaAlloc<4096> allocator;
    SkOpContourHead contourHead;
    SkOpGlobalState globalState(&contourHead, &allocator  SkDEBUGPARAMS(false)
            SkDEBUGPARAMS(nullptr));
    SkOpEdgeBuilder builder(*path, &contourHead, &globalState);
    if (builder.unparseable() || !builder.finish()) {
        return false;
    }
    if (!contourHead.count()) {
        return true;
    }
    if (!contourHead.next()) {
        return false;
    }
    contourHead.joinAllSegments();
    contourHead.resetReverse();
    bool writePath = false;
    SkOpSpan* topSpan;
    globalState.setPhase(SkOpPhase::kFixWinding);
    while ((topSpan = FindSortableTop(&contourHead))) {
        SkOpSegment* topSegment = topSpan->segment();
        SkOpContour* topContour = topSegment->contour();
        SkASSERT(topContour->isCcw() >= 0);
#if DEBUG_WINDING
        SkDebugf("%s id=%d nested=%d ccw=%d\n",  __FUNCTION__,
                topSegment->debugID(), globalState.nested(), topContour->isCcw());
#endif
        if ((globalState.nested() & 1) != SkToBool(topContour->isCcw())) {
            topContour->setReverse();
            writePath = true;
        }
        topContour->markAllDone();
        globalState.clearNested();
    }
    if (!writePath) {
        path->setFillType(fillType);
        return true;
    }

    SkPathWriter woundPath(fillType);
    SkOpContour* test = &contourHead;
    do {
        if (!test->count()) {
            continue;
        }
        if (test->reversed()) {
            test->toReversePath(&woundPath);
        } else {
            test->toPath(&woundPath);
        }
    } while ((test = test->next()));
    *path = woundPath.nativePath();
    return true;
}

void SkOpBuilder::add(const SkPath& path, SkPathOp op) {
    if (fOps.empty() && op != kUnion_SkPathOp) {
        fPathRefs.push_back() = SkPath();
        *fOps.append() = kUnion_SkPathOp;
    }
    fPathRefs.push_back() = path;
    *fOps.append() = op;
}

void SkOpBuilder::reset() {
    fPathRefs.clear();
    fOps.reset();
}

/* OPTIMIZATION: Union doesn't need to be all-or-nothing. A run of three or more convex
   paths with union ops could be locally resolved and still improve over doing the
   ops one at a time. */
std::optional<SkPath> SkOpBuilder::resolve() {
    int count = fOps.size();
    bool allUnion = true;
    SkPathFirstDirection firstDir = SkPathFirstDirection::kUnknown;
    for (int index = 0; index < count; ++index) {
        SkPath* test = &fPathRefs[index];
        if (kUnion_SkPathOp != fOps[index] || test->isInverseFillType()) {
            allUnion = false;
            break;
        }
        // If all paths are convex, track direction, reversing as needed.
        if (test->isConvex()) {
            SkPathFirstDirection dir = SkPathPriv::ComputeFirstDirection(*test);
            if (dir == SkPathFirstDirection::kUnknown) {
                allUnion = false;
                break;
            }
            if (firstDir == SkPathFirstDirection::kUnknown) {
                firstDir = dir;
            } else if (firstDir != dir) {
                ReversePath(test);
            }
            continue;
        }
        // If the path is not convex but its bounds do not intersect the others, simplify is enough.
        const SkRect& testBounds = test->getBounds();
        for (int inner = 0; inner < index; ++inner) {
            // OPTIMIZE: check to see if the contour bounds do not intersect other contour bounds?
            if (SkRect::Intersects(fPathRefs[inner].getBounds(), testBounds)) {
                allUnion = false;
                break;
            }
        }
    }
    if (!allUnion) {
        SkPath result = fPathRefs[0];
        for (int index = 1; index < count; ++index) {
            if (auto res = Op(result, fPathRefs[index], fOps[index])) {
                result = *res;
            } else {
                reset();
                return {};
            }
        }
        reset();
        return result;
    }
    SkPathBuilder sum;
    for (int index = 0; index < count; ++index) {
        auto result = Simplify(fPathRefs[index]);
        if (!result.has_value()) {
            reset();
            return {};
        }
        fPathRefs[index] = *result;
        if (!fPathRefs[index].isEmpty()) {
            // convert the even odd result back to winding form before accumulating it
            if (!FixWinding(&fPathRefs[index])) {
                return {};
            }
            sum.addPath(fPathRefs[index]);
        }
    }
    reset();

    return Simplify(sum.detach());
}
