/**
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.kerby.xdr.type;

import org.apache.kerby.xdr.XdrDataType;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/*
 *  From RFC 4506 :
 *
 *  0     1     2     3     4     5   ...
 *        +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
 *        |        length n       |byte0|byte1|...| n-1 |  0  |...|  0  |
 *        +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
 *        |--------4 bytes--------|-------n bytes-------|----r bytes----|
 *                                |-----n+r (where (n+r) mod 4 = 0)-----|
 *                                                                 STRING
 */
public class XdrString extends XdrSimple<String> {
    private int padding;

    public XdrString() {
        this((String) null);
    }

    public XdrString(String value) {
        super(XdrDataType.STRING, value);
    }

    @Override
    protected void toBytes() {
        if (getValue() != null) {
            /**Default value of byte is 0. So we don't have to initialize it with 0*/
            byte[] bytes = new byte[encodingBodyLength()];
            int length = bytes.length - padding - 4;
            bytes[0] = (byte) (length >> 24);
            bytes[1] = (byte) (length >> 16);
            bytes[2] = (byte) (length >> 8);
            bytes[3] = (byte) (length);
            System.arraycopy(getValue().getBytes(), 0, bytes, 4, length);
            setBytes(bytes);
        }
    }

    @Override
    protected int encodingBodyLength() {
        if (getValue() != null) {
            padding = (4 - getValue().length() % 4) % 4;
            return getValue().length() + padding + 4;
        }
        return 0;
    }

    protected void toValue() throws IOException {
        byte[] bytes = getBytes();
        byte[] header = new byte[4];
        System.arraycopy(bytes, 0, header, 0, 4);
        int stringLen  = ByteBuffer.wrap(header).getInt();
        int paddingBytes = (4 - (stringLen % 4)) % 4;
        validatePaddingBytes(paddingBytes);
        setPadding(paddingBytes);

        if (bytes.length != stringLen + 4 + paddingBytes) {
            int totalLength = stringLen + paddingBytes + 4;
            byte[] stringBytes = ByteBuffer.allocate(totalLength).put(getBytes(),
                0, totalLength).array();
            /**reset bytes in case the enum type is in a struct or union*/
            setBytes(stringBytes);
        }

        byte[] content = new byte[stringLen];
        if (bytes.length > 1) {
            System.arraycopy(bytes, 4, content, 0, stringLen);
        }
        setValue(new String(content, StandardCharsets.US_ASCII));
    }

    public void setPadding(int padding) {
        this.padding = padding;
    }

    public int getPadding() {
        return padding;
    }

    public static String fromUTF8ByteArray(byte[] bytes) {
        int i = 0;
        int length = 0;

        while (i < bytes.length) {
            length++;
            if ((bytes[i] & 0xf0) == 0xf0) {
                // surrogate pair
                length++;
                i += 4;
            } else if ((bytes[i] & 0xe0) == 0xe0) {
                i += 3;
            } else if ((bytes[i] & 0xc0) == 0xc0) {
                i += 2;
            } else {
                i += 1;
            }
        }

        char[] cs = new char[length];
        i = 0;
        length = 0;

        while (i < bytes.length) {
            char ch;

            if ((bytes[i] & 0xf0) == 0xf0) {
                int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i + 1] & 0x3F) << 12)
                        | ((bytes[i + 2] & 0x3F) << 6) | (bytes[i + 3] & 0x3F);
                int u = codePoint - 0x10000;
                char w1 = (char) (0xD800 | (u >> 10));
                char w2 = (char) (0xDC00 | (u & 0x3FF));
                cs[length++] = w1;
                ch = w2;
                i += 4;
            } else if ((bytes[i] & 0xe0) == 0xe0) {
                ch = (char) (((bytes[i] & 0x0f) << 12)
                        | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
                i += 3;
            } else if ((bytes[i] & 0xd0) == 0xd0) {
                ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
                i += 2;
            } else if ((bytes[i] & 0xc0) == 0xc0) {
                ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
                i += 2;
            } else {
                ch = (char) (bytes[i] & 0xff);
                i += 1;
            }

            cs[length++] = ch;
        }

        return new String(cs);
    }

    public static byte[] toUTF8ByteArray(String string) {
        return toUTF8ByteArray(string.toCharArray());
    }

    public static byte[] toUTF8ByteArray(char[] string) {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        try {
            toUTF8ByteArray(string, bOut);
        } catch (IOException e) {
            throw new IllegalStateException("cannot encode string to byte array!");
        }

        return bOut.toByteArray();
    }

    public static void toUTF8ByteArray(char[] string, OutputStream sOut) throws IOException {
        char[] c = string;
        int i = 0;

        while (i < c.length) {
            char ch = c[i];

            if (ch < 0x0080) {
                sOut.write(ch);
            } else if (ch < 0x0800) {
                sOut.write(0xc0 | (ch >> 6));
                sOut.write(0x80 | (ch & 0x3f));
            } else if (ch >= 0xD800 && ch <= 0xDFFF) {
                // in error - can only happen, if the Java String class has a
                // bug.
                if (i + 1 >= c.length) {
                    throw new IllegalStateException("invalid UTF-16 codepoint");
                }
                char w1 = ch;
                ch = c[++i];
                char w2 = ch;
                // in error - can only happen, if the Java String class has a
                // bug.
                if (w1 > 0xDBFF) {
                    throw new IllegalStateException("invalid UTF-16 codepoint");
                }
                int codePoint = ((w1 & 0x03FF) << 10) | (w2 & 0x03FF) + 0x10000;
                sOut.write(0xf0 | (codePoint >> 18));
                sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
                sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
                sOut.write(0x80 | (codePoint & 0x3F));
            } else {
                sOut.write(0xe0 | (ch >> 12));
                sOut.write(0x80 | ((ch >> 6) & 0x3F));
                sOut.write(0x80 | (ch & 0x3F));
            }

            i++;
        }
    }

    /**
     * A locale independent version of toUpperCase.
     *
     * @param string input to be converted
     * @return a US Ascii uppercase version
     */
    public static String toUpperCase(String string) {
        boolean changed = false;
        char[] chars = string.toCharArray();

        for (int i = 0; i != chars.length; i++) {
            char ch = chars[i];
            if ('a' <= ch && 'z' >= ch) {
                changed = true;
                chars[i] = (char) (ch - 'a' + 'A');
            }
        }

        if (changed) {
            return new String(chars);
        }

        return string;
    }

    /**
     * A locale independent version of toLowerCase.
     *
     * @param string input to be converted
     * @return a US ASCII lowercase version
     */
    public static String toLowerCase(String string) {
        boolean changed = false;
        char[] chars = string.toCharArray();

        for (int i = 0; i != chars.length; i++) {
            char ch = chars[i];
            if ('A' <= ch && 'Z' >= ch) {
                changed = true;
                chars[i] = (char) (ch - 'A' + 'a');
            }
        }

        if (changed) {
            return new String(chars);
        }

        return string;
    }

    public static byte[] toByteArray(char[] chars) {
        byte[] bytes = new byte[chars.length];

        for (int i = 0; i != bytes.length; i++) {
            bytes[i] = (byte) chars[i];
        }

        return bytes;
    }

    public static byte[] toByteArray(String string) {
        byte[] bytes = new byte[string.length()];

        for (int i = 0; i != bytes.length; i++) {
            char ch = string.charAt(i);

            bytes[i] = (byte) ch;
        }

        return bytes;
    }

    /**
     * Convert an array of 8 bit characters into a string.
     *
     * @param bytes 8 bit characters.
     * @return resulting String.
     */
    public static String fromByteArray(byte[] bytes) {
        return new String(asCharArray(bytes));
    }

    /**
     * Do a simple conversion of an array of 8 bit characters into a string.
     *
     * @param bytes 8 bit characters.
     * @return resulting String.
     */
    public static char[] asCharArray(byte[] bytes) {
        char[] chars = new char[bytes.length];

        for (int i = 0; i != chars.length; i++) {
            chars[i] = (char) (bytes[i] & 0xff);
        }

        return chars;
    }

    public static String[] split(String input, char delimiter) {
        List<String> v = new ArrayList<>();
        boolean moreTokens = true;
        String subString;

        while (moreTokens) {
            int tokenLocation = input.indexOf(delimiter);
            if (tokenLocation > 0) {
                subString = input.substring(0, tokenLocation);
                v.add(subString);
                input = input.substring(tokenLocation + 1);
            } else {
                moreTokens = false;
                v.add(input);
            }
        }

        return v.toArray(new String[v.size()]);
    }

    private void validatePaddingBytes(int paddingBytes) throws IOException {
        if (paddingBytes < 0 || paddingBytes > 3) {
            throw new IOException("Bad padding number: " + paddingBytes + ", should be in [0, 3]");
        }
    }
}
