// Copyright 2019 Google LLC.
#include "modules/skparagraph/src/Run.h"
#include <unicode/brkiter.h>
#include "include/core/SkFontMetrics.h"

namespace skia {
namespace textlayout {

Run::Run(SkSpan<const char> text,
         const SkShaper::RunHandler::RunInfo& info,
         SkScalar lineHeight,
         size_t index,
         SkScalar offsetX) {
    TRACE_EVENT0("skia", TRACE_FUNC);
    fFont = info.fFont;
    fHeightMultiplier = lineHeight;
    fBidiLevel = info.fBidiLevel;
    fAdvance = info.fAdvance;
    fText = SkSpan<const char>(text.begin() + info.utf8Range.begin(), info.utf8Range.size());

    fIndex = index;
    fUtf8Range = info.utf8Range;
    fOffset = SkVector::Make(offsetX, 0);
    fGlyphs.push_back_n(info.glyphCount);
    fPositions.push_back_n(info.glyphCount + 1);
    fOffsets.push_back_n(info.glyphCount + 1, SkScalar(0));
    fClusterIndexes.push_back_n(info.glyphCount + 1);
    info.fFont.getMetrics(&fFontMetrics);
    fSpaced = false;
    // To make edge cases easier:
    fPositions[info.glyphCount] = fOffset + fAdvance;
    fClusterIndexes[info.glyphCount] = info.utf8Range.end();
}

SkShaper::RunHandler::Buffer Run::newRunBuffer() {
    TRACE_EVENT0("skia", TRACE_FUNC);
    return {fGlyphs.data(), fPositions.data(), nullptr, fClusterIndexes.data(), fOffset};
}

SkScalar Run::calculateWidth(size_t start, size_t end, bool clip) const {
    TRACE_EVENT0("skia", TRACE_FUNC);
    SkASSERT(start <= end);
    // clip |= end == size();  // Clip at the end of the run?
    SkScalar offset = 0;
    if (fSpaced && end > start) {
        offset = fOffsets[clip ? end - 1 : end] - fOffsets[start];
    }
    return fPositions[end].fX - fPositions[start].fX + offset;
}

void Run::copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector offset) const {
    TRACE_EVENT0("skia", TRACE_FUNC);
    SkASSERT(pos + size <= this->size());
    const auto& blobBuffer = builder.allocRunPos(fFont, SkToInt(size));
    sk_careful_memcpy(blobBuffer.glyphs, fGlyphs.data() + pos, size * sizeof(SkGlyphID));

    if (fSpaced || offset.fX != 0 || offset.fY != 0) {
        for (size_t i = 0; i < size; ++i) {
            auto point = fPositions[i + pos];
            if (fSpaced) {
                point.fX += fOffsets[i + pos];
            }
            blobBuffer.points()[i] = point + offset;
        }
    } else {
        // Good for the first line
        sk_careful_memcpy(blobBuffer.points(), fPositions.data() + pos, size * sizeof(SkPoint));
    }
}

// TODO: Make the search more effective
std::tuple<bool, Cluster*, Cluster*> Run::findLimitingClusters(SkSpan<const char> text) {
    if (text.empty()) {
        Cluster* found = nullptr;
        for (auto& cluster : fClusters) {
            if (cluster.contains(text.begin())) {
                found = &cluster;
                break;
            }
        }
        return std::make_tuple(found != nullptr, found, found);
    }

    auto first = text.begin();
    auto last = text.end() - 1;

    Cluster* start = nullptr;
    Cluster* end = nullptr;
    for (auto& cluster : fClusters) {
        if (cluster.contains(first)) start = &cluster;
        if (cluster.contains(last)) end = &cluster;
    }
    if (!leftToRight()) {
        std::swap(start, end);
    }

    return std::make_tuple(start != nullptr && end != nullptr, start, end);
}

void Run::iterateThroughClustersInTextOrder(const ClusterVisitor& visitor) {
    TRACE_EVENT0("skia", TRACE_FUNC);
    // Can't figure out how to do it with one code for both cases without 100 ifs
    // Can't go through clusters because there are no cluster table yet
    if (leftToRight()) {
        size_t start = 0;
        size_t cluster = this->clusterIndex(start);
        for (size_t glyph = 1; glyph <= this->size(); ++glyph) {
            auto nextCluster = this->clusterIndex(glyph);
            if (nextCluster == cluster) {
                continue;
            }

            visitor(start,
                    glyph,
                    cluster,
                    nextCluster,
                    this->calculateWidth(start, glyph, glyph == size()),
                    this->calculateHeight());

            start = glyph;
            cluster = nextCluster;
        }
    } else {
        size_t glyph = this->size();
        size_t cluster = this->fUtf8Range.begin();
        for (int32_t start = this->size() - 1; start >= 0; --start) {
            size_t nextCluster =
                    start == 0 ? this->fUtf8Range.end() : this->clusterIndex(start - 1);
            if (nextCluster == cluster) {
                continue;
            }

            visitor(start,
                    glyph,
                    cluster,
                    nextCluster,
                    this->calculateWidth(start, glyph, glyph == 0),
                    this->calculateHeight());

            glyph = start;
            cluster = nextCluster;
        }
    }
}

SkScalar Run::addSpacesAtTheEnd(SkScalar space, Cluster* cluster) {
    TRACE_EVENT0("skia", TRACE_FUNC);
    if (cluster->endPos() == cluster->startPos()) {
        return 0;
    }

    fOffsets[cluster->endPos() - 1] += space;
    // Increment the run width
    fSpaced = true;
    fAdvance.fX += space;
    // Increment the cluster width
    cluster->space(space, space);

    return space;
}

SkScalar Run::addSpacesEvenly(SkScalar space, Cluster* cluster) {
    TRACE_EVENT0("skia", TRACE_FUNC);
    // Offset all the glyphs in the cluster
    SkScalar shift = 0;
    for (size_t i = cluster->startPos(); i < cluster->endPos(); ++i) {
        fOffsets[i] += shift;
        shift += space;
    }
    if (this->size() == cluster->endPos()) {
        // To make calculations easier
        fOffsets[cluster->endPos()] += shift;
    }
    // Increment the run width
    fSpaced = true;
    fAdvance.fX += shift;
    // Increment the cluster width
    cluster->space(shift, space);

    return shift;
}

void Run::shift(const Cluster* cluster, SkScalar offset) {
    TRACE_EVENT0("skia", TRACE_FUNC);
    if (offset == 0) {
        return;
    }

    fSpaced = true;
    for (size_t i = cluster->startPos(); i < cluster->endPos(); ++i) {
        fOffsets[i] += offset;
    }
    if (this->size() == cluster->endPos()) {
        // To make calculations easier
        fOffsets[cluster->endPos()] += offset;
    }
}

void Cluster::setIsWhiteSpaces() {
    TRACE_EVENT0("skia", TRACE_FUNC);
    auto pos = fText.end();
    while (--pos >= fText.begin()) {
        auto ch = *pos;
        if (!u_isspace(ch) && u_charType(ch) != U_CONTROL_CHAR &&
            u_charType(ch) != U_NON_SPACING_MARK) {
            return;
        }
    }
    fWhiteSpaces = true;
}

SkScalar Cluster::sizeToChar(const char* ch) const {
    TRACE_EVENT0("skia", TRACE_FUNC);
    if (ch < fText.begin() || ch >= fText.end()) {
        return 0;
    }
    auto shift = ch - fText.begin();
    auto ratio = shift * 1.0 / fText.size();

    return SkDoubleToScalar(fWidth * ratio);
}

SkScalar Cluster::sizeFromChar(const char* ch) const {
    TRACE_EVENT0("skia", TRACE_FUNC);
    if (ch < fText.begin() || ch >= fText.end()) {
        return 0;
    }
    auto shift = fText.end() - ch - 1;
    auto ratio = shift * 1.0 / fText.size();

    return SkDoubleToScalar(fWidth * ratio);
}

size_t Cluster::roundPos(SkScalar s) const {
    TRACE_EVENT0("skia", TRACE_FUNC);
    auto ratio = (s * 1.0) / fWidth;
    return sk_double_floor2int(ratio * size());
}

SkScalar Cluster::trimmedWidth(size_t pos) const {
    // Find the width until the pos and return the min between trimmedWidth and the width(pos)
    return SkTMin(this->run()->positionX(pos) - this->run()->positionX(fStart), fWidth - fSpacing);
}

}  // namespace textlayout
}  // namespace skia
