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

#include "SkFontMetrics.h"
#include "SkMakeUnique.h"
#include "SkShaper.h"
#include "SkStream.h"
#include "SkTo.h"
#include "SkTypeface.h"
#include "SkUTF.h"

class SkShaperPrimitive : public SkShaper {
public:
    SkShaperPrimitive() {}
private:
    SkPoint shape(RunHandler* handler,
                  const SkFont& srcFont,
                  const char* utf8text,
                  size_t textBytes,
                  bool leftToRight,
                  SkPoint point,
                  SkScalar width) const override;
};

std::unique_ptr<SkShaper> SkShaper::MakePrimitive() {
    return skstd::make_unique<SkShaperPrimitive>();
}

static inline bool is_breaking_whitespace(SkUnichar c) {
    switch (c) {
        case 0x0020: // SPACE
        //case 0x00A0: // NO-BREAK SPACE
        case 0x1680: // OGHAM SPACE MARK
        case 0x180E: // MONGOLIAN VOWEL SEPARATOR
        case 0x2000: // EN QUAD
        case 0x2001: // EM QUAD
        case 0x2002: // EN SPACE (nut)
        case 0x2003: // EM SPACE (mutton)
        case 0x2004: // THREE-PER-EM SPACE (thick space)
        case 0x2005: // FOUR-PER-EM SPACE (mid space)
        case 0x2006: // SIX-PER-EM SPACE
        case 0x2007: // FIGURE SPACE
        case 0x2008: // PUNCTUATION SPACE
        case 0x2009: // THIN SPACE
        case 0x200A: // HAIR SPACE
        case 0x200B: // ZERO WIDTH SPACE
        case 0x202F: // NARROW NO-BREAK SPACE
        case 0x205F: // MEDIUM MATHEMATICAL SPACE
        case 0x3000: // IDEOGRAPHIC SPACE
        //case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
            return true;
        default:
            return false;
    }
}

static size_t linebreak(const char text[], const char stop[],
                        const SkFont& font, SkScalar width,
                        SkScalar* advance,
                        size_t* trailing)
{
    SkScalar accumulatedWidth = 0;
    int glyphIndex = 0;
    const char* start = text;
    const char* word_start = text;
    bool prevWS = true;
    *trailing = 0;

    while (text < stop) {
        const char* prevText = text;
        SkUnichar uni = SkUTF::NextUTF8(&text, stop);
        accumulatedWidth += advance[glyphIndex++];
        bool currWS = is_breaking_whitespace(uni);

        if (!currWS && prevWS) {
            word_start = prevText;
        }
        prevWS = currWS;

        if (width < accumulatedWidth) {
            if (currWS) {
                // eat the rest of the whitespace
                const char* next = text;
                while (next < stop && is_breaking_whitespace(SkUTF::NextUTF8(&next, stop))) {
                    text = next;
                }
                if (trailing) {
                    *trailing = text - prevText;
                }
            } else {
                // backup until a whitespace (or 1 char)
                if (word_start == start) {
                    if (prevText > start) {
                        text = prevText;
                    }
                } else {
                    text = word_start;
                }
            }
            break;
        }

        if ('\n' == uni) {
            size_t ret = text - start;
            size_t lineBreakSize = 1;
            if (text < stop) {
                uni = SkUTF::NextUTF8(&text, stop);
                if ('\r' == uni) {
                    ret = text - start;
                    ++lineBreakSize;
                }
            }
            if (trailing) {
                *trailing = lineBreakSize;
            }
            return ret;
        }

        if ('\r' == uni) {
            size_t ret = text - start;
            size_t lineBreakSize = 1;
            if (text < stop) {
                uni = SkUTF::NextUTF8(&text, stop);
                if ('\n' == uni) {
                    ret = text - start;
                    ++lineBreakSize;
                }
            }
            if (trailing) {
                *trailing = lineBreakSize;
            }
            return ret;
        }
    }

    return text - start;
}

SkPoint SkShaperPrimitive::shape(RunHandler* handler,
                                 const SkFont& font,
                                 const char* utf8text,
                                 size_t textBytes,
                                 bool leftToRight,
                                 SkPoint point,
                                 SkScalar width) const {
    sk_ignore_unused_variable(leftToRight);

    int glyphCount = font.countText(utf8text, textBytes, SkTextEncoding::kUTF8);
    if (glyphCount <= 0) {
        return point;
    }

    std::unique_ptr<SkGlyphID[]> glyphs(new SkGlyphID[glyphCount]);
    font.textToGlyphs(utf8text, textBytes, SkTextEncoding::kUTF8, glyphs.get(), glyphCount);

    std::unique_ptr<SkScalar[]> advances(new SkScalar[glyphCount]);
    font.getWidthsBounds(glyphs.get(), glyphCount, advances.get(), nullptr, nullptr);

    SkFontMetrics metrics;
    font.getMetrics(&metrics);

    size_t glyphOffset = 0;
    size_t utf8Offset = 0;
    while (0 < textBytes) {
        point.fY -= metrics.fAscent;

        size_t bytesCollapsed;
        size_t bytesConsumed = linebreak(utf8text, utf8text + textBytes, font, width,
                                         advances.get() + glyphOffset, &bytesCollapsed);
        size_t bytesVisible = bytesConsumed - bytesCollapsed;

        int numGlyphs = SkUTF::CountUTF8(utf8text, bytesVisible);
        const RunHandler::RunInfo info = {
            { font.measureText(utf8text, bytesVisible, SkTextEncoding::kUTF8), 0 },
            metrics.fAscent,
            metrics.fDescent,
            metrics.fLeading,
        };
        const auto buffer = handler->newRunBuffer(info, font, numGlyphs,
                                                  SkSpan<const char>(utf8text, bytesVisible));

        memcpy(buffer.glyphs, glyphs.get() + glyphOffset, numGlyphs * sizeof(SkGlyphID));
        SkScalar position = point.fX;
        for (int i = 0; i < numGlyphs; ++i) {
            buffer.positions[i] = { position, point.fY };
            position += advances[i + glyphOffset];
        }
        if (buffer.clusters) {
            const char* txtPtr = utf8text;
            for (int i = 0; i < numGlyphs; ++i) {
                // Each character maps to exactly one glyph.
                buffer.clusters[i] = SkToU32(txtPtr - utf8text + utf8Offset);
                SkUTF::NextUTF8(&txtPtr, utf8text + textBytes);
            }
        }
        handler->commitRun();
        handler->commitLine();

        glyphOffset += SkUTF::CountUTF8(utf8text, bytesConsumed);
        utf8Offset += bytesConsumed;
        utf8text += bytesConsumed;
        textBytes -= bytesConsumed;
        point.fY += metrics.fDescent + metrics.fLeading;
    }

    return point;
}
