/*
 *******************************************************************************
 *
 *   © 2016 and later: Unicode, Inc. and others.
 *   License & terms of use: http://www.unicode.org/copyright.html#License
 *
 *******************************************************************************
 *******************************************************************************
 *
 *   Copyright (C) 1999-2015, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  Paragraph.cpp
 *
 *   created on: 09/06/2000
 *   created by: Eric R. Mader
 */

#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/ubidi.h"
#include "unicode/ustring.h"

#include "layout/ParagraphLayout.h"

#include "RenderingSurface.h"

#include "paragraph.h"
#include "UnicodeReader.h"

#define MARGIN 10
#define LINE_GROW 32
#define PARA_GROW 8

#define CH_LF 0x000A
#define CH_CR 0x000D
#define CH_LSEP 0x2028
#define CH_PSEP 0x2029

static LEUnicode *skipLineEnd(LEUnicode *ptr)
{
    if (ptr[0] == CH_CR && ptr[1] == CH_LF) {
        ptr += 1;
    }

    return ptr + 1;
}

static le_int32 findRun(const RunArray *runArray, le_int32 offset)
{
    le_int32 runCount = runArray->getCount();

    for (le_int32 run = 0; run < runCount; run += 1) {
        if (runArray->getLimit(run) > offset) {
            return run;
        }
    }

    return -1;
}

static void subsetFontRuns(const FontRuns *fontRuns, le_int32 start, le_int32 limit, FontRuns *sub)
{
    le_int32 startRun = findRun(fontRuns, start);
    le_int32 endRun   = findRun(fontRuns, limit - 1);

    sub->reset();

    for (le_int32 run = startRun; run <= endRun; run += 1) {
        const LEFontInstance *runFont = fontRuns->getFont(run);
        le_int32 runLimit = fontRuns->getLimit(run) - start;

        if (run == endRun) {
            runLimit = limit - start;
        }

        sub->add(runFont, runLimit);
    }
}

Paragraph::Paragraph(const LEUnicode chars[], int32_t charCount, const FontRuns *fontRuns, LEErrorCode &status)
  : fParagraphLayout(NULL), fParagraphCount(0), fParagraphMax(PARA_GROW), fParagraphGrow(PARA_GROW),
    fLineCount(0), fLinesMax(LINE_GROW), fLinesGrow(LINE_GROW), fLines(NULL), fChars(NULL),
    fLineHeight(-1), fAscent(-1), fWidth(-1), fHeight(-1), fParagraphLevel(UBIDI_DEFAULT_LTR)
{
    static const LEUnicode separators[] = {CH_LF, CH_CR, CH_LSEP, CH_PSEP, 0x0000};

	if (LE_FAILURE(status)) {
		return;
	}

    le_int32 ascent  = 0;
    le_int32 descent = 0;
    le_int32 leading = 0;

	LocaleRuns *locales = NULL;
    FontRuns fr(0);

    fLines = LE_NEW_ARRAY(const ParagraphLayout::Line *, fLinesMax);
    fParagraphLayout = LE_NEW_ARRAY(ParagraphLayout *, fParagraphMax);

    fChars = LE_NEW_ARRAY(LEUnicode, charCount + 1);
    LE_ARRAY_COPY(fChars, chars, charCount);
    fChars[charCount] = 0;

    LEUnicode *pStart = &fChars[0];

    while (*pStart != 0) {
        LEUnicode *pEnd = u_strpbrk(pStart, separators);
        le_int32 pAscent, pDescent, pLeading;
        ParagraphLayout *paragraphLayout = NULL;

        if (pEnd == NULL) {
            pEnd = &fChars[charCount];
        }

        if (pEnd != pStart) {
            subsetFontRuns(fontRuns, pStart - fChars, pEnd - fChars, &fr);

            paragraphLayout = new ParagraphLayout(pStart, pEnd - pStart, &fr, NULL, NULL, locales, fParagraphLevel, FALSE, status);

            if (LE_FAILURE(status)) {
                delete paragraphLayout;
                break; // return? something else?
            }

            if (fParagraphLevel == UBIDI_DEFAULT_LTR) {
                fParagraphLevel = paragraphLayout->getParagraphLevel();
            }

            pAscent  = paragraphLayout->getAscent();
            pDescent = paragraphLayout->getDescent();
            pLeading = paragraphLayout->getLeading();

            if (pAscent > ascent) {
                ascent = pAscent;
            }

            if (pDescent > descent) {
                descent = pDescent;
            }

            if (pLeading > leading) {
                leading = pLeading;
            }
        }

        if (fParagraphCount >= fParagraphMax) {
            fParagraphLayout = (ParagraphLayout **) LE_GROW_ARRAY(fParagraphLayout, fParagraphMax + fParagraphGrow);
            fParagraphMax += fParagraphGrow;
        }

        fParagraphLayout[fParagraphCount++] = paragraphLayout;

        if (*pEnd == 0) {
            break;
        }

        pStart = skipLineEnd(pEnd);
    }

    fLineHeight = ascent + descent + leading;
    fAscent     = ascent;
}

Paragraph::~Paragraph()
{
    for (le_int32 line = 0; line < fLineCount; line += 1) {
        delete /*(LineInfo *)*/ fLines[line];
    }

    for (le_int32 paragraph = 0; paragraph < fParagraphCount; paragraph += 1) {
        delete fParagraphLayout[paragraph];
    }

    LE_DELETE_ARRAY(fLines);
    LE_DELETE_ARRAY(fParagraphLayout);
    LE_DELETE_ARRAY(fChars);
}

void Paragraph::addLine(const ParagraphLayout::Line *line)
{
    if (fLineCount >= fLinesMax) {
        fLines = (const ParagraphLayout::Line **) LE_GROW_ARRAY(fLines, fLinesMax + fLinesGrow);
        fLinesMax += fLinesGrow;
    }

    fLines[fLineCount++] = line;
}

void Paragraph::breakLines(le_int32 width, le_int32 height)
{
    fHeight = height;

    // don't re-break if the width hasn't changed
    if (fWidth == width) {
        return;
    }

    fWidth  = width;

    float lineWidth = (float) (width - 2 * MARGIN);
    const ParagraphLayout::Line *line;

    // Free the old LineInfo's...
    for (le_int32 li = 0; li < fLineCount; li += 1) {
        delete fLines[li];
    }

    fLineCount = 0;

    for (le_int32 p = 0; p < fParagraphCount; p += 1) {
        ParagraphLayout *paragraphLayout = fParagraphLayout[p];

        if (paragraphLayout != NULL) {
            paragraphLayout->reflow();
            while ((line = paragraphLayout->nextLine(lineWidth)) != NULL) {
                addLine(line);
            }
        } else {
            addLine(NULL);
        }
    }
}

void Paragraph::draw(RenderingSurface *surface, le_int32 firstLine, le_int32 lastLine)
{
    le_int32 li, x, y;

    x = MARGIN;
    y = fAscent;

    for (li = firstLine; li <= lastLine; li += 1) {
        const ParagraphLayout::Line *line = fLines[li];

        if (line != NULL) {
            le_int32 runCount = line->countRuns();
            le_int32 run;

		    if (fParagraphLevel == UBIDI_RTL) {
			    le_int32 lastX = line->getWidth();

			    x = (fWidth - lastX - MARGIN);
		    }


            for (run = 0; run < runCount; run += 1) {
                const ParagraphLayout::VisualRun *visualRun = line->getVisualRun(run);
                le_int32 glyphCount = visualRun->getGlyphCount();
                const LEFontInstance *font = visualRun->getFont();
                const LEGlyphID *glyphs = visualRun->getGlyphs();
                const float *positions = visualRun->getPositions();

                surface->drawGlyphs(font, glyphs, glyphCount, positions, x, y, fWidth, fHeight);
            }
        }

        y += fLineHeight;
    }
}

Paragraph *Paragraph::paragraphFactory(const char *fileName, const LEFontInstance *font, GUISupport *guiSupport)
{
    LEErrorCode status  = LE_NO_ERROR;
    le_int32 charCount;
    const UChar *text = UnicodeReader::readFile(fileName, guiSupport, charCount);
    Paragraph *result = NULL;

    if (text == NULL) {
        return NULL;
    }

    FontRuns  fontRuns(0);

    fontRuns.add(font, charCount);

    result = new Paragraph(text, charCount, &fontRuns, status);

	if (LE_FAILURE(status)) {
		delete result;
		result = NULL;
	}

    LE_DELETE_ARRAY(text);

    return result;    
}

