/*
*******************************************************************************
*   Copyright (C) 2001-2007, International Business Machines
*   Corporation and others.  All Rights Reserved.
*******************************************************************************
*/
/* Written by Simon Montagu, Matitiahu Allouche
 * (ported from C code written by Markus W. Scherer)
 */

package com.ibm.icu.text;

import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.Bidi;

final class BidiWriter {

    /** Bidi control code points */
    static final char LRM_CHAR = 0x200e;
    static final char RLM_CHAR = 0x200f;
    static final int MASK_R_AL = (1 << UCharacter.RIGHT_TO_LEFT |
                                  1 << UCharacter.RIGHT_TO_LEFT_ARABIC);

    private static boolean IsCombining(int type)
    {
        return ((1<<type &
                (1<<UCharacter.NON_SPACING_MARK |
                 1<<UCharacter.COMBINING_SPACING_MARK |
                 1<<UCharacter.ENCLOSING_MARK)) != 0);
    }

    /*
     * When we have OUTPUT_REVERSE set on writeReordered(), then we
     * semantically write RTL runs in reverse and later reverse them again.
     * Instead, we actually write them in forward order to begin with.
     * However, if the RTL run was to be mirrored, we need to mirror here now
     * since the implicit second reversal must not do it.
     * It looks strange to do mirroring in LTR output, but it is only because
     * we are writing RTL output in reverse.
     */
    private static String doWriteForward(String src, int options) {
        /* optimize for several combinations of options */
        switch(options&(Bidi.REMOVE_BIDI_CONTROLS|Bidi.DO_MIRRORING)) {
        case 0: {
            /* simply copy the LTR run to the destination */
            return new String(src);
        }
        case Bidi.DO_MIRRORING: {
            StringBuffer dest = new StringBuffer(src.length());

            /* do mirroring */
            int i=0;
            int c;

            do {
                c = UTF16.charAt(src, i);
                i += UTF16.getCharCount(c);
                UTF16.append(dest, UCharacter.getMirror(c));
            } while(i < src.length());
            return dest.toString();
        }
        case Bidi.REMOVE_BIDI_CONTROLS: {
            StringBuffer dest = new StringBuffer(src.length());

            /* copy the LTR run and remove any Bidi control characters */
            int i = 0;
            char c;
            do {
                c = src.charAt(i++);
                if(!Bidi.IsBidiControlChar(c)) {
                    dest.append(c);
                }
            } while(i < src.length());
            return dest.toString();
        }
        default: {
            StringBuffer dest = new StringBuffer(src.length());

            /* remove Bidi control characters and do mirroring */
            int i = 0;
            int c;
            do {
                c = UTF16.charAt(src, i);
                i += UTF16.getCharCount(c);
                if(!Bidi.IsBidiControlChar(c)) {
                    UTF16.append(dest, UCharacter.getMirror(c));
                }
            } while(i < src.length());
            return dest.toString();
        }
        } /* end of switch */
    }

    private static String doWriteForward(char[] text, int start, int limit,
                                         int options)
    {
        return doWriteForward(new String(text, start, limit - start), options);
    }

    static String writeReverse(String src, int options) {
        /*
         * RTL run -
         *
         * RTL runs need to be copied to the destination in reverse order
         * of code points, not code units, to keep Unicode characters intact.
         *
         * The general strategy for this is to read the source text
         * in backward order, collect all code units for a code point
         * (and optionally following combining characters, see below),
         * and copy all these code units in ascending order
         * to the destination for this run.
         *
         * Several options request whether combining characters
         * should be kept after their base characters,
         * whether Bidi control characters should be removed, and
         * whether characters should be replaced by their mirror-image
         * equivalent Unicode characters.
         */
        StringBuffer dest = new StringBuffer(src.length());

        /* optimize for several combinations of options */
        switch (options &
                (Bidi.REMOVE_BIDI_CONTROLS |
                 Bidi.DO_MIRRORING |
                 Bidi.KEEP_BASE_COMBINING)) {

        case 0:
            /*
             * With none of the "complicated" options set, the destination
             * run will have the same length as the source run,
             * and there is no mirroring and no keeping combining characters
             * with their base characters.
             *
             * XXX: or dest = UTF16.reverse(new StringBuffer(src));
             */

            int srcLength = src.length();

            /* preserve character integrity */
            do {
                /* i is always after the last code unit known to need to be kept
                 *  in this segment */
                int i = srcLength;

                /* collect code units for one base character */
                srcLength -= UTF16.getCharCount(UTF16.charAt(src,
                                                             srcLength - 1));

                /* copy this base character */
                dest.append(src.substring(srcLength, i));
            } while(srcLength > 0);
            break;

        case Bidi.KEEP_BASE_COMBINING:
            /*
             * Here, too, the destination
             * run will have the same length as the source run,
             * and there is no mirroring.
             * We do need to keep combining characters with their base
             * characters.
             */
            srcLength = src.length();

            /* preserve character integrity */
            do {
                /* i is always after the last code unit known to need to be kept
                 *  in this segment */
                int c;
                int i = srcLength;

                /* collect code units and modifier letters for one base
                 * character */
                do {
                    c = UTF16.charAt(src, srcLength - 1);
                    srcLength -= UTF16.getCharCount(c);
                } while(srcLength > 0 && IsCombining(UCharacter.getType(c)));

                /* copy this "user character" */
                dest.append(src.substring(srcLength, i));
            } while(srcLength > 0);
            break;

        default:
            /*
             * With several "complicated" options set, this is the most
             * general and the slowest copying of an RTL run.
             * We will do mirroring, remove Bidi controls, and
             * keep combining characters with their base characters
             * as requested.
             */
            srcLength = src.length();

            /* preserve character integrity */
            do {
                /* i is always after the last code unit known to need to be kept
                 *  in this segment */
                int i = srcLength;

                /* collect code units for one base character */
                int c = UTF16.charAt(src, srcLength - 1);
                srcLength -= UTF16.getCharCount(c);
                if ((options & Bidi.KEEP_BASE_COMBINING) != 0) {
                    /* collect modifier letters for this base character */
                    while(srcLength > 0 && IsCombining(UCharacter.getType(c))) {
                        c = UTF16.charAt(src, srcLength - 1);
                        srcLength -= UTF16.getCharCount(c);
                    }
                }

                if ((options & Bidi.REMOVE_BIDI_CONTROLS) != 0 &&
                    Bidi.IsBidiControlChar(c)) {
                    /* do not copy this Bidi control character */
                    continue;
                }

                /* copy this "user character" */
                int j = srcLength;
                if((options & Bidi.DO_MIRRORING) != 0) {
                    /* mirror only the base character */
                    c = UCharacter.getMirror(c);
                    UTF16.append(dest, c);
                    j += UTF16.getCharCount(c);
                }
                dest.append(src.substring(j, i));
            } while(srcLength > 0);
            break;
        } /* end of switch */

        return dest.toString();
    }

    static String doWriteReverse(char[] text, int start, int limit, int options)
    {
        return writeReverse(new String(text, start, limit - start), options);
    }

    static String writeReordered(Bidi bidi, short options)
    {
        int run, runCount;
        StringBuffer dest;
        char[] text = bidi.text;
        runCount = bidi.countRuns();

        /*
         * Option "insert marks" implies Bidi.INSERT_LRM_FOR_NUMERIC if the
         * reordering mode (checked below) is appropriate.
         */
        if ((bidi.reorderingOptions & Bidi.OPTION_INSERT_MARKS) != 0) {
            options |= Bidi.INSERT_LRM_FOR_NUMERIC;
            options &= ~Bidi.REMOVE_BIDI_CONTROLS;
        }
        /*
         * Option "remove controls" implies Bidi.REMOVE_BIDI_CONTROLS
         * and cancels Bidi.INSERT_LRM_FOR_NUMERIC.
         */
        if ((bidi.reorderingOptions & Bidi.OPTION_REMOVE_CONTROLS) != 0) {
            options |= Bidi.REMOVE_BIDI_CONTROLS;
            options &= ~Bidi.INSERT_LRM_FOR_NUMERIC;
        }
        /*
         * If we do not perform the "inverse Bidi" algorithm, then we
         * don't need to insert any LRMs, and don't need to test for it.
         */
        if ((bidi.reorderingMode != Bidi.REORDER_INVERSE_NUMBERS_AS_L) &&
            (bidi.reorderingMode != Bidi.REORDER_INVERSE_LIKE_DIRECT)  &&
            (bidi.reorderingMode != Bidi.REORDER_INVERSE_FOR_NUMBERS_SPECIAL) &&
            (bidi.reorderingMode != Bidi.REORDER_RUNS_ONLY)) {
            options &= ~Bidi.INSERT_LRM_FOR_NUMERIC;
        }
        dest = new StringBuffer((options & Bidi.INSERT_LRM_FOR_NUMERIC) != 0
            ? bidi.getLength() * 2 : bidi.getLength());
        /*
         * Iterate through all visual runs and copy the run text segments to
         * the destination, according to the options.
         *
         * The tests for where to insert LRMs ignore the fact that there may be
         * BN codes or non-BMP code points at the beginning and end of a run;
         * they may insert LRMs unnecessarily but the tests are faster this way
         * (this would have to be improved for UTF-8).
         */
        if ((options & Bidi.OUTPUT_REVERSE) == 0) {
            /* forward output */
            if ((options & Bidi.INSERT_LRM_FOR_NUMERIC) == 0) {
                /* do not insert Bidi controls */
                for (run = 0; run < runCount; ++run) {
                    BidiRun bidiRun = bidi.getVisualRun(run);
                    if (bidiRun.isEvenRun()) {
                        dest.append(doWriteForward(text, bidiRun.start,
                                                   bidiRun.limit,
                                                   options & ~Bidi.DO_MIRRORING));
                     } else {
                        dest.append(doWriteReverse(text, bidiRun.start,
                                                   bidiRun.limit, options));
                     }
                }
            } else {
                /* insert Bidi controls for "inverse Bidi" */
                byte[] dirProps = bidi.dirProps;
                char uc;
                int markFlag;

                for (run = 0; run < runCount; ++run) {
                    BidiRun bidiRun = bidi.getVisualRun(run);
                    markFlag=0;
                    /* check if something relevant in insertPoints */
                    markFlag = bidi.runs[run].insertRemove;
                    if (markFlag < 0) { /* insert count */
                        markFlag = 0;
                    }
                    if (bidiRun.isEvenRun()) {
                        if (bidi.isInverse() &&
                                dirProps[bidiRun.start] != Bidi.L) {
                            markFlag |= Bidi.LRM_BEFORE;
                        }
                        if ((markFlag & Bidi.LRM_BEFORE) != 0) {
                            uc = LRM_CHAR;
                        } else if ((markFlag & Bidi.RLM_BEFORE) != 0) {
                            uc = RLM_CHAR;
                        } else {
                            uc = 0;
                        }
                        if (uc != 0) {
                            dest.append(uc);
                        }
                        dest.append(doWriteForward(text,
                                                   bidiRun.start, bidiRun.limit,
                                                   options & ~Bidi.DO_MIRRORING));

                        if (bidi.isInverse() &&
                             dirProps[bidiRun.limit - 1] != Bidi.L) {
                            markFlag |= Bidi.LRM_AFTER;
                        }
                        if ((markFlag & Bidi.LRM_AFTER) != 0) {
                            uc = LRM_CHAR;
                        } else if ((markFlag & Bidi.RLM_AFTER) != 0) {
                            uc = RLM_CHAR;
                        } else {
                            uc = 0;
                        }
                        if (uc != 0) {
                            dest.append(uc);
                        }
                    } else { /* RTL run */
                        if (bidi.isInverse() &&
                            !bidi.testDirPropFlagAt(MASK_R_AL,
                                                    bidiRun.limit - 1)) {
                            markFlag |= Bidi.RLM_BEFORE;
                        }
                        if ((markFlag & Bidi.LRM_BEFORE) != 0) {
                            uc = LRM_CHAR;
                        } else if ((markFlag & Bidi.RLM_BEFORE) != 0) {
                            uc = RLM_CHAR;
                        } else {
                            uc = 0;
                        }
                        if (uc != 0) {
                            dest.append(uc);
                        }
                        dest.append(doWriteReverse(text, bidiRun.start,
                                                   bidiRun.limit, options));

                        if(bidi.isInverse() &&
                                (MASK_R_AL & Bidi.DirPropFlag(dirProps[bidiRun.start])) == 0) {
                            markFlag |= Bidi.RLM_AFTER;
                        }
                        if ((markFlag & Bidi.LRM_AFTER) != 0) {
                            uc = LRM_CHAR;
                        } else if ((markFlag & Bidi.RLM_AFTER) != 0) {
                            uc = RLM_CHAR;
                        } else {
                            uc = 0;
                        }
                        if (uc != 0) {
                            dest.append(uc);
                        }
                    }
                }
            }
        } else {
            /* reverse output */
            if((options & Bidi.INSERT_LRM_FOR_NUMERIC) == 0) {
                /* do not insert Bidi controls */
                for(run = runCount; --run >= 0; ) {
                    BidiRun bidiRun = bidi.getVisualRun(run);
                    if (bidiRun.isEvenRun()) {
                        dest.append(doWriteReverse(text,
                                                   bidiRun.start, bidiRun.limit,
                                                   options & ~Bidi.DO_MIRRORING));
                    } else {
                        dest.append(doWriteForward(text, bidiRun.start,
                                                   bidiRun.limit, options));
                    }
                }
            } else {
                /* insert Bidi controls for "inverse Bidi" */

                byte[] dirProps = bidi.dirProps;

                for (run = runCount; --run >= 0; ) {
                    /* reverse output */
                    BidiRun bidiRun = bidi.getVisualRun(run);
                    if (bidiRun.isEvenRun()) {
                        if (dirProps[bidiRun.limit - 1] != Bidi.L) {
                            dest.append(LRM_CHAR);
                        }

                        dest.append(doWriteReverse(text, bidiRun.start,
                                bidiRun.limit, options & ~Bidi.DO_MIRRORING));

                        if (dirProps[bidiRun.start] != Bidi.L) {
                            dest.append(LRM_CHAR);
                        }
                    } else {
                        if ((MASK_R_AL & Bidi.DirPropFlag(dirProps[bidiRun.start])) == 0) {
                            dest.append(RLM_CHAR);
                        }

                        dest.append(doWriteForward(text, bidiRun.start,
                                                   bidiRun.limit, options));

                        if ((MASK_R_AL & Bidi.DirPropFlag(dirProps[bidiRun.limit - 1])) == 0) {
                            dest.append(RLM_CHAR);
                        }
                    }
                }
            }
        }

        return dest.toString();
    }
}
