/*
 *******************************************************************************
 * Copyright (C) 2008-2015, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
package com.ibm.icu.charset;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.UnsupportedCharsetException;

import com.ibm.icu.text.UTF16;
import com.ibm.icu.text.UnicodeSet;

class CharsetHZ extends CharsetICU {

    private static final int UCNV_TILDE = 0x7E; /* ~ */
    private static final int UCNV_OPEN_BRACE = 0x7B; /* { */
    private static final int UCNV_CLOSE_BRACE = 0x7D; /* } */
    private static final byte[] SB_ESCAPE = new byte[] { 0x7E, 0x7D };
    private static final byte[] DB_ESCAPE = new byte[] { 0x7E, 0x7B };
    private static final byte[] TILDE_ESCAPE = new byte[] { 0x7E, 0x7E };
    private static final byte[] fromUSubstitution = new byte[] { (byte) 0x1A };

    private CharsetMBCS gbCharset;
    private boolean isEmptySegment;

    public CharsetHZ(String icuCanonicalName, String canonicalName, String[] aliases) {
        super(icuCanonicalName, canonicalName, aliases);
        gbCharset = (CharsetMBCS) new CharsetProviderICU().charsetForName("GBK");
        if (gbCharset == null) {
            throw new UnsupportedCharsetException("unable to open ICU GBK Charset, required for HZ");
        }

        maxBytesPerChar = 4;
        minBytesPerChar = 1;
        maxCharsPerByte = 1;
        
        isEmptySegment = false;
    }

    class CharsetDecoderHZ extends CharsetDecoderICU {
        CharsetMBCS.CharsetDecoderMBCS gbDecoder;
        boolean isStateDBCS = false;

        public CharsetDecoderHZ(CharsetICU cs) {
            super(cs);
            gbDecoder = (CharsetMBCS.CharsetDecoderMBCS) gbCharset.newDecoder();
        }

        protected void implReset() {
            super.implReset();
            gbDecoder.implReset();

            isStateDBCS = false;
            isEmptySegment = false;
        }

        protected CoderResult decodeLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets, boolean flush) {
            CoderResult err = CoderResult.UNDERFLOW;
            byte[] tempBuf = new byte[2];
            int targetUniChar = 0;
            int mySourceChar = 0;

            if (!source.hasRemaining())
                return CoderResult.UNDERFLOW;
            else if (!target.hasRemaining())
                return CoderResult.OVERFLOW;

            while (source.hasRemaining()) {

                if (target.hasRemaining()) {

                    // get the byte as unsigned
                    mySourceChar = source.get() & 0xff;

                    if (mode == UCNV_TILDE) {
                        /* second byte after ~ */
                        mode = 0;
                        switch (mySourceChar) {
                        case 0x0A:
                            /* no output for ~\n (line-continuation marker) */
                            continue;
                        case UCNV_TILDE:
                            if (offsets != null) {
                                offsets.put(source.position() - 2);
                            }
                            target.put((char) mySourceChar);
                            continue;
                        case UCNV_OPEN_BRACE:
                        case UCNV_CLOSE_BRACE:
                            isStateDBCS = (mySourceChar == UCNV_OPEN_BRACE);
                            if (isEmptySegment) {
                                isEmptySegment = false; /* we are handling it, reset to avoid future spurious errors */
                                this.toUBytesArray[0] = UCNV_TILDE;
                                this.toUBytesArray[1] = (byte)mySourceChar;
                                this.toULength = 2;
                                return CoderResult.malformedForLength(1);
                            }
                            isEmptySegment = true;
                            continue;
                        default:
                            /*
                             * if the first byte is equal to TILDE and the trail byte is not a valid byte then it is an
                             * error condition
                             */
                            /*
                             * Ticket 5691: consistent illegal sequences:
                             * - We include at least the first byte in the illegal sequence.
                             * - If any of the non-initial bytes could be the start of a character,
                             *   we stop the illegal sequence before the first one of those.
                             */
                            isEmptySegment = false; /* different error here, reset this to avoid spurious furture error */
                            err = CoderResult.malformedForLength(1);
                            toUBytesArray[0] = UCNV_TILDE;
                            if (isStateDBCS ? (0x21 <= mySourceChar && mySourceChar <= 0x7e) : mySourceChar <= 0x7f) {
                                /* The current byte could be the start of a character: Back it out. */
                                toULength = 1;
                                source.position(source.position() - 1);
                            } else {
                                /* Include the current byte in the illegal sequence. */
                                toUBytesArray[1] = (byte)mySourceChar;
                                toULength = 2;
                            }
                            return err;
                        }
                    } else if (isStateDBCS) {
                        if (toUnicodeStatus == 0) {
                            /* lead byte */
                            if (mySourceChar == UCNV_TILDE) {
                                mode = UCNV_TILDE;
                            } else {
                                /*
                                 * add another bit to distinguish a 0 byte from not having seen a lead byte
                                 */
                                toUnicodeStatus = mySourceChar | 0x100;
                                isEmptySegment = false; /* the segment has something, either valid or will produce a different error, so reset this */ 
                            }
                            continue;
                        } else {
                            /* trail byte */
                            boolean leadIsOk, trailIsOk;
                            int leadByte = toUnicodeStatus & 0xff;
                            targetUniChar = 0xffff;
                            /*
                             * Ticket 5691: consistent illegal sequence
                             * - We include at least the first byte in the illegal sequence.
                             * - If any of the non-initial bytes could be the start of a character,
                             *   we stop the illegal sequence before the first one of those
                             * 
                             * In HZ DBCS, if the second byte is in the 21..7e range,
                             * we report ony the first byte as the illegal sequence.
                             * Otherwise we convert of report the pair of bytes.
                             */
                            leadIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (leadByte - 0x21)) <= (0x7d - 0x21);
                            trailIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (mySourceChar - 0x21)) <= (0x7e - 0x21);
                            if (leadIsOk && trailIsOk) {
                                tempBuf[0] = (byte)(leadByte + 0x80);
                                tempBuf[1] = (byte)(mySourceChar + 0x80);
                                targetUniChar = gbDecoder.simpleGetNextUChar(ByteBuffer.wrap(tempBuf), super.isFallbackUsed());
                                mySourceChar = (leadByte << 8) | mySourceChar;
                            } else if (trailIsOk) {
                                /* report a single illegal byte and continue with the following DBCS starter byte */
                                source.position(source.position() - 1);
                                mySourceChar = leadByte;
                            } else {
                                /* report a pair of illegal bytes if the second byte is not a DBCS starter */
                                /* add another bit so that the code below writes 2 bytes in case of error */
                                mySourceChar = 0x10000 | (leadByte << 8) | mySourceChar;
                            }
                            toUnicodeStatus = 0x00;
                        }
                    } else {
                        if (mySourceChar == UCNV_TILDE) {
                            mode = UCNV_TILDE;
                            continue;
                        } else if (mySourceChar <= 0x7f) {
                            targetUniChar = mySourceChar; /* ASCII */
                            isEmptySegment = false; /* the segment has something valid */
                        } else {
                            targetUniChar = 0xffff;
                            isEmptySegment = false; /* different error here, reset this to avoid spurious future error */
                        }
                    }

                    if (targetUniChar < 0xfffe) {
                        if (offsets != null) {
                            offsets.put(source.position() - 1 - (isStateDBCS ? 1 : 0));
                        }

                        target.put((char) targetUniChar);
                    } else /* targetUniChar >= 0xfffe */{
                        if (mySourceChar > 0xff) {
                            toUBytesArray[toUBytesBegin + 0] = (byte) (mySourceChar >> 8);
                            toUBytesArray[toUBytesBegin + 1] = (byte) mySourceChar;
                            toULength = 2;
                        } else {
                            toUBytesArray[toUBytesBegin + 0] = (byte) mySourceChar;
                            toULength = 1;
                        }
                        if (targetUniChar == 0xfffe) {
                            return CoderResult.unmappableForLength(toULength);
                        } else {
                            return CoderResult.malformedForLength(toULength);
                        }
                    }
                } else {
                    return CoderResult.OVERFLOW;
                }
            }

            return err;
        }
    }

    class CharsetEncoderHZ extends CharsetEncoderICU {
        CharsetMBCS.CharsetEncoderMBCS gbEncoder;
        boolean isEscapeAppended = false;
        boolean isTargetUCharDBCS = false;

        public CharsetEncoderHZ(CharsetICU cs) {
            super(cs, fromUSubstitution);
            gbEncoder = (CharsetMBCS.CharsetEncoderMBCS) gbCharset.newEncoder();
        }

        protected void implReset() {
            super.implReset();
            gbEncoder.implReset();

            isEscapeAppended = false;
            isTargetUCharDBCS = false;
        }

        protected CoderResult encodeLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
            int length = 0;
            int[] targetUniChar = new int[] { 0 };
            int mySourceChar = 0;
            boolean oldIsTargetUCharDBCS = isTargetUCharDBCS;

            if (!source.hasRemaining())
                return CoderResult.UNDERFLOW;
            else if (!target.hasRemaining())
                return CoderResult.OVERFLOW;

            if (fromUChar32 != 0 && target.hasRemaining()) {
                CoderResult cr = handleSurrogates(source, (char) fromUChar32);
                return (cr != null) ? cr : CoderResult.unmappableForLength(2);
            }
            /* writing the char to the output stream */
            while (source.hasRemaining()) {
                targetUniChar[0] = MISSING_CHAR_MARKER;
                if (target.hasRemaining()) {

                    mySourceChar = source.get();

                    oldIsTargetUCharDBCS = isTargetUCharDBCS;
                    if (mySourceChar == UCNV_TILDE) {
                        /*
                         * concatEscape(args, &myTargetIndex, &targetLength,"\x7E\x7E",err,2,&mySourceIndex);
                         */
                        concatEscape(source, target, offsets, TILDE_ESCAPE);
                        continue;
                    } else if (mySourceChar <= 0x7f) {
                        length = 1;
                        targetUniChar[0] = mySourceChar;
                    } else {
                        length = gbEncoder.fromUChar32(mySourceChar, targetUniChar, super.isFallbackUsed());

                        /*
                         * we can only use lead bytes 21..7D and trail bytes 21..7E
                         */
                        if (length == 2 && 0xa1a1 <= targetUniChar[0] && targetUniChar[0] <= 0xfdfe
                                && 0xa1 <= (targetUniChar[0] & 0xff) && (targetUniChar[0] & 0xff) <= 0xfe) {
                            targetUniChar[0] -= 0x8080;
                        } else {
                            targetUniChar[0] = MISSING_CHAR_MARKER;
                        }
                    }
                    if (targetUniChar[0] != MISSING_CHAR_MARKER) {
                        isTargetUCharDBCS = (targetUniChar[0] > 0x00FF);
                        if (oldIsTargetUCharDBCS != isTargetUCharDBCS || !isEscapeAppended) {
                            /* Shifting from a double byte to single byte mode */
                            if (!isTargetUCharDBCS) {
                                concatEscape(source, target, offsets, SB_ESCAPE);
                                isEscapeAppended = true;
                            } else { /*
                                         * Shifting from a single byte to double byte mode
                                         */
                                concatEscape(source, target, offsets, DB_ESCAPE);
                                isEscapeAppended = true;

                            }
                        }

                        if (isTargetUCharDBCS) {
                            if (target.hasRemaining()) {
                                target.put((byte) (targetUniChar[0] >> 8));
                                if (offsets != null) {
                                    offsets.put(source.position() - 1);
                                }
                                if (target.hasRemaining()) {
                                    target.put((byte) targetUniChar[0]);
                                    if (offsets != null) {
                                        offsets.put(source.position() - 1);
                                    }
                                } else {
                                    errorBuffer[errorBufferLength++] = (byte) targetUniChar[0];
                                    // *err = U_BUFFER_OVERFLOW_ERROR;
                                }
                            } else {
                                errorBuffer[errorBufferLength++] = (byte) (targetUniChar[0] >> 8);
                                errorBuffer[errorBufferLength++] = (byte) targetUniChar[0];
                                // *err = U_BUFFER_OVERFLOW_ERROR;
                            }

                        } else {
                            if (target.hasRemaining()) {
                                target.put((byte) targetUniChar[0]);
                                if (offsets != null) {
                                    offsets.put(source.position() - 1);
                                }

                            } else {
                                errorBuffer[errorBufferLength++] = (byte) targetUniChar[0];
                                // *err = U_BUFFER_OVERFLOW_ERROR;
                            }
                        }

                    } else {
                        /* oops.. the code point is unassigned */
                        /* Handle surrogates */
                        /* check if the char is a First surrogate */

                        if (UTF16.isSurrogate((char) mySourceChar)) {
                            // use that handy handleSurrogates method everyone's been talking about!
                            CoderResult cr = handleSurrogates(source, (char) mySourceChar);
                            return (cr != null) ? cr : CoderResult.unmappableForLength(2);
                        } else {
                            /* callback(unassigned) for a BMP code point */
                            // *err = U_INVALID_CHAR_FOUND;
                            fromUChar32 = mySourceChar;
                            return CoderResult.unmappableForLength(1);
                        }
                    }
                } else {
                    // *err = U_BUFFER_OVERFLOW_ERROR;
                    return CoderResult.OVERFLOW;
                }
            }

            return CoderResult.UNDERFLOW;
        }

        private CoderResult concatEscape(CharBuffer source, ByteBuffer target, IntBuffer offsets, byte[] strToAppend) {
            CoderResult cr = null;
            for (int i=0; i<strToAppend.length; i++) {
                byte b = strToAppend[i];
                if (target.hasRemaining()) {
                    target.put(b);
                    if (offsets != null)
                        offsets.put(source.position() - 1);
                } else {
                    errorBuffer[errorBufferLength++] = b;
                    cr = CoderResult.OVERFLOW;
                }
            }
            return cr;
        }
    }

    public CharsetDecoder newDecoder() {
        return new CharsetDecoderHZ(this);
    }

    public CharsetEncoder newEncoder() {
        return new CharsetEncoderHZ(this);
    }
    
    void getUnicodeSetImpl( UnicodeSet setFillIn, int which){
        setFillIn.add(0,0x7f);
       // CharsetMBCS mbcshz = (CharsetMBCS)CharsetICU.forNameICU("icu-internal-25546");
        gbCharset.MBCSGetFilteredUnicodeSetForUnicode(gbCharset.sharedData, setFillIn, which, CharsetMBCS.UCNV_SET_FILTER_HZ);
    }
}
