/*
 *******************************************************************************
 *
 *   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;    
}

