// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 *
 *   Copyright (C) 1999-2003, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  scrptrun.h
 *
 *   created on: 10/17/2001
 *   created by: Eric R. Mader
 */

#ifndef __SCRPTRUN_H
#define __SCRPTRUN_H

#include <unicode/utypes.h>
#include <unicode/uobject.h>
#include <unicode/uscript.h>
#include <array>

U_NAMESPACE_BEGIN

struct ScriptRecord
{
    UChar32 startChar = 0;
    UChar32 endChar = 0;
    UScriptCode scriptCode{};
};

struct ParenStackEntry
{
    int32_t pairIndex = 0;
    UScriptCode scriptCode{};
};

class ScriptRun : public UObject {
public:
    ScriptRun();

    ScriptRun(const char16_t *chars, int32_t length);

    ScriptRun(const char16_t *chars, int32_t start, int32_t length);

    void reset();

    void reset(int32_t start, int32_t count);

    void reset(const char16_t *chars, int32_t start, int32_t length);

    int32_t getScriptStart();

    int32_t getScriptEnd();

    UScriptCode getScriptCode();

    UBool next();

    /**
     * ICU "poor man's RTTI", returns a UClassID for the actual class.
     *
     * @stable ICU 2.2
     */
    virtual inline UClassID getDynamicClassID() const override { return getStaticClassID(); }

    /**
     * ICU "poor man's RTTI", returns a UClassID for this class.
     *
     * @stable ICU 2.2
     */
    static inline UClassID getStaticClassID() { return (UClassID)const_cast<char *>(&fgClassID); }

private:

    static UBool sameScript(int32_t scriptOne, int32_t scriptTwo);

    int32_t charStart = 0;
    int32_t charLimit = 0;
    const char16_t *charArray = nullptr;

    int32_t scriptStart = 0;
    int32_t scriptEnd = 0;
    UScriptCode scriptCode{};

    std::array<ParenStackEntry, 128> parenStack{};
    int32_t parenSP = 0;

    static int8_t highBit(int32_t value);
    static int32_t getPairIndex(UChar32 ch);

    static UChar32 pairedChars[];
    static const int32_t pairedCharCount;
    static const int32_t pairedCharPower;
    static const int32_t pairedCharExtra;

    /**
     * The address of this static class variable serves as this class's ID
     * for ICU "poor man's RTTI".
     */
    static const char fgClassID;
};

inline ScriptRun::ScriptRun()
{
    reset(nullptr, 0, 0);
}

inline ScriptRun::ScriptRun(const char16_t *chars, int32_t length)
{
    reset(chars, 0, length);
}

inline ScriptRun::ScriptRun(const char16_t *chars, int32_t start, int32_t length)
{
    reset(chars, start, length);
}

inline int32_t ScriptRun::getScriptStart()
{
    return scriptStart;
}

inline int32_t ScriptRun::getScriptEnd()
{
    return scriptEnd;
}

inline UScriptCode ScriptRun::getScriptCode()
{
    return scriptCode;
}

inline void ScriptRun::reset()
{
    scriptStart = charStart;
    scriptEnd   = charStart;
    scriptCode  = USCRIPT_INVALID_CODE;
    parenSP     = -1;
}

inline void ScriptRun::reset(int32_t start, int32_t length)
{
    charStart = start;
    charLimit = start + length;

    reset();
}

inline void ScriptRun::reset(const char16_t *chars, int32_t start, int32_t length)
{
    charArray = chars;

    reset(start, length);
}

U_NAMESPACE_END

#endif
