/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.eis.cobol.helper;

import java.io.StringWriter;

import org.eclipse.persistence.internal.eis.cobol.ByteArrayException;
import org.eclipse.persistence.internal.eis.cobol.FieldMetaData;

/**
* <b>Purpose</b>: This class handles all the byte &lt;-&gt; string conversions. It handles
* ascii/binary/packed-decimal conversions.  This class is used by and dependent on <code>
* FieldMetaData</code>
*/
public class ByteConverter {

    /** This is the byte array that represents the byte data for the entire record */
    private byte[] myRecordData;

    /** This is the field that this particular <code>ByteConverter</code> is associatedd */
    FieldMetaData myFieldMetaData;

    /** This is the word size for the system, api is provided to change this if necessary */
    public static int wordSize = 2;

    /** This represents whether the system is little endian or not, api is provided to change
    * this if necessary. */
    private boolean isLittleEndian;

    /**
    * Default constructor
    */
    public ByteConverter() {
        initialize();
    }

    /**
    * constructor that accepts FieldMetaData and record data, this is the preferred constructor
    */
    public ByteConverter(FieldMetaData metaData, byte[] recordData) {
        initialize(metaData, recordData);
    }

    /**
    * no-argument initializer
    */
    protected void initialize() {
        isLittleEndian = false;
    }

    /**
    * accepts FieldMetaData and record data.
    */
    protected void initialize(FieldMetaData metaData, byte[] recordData) {
        myFieldMetaData = metaData;
        myRecordData = recordData;
        isLittleEndian = false;
    }

    /**
    * method returns littleEndian attribute
    */
    public boolean isLittleEndian() {
        return isLittleEndian;
    }

    /**
    * method sets littleEndian attribute
    */
    public void setIsLittleEndian(boolean newValue) {
        isLittleEndian = newValue;
    }

    /**
    * method returns wordSize attribute
    */
    public int getWordSize() {
        return wordSize;
    }

    /**
    * method sets wordSize attribute
    */
    public void setWordSize(int newWordSize) {
        wordSize = newWordSize;
    }

    /**
    * This method checks the field to see if it should have a decimal point added and inserts it
    * if needed.
    */
    protected String insertDecimalInString(String string) {
        if (getFieldMetaData().hasDecimal()) {
            int decimalPosition = this.getFieldMetaData().getDecimalPosition();
            if (decimalPosition < string.length()) {
                StringWriter writer = new StringWriter();
                writer.write(string.substring(0, decimalPosition - 1));
                writer.write(".");
                writer.write(string.substring(decimalPosition - 1));
                return writer.toString();
            }
        }
        return string;
    }

    /**
    * This method removes the decimal if needed
    */
    protected String removeDecimalInString(String string) {
        if (getFieldMetaData().hasDecimal()) {
            int decimalPosition = this.getFieldMetaData().getDecimalPosition();
            if (decimalPosition < string.length()) {
                StringWriter writer = new StringWriter();
                writer.write(string.substring(0, decimalPosition - 1));
                writer.write(string.substring(decimalPosition));
                return writer.toString();
            }
        }
        return string;
    }

    /**
    * This method is the primary public access for the byte converter to extract a string value
    * associated with a field, from a byte array associated with a record.
    */
    public String getStringValue() {
        int offset = this.getFieldMetaData().getOffset();
        String stringValue = null;
        if ((this.getFieldMetaData().getType() != FieldMetaData.BINARY) && (this.getFieldMetaData().getType() != FieldMetaData.MANTISSA) && (this.getFieldMetaData().getType() != FieldMetaData.PACKED_DECIMAL)) {
            int length = 0;
            while (length < this.getFieldMetaData().getSize()) {
                if (this.getRecordData()[offset + length] == 0) {
                    break;
                }
                length++;
            }
            stringValue = new String(this.getRecordData(), offset, length);
        } else if (this.getFieldMetaData().getType() == FieldMetaData.BINARY) {
            if (isLittleEndian()) {
                this.swapEndians(offset, this.getFieldMetaData().getSize());
            }
            stringValue = getStringFromBinaryData(offset, this.getFieldMetaData().getSize());
        } else if (this.getFieldMetaData().getType() == FieldMetaData.PACKED_DECIMAL) {
            stringValue = this.getStringValueFromPackedDecimal();
          //todo: else handle other types of data
        }
        return insertDecimalInString(stringValue);
    }

    /**
    * This is the primary public access for writing string values associated with a field to a
    * byte array associated with a record.
    */
    public void setBytesToValue(String value) {
        value = removeDecimalInString(value);
        if ((this.getFieldMetaData().getType() != FieldMetaData.BINARY) && (this.getFieldMetaData().getType() != FieldMetaData.MANTISSA) && (this.getFieldMetaData().getType() != FieldMetaData.PACKED_DECIMAL)) {
            byte[] byteValue = value.getBytes();
            int length = byteValue.length;

            //assure length is within boundaries of the field
            if (length > this.getFieldMetaData().getSize()) {
                length = this.getFieldMetaData().getSize();
            }
            int i;
            int j;
            for (i = 0, j = this.getFieldMetaData().getOffset(); i < length; i++, j++) {
                this.getRecordData()[j] = byteValue[i];
            }

            //terminate the string
            if (length < this.getFieldMetaData().getSize()) {
                this.getRecordData()[j] = 0;
            }
        } else if (this.getFieldMetaData().getType() == FieldMetaData.BINARY) {
            this.setBinaryDataToStringValue(value, this.getFieldMetaData().getOffset(), this.getFieldMetaData().getSize());
        } else if (this.getFieldMetaData().getType() == FieldMetaData.PACKED_DECIMAL) {
            this.setByteArrayToPackedDecimalValue(value);
          //todo: else handle other types of data
        }
    }

    /**
    * getter for <code>FieldMetaData</code>
    */
    public FieldMetaData getFieldMetaData() {
        return myFieldMetaData;
    }

    /**
    * setter for <code>FieldMetaData</code>
    */
    public void setFieldMetaData(FieldMetaData newFieldMetaData) {
        myFieldMetaData = newFieldMetaData;
    }

    /**
    * getter for record data
    */
    public byte[] getRecordData() {
        return myRecordData;
    }

    /**
    * setter for record data
    */
    public void setRecordData(byte[] newRecordData) {
        myRecordData = newRecordData;
    }

    /**
    * this method builds a string value from a byte array containing packed-decimal data
    */
    protected String getStringValueFromPackedDecimal() {
        int mask = 0xf0;
        boolean signed = this.getFieldMetaData().isSigned();
        String sign = "";
        int offset = this.getFieldMetaData().getOffset();
        int size = this.getFieldMetaData().getSize();
        StringBuilder value = new StringBuilder();
        int position = 0;

        // Determine the sign if there is one
        if (signed) {
            byte signBits = (byte)(myRecordData[(offset + size) - 1] | mask);
            if (signBits == 0x0d) {
                sign = String.valueOf('-');
            } else if (signBits == 0x0c) {
                sign = String.valueOf('+');
            }
        }

        String stringValue;

        // Build hex string
        for (int i = offset; i < (offset + size); i++) {
            stringValue = Integer.toHexString(Helper.intFromByte(myRecordData[i]));
            // Added to handle strange behavior of toHexString method with negative numbers
            if (stringValue.length() > 2) {
                stringValue = stringValue.substring(stringValue.length() - 2);
            }
            value.append(stringValue);
        }

        // Count leading zeros
        while (value.charAt(position) == '0') {
            position++;
        }
        // Prepend sign and remove leading zeros
        if (signed) {
            value.replace(0, position, sign);
        } else {
            value.delete(0, position);
        }
        return value.toString();
    }

    /**
    * this method sets byte array data to a packed-decimal value held in the value argument
    */
    protected void setByteArrayToPackedDecimalValue(String value) {
        int size = this.getFieldMetaData().getSize();
        int offset = this.getFieldMetaData().getOffset();
        boolean signed = this.getFieldMetaData().isSigned();

        //determine the sign if there is one add it
        if (signed) {
            if (value.startsWith("-")) {
                value += "d";
            } else {
                value += "c";
            }
            value = value.substring(1);
        }
        //add F if unsigned
        else {
            value += "f";
        }

        //add leading zeros
        StringBuilder sb = new StringBuilder(value);
        while (sb.length() < (size * 2)) {
            sb.insert(0, "0");
        }
        value = sb.toString();

        //write one byte at a time to array
        for (int i = offset, j = 0; i < (offset + size); i++, j += 2) {
            myRecordData[i] = Helper.byteFromInt(Helper.intFromHexString(value.substring(j, j + 2)));
        }
    }

    /**
    * this method will swap the ends of a byte in a byte array starting at <code>offset</code>
    * and ending at <code>end</code>
    */
    protected void swapEndians(int offset, int end) {
        if ((wordSize > 0) && ((wordSize % 2) == 0)) {
            int length = end - offset;
            int stop = end;

            //assure length is divisible by wordSize
            if ((length % wordSize) != 0) {
                int remainder = length % wordSize;
                stop = end - remainder;
            }
            int halfWord = wordSize / 2;
            byte highByte;
            byte lowByte;
            for (int i = offset; i < stop; i += wordSize) {
                for (int j = 0; j < halfWord; j++) {
                    highByte = myRecordData[i + j];
                    lowByte = myRecordData[i + j + halfWord];
                    myRecordData[i + j] = lowByte;
                    myRecordData[i + j + halfWord] = highByte;
                }
            }
        } else {
            throw ByteArrayException.unrecognizedDataType();
        }
    }

    /**
    * this method performs a bitwise twos complement on a section of a byte array starting at
    * <code>offset</code> and ending at <code>offset + length</code>
    */
    protected void twosComplement(int offset, int length) {
        int i;

        //perform a twos complement on the bytes in record data
        for (i = offset; i < (offset + length); i++) {
            myRecordData[i] = Helper.byteFromInt(~(Helper.intFromByte(myRecordData[i])));
        }
        i--;
        //add one to value
        while ((i >= offset) && (Helper.intFromByte(myRecordData[i]) == -1)) {
            myRecordData[i]++;
            i--;
        }
        if (i >= offset) {
            myRecordData[i]++;
        }
    }

    /**
    * This method builds a string value from a byte array section containing binary data
    */
    protected String getStringFromBinaryData(int offset, int size) {
        boolean signed = this.getFieldMetaData().isSigned();
        String sign = null;
        int total = 0;

        //check if it is signed and determine sign
        if (signed) {
            int mask = 0xff;
            byte highestByte = myRecordData[offset];
            if (((highestByte >> 3) & mask) == 0xff) {
                sign = "-";
                twosComplement(offset, size);
            } else {
                sign = "+";
            }
        }

        //loop through bytes accumulating total
        for (int i = (offset + size) - 1, j = 0; i >= offset; i--, j++) {
            if (Helper.intFromByte(myRecordData[i]) < 0) {
                myRecordData[i] &= 0x7f;
                total += Helper.power(2, ((j + 1) * 8) - 1);
            }
            total += (Helper.intFromByte(myRecordData[i]) * Helper.power(2, j * 8));
        }
        if (signed) {
            return sign + total;
        } else {
            return String.valueOf(total);
        }
    }

    /**
    * this method sets a section of byte array to the value represented by the string <code> value
    * </code> using a binary representation.
    */
    protected void setBinaryDataToStringValue(String value, int offset, int size) {
        boolean isNegative = false;

        //remove +/-
        if (value.startsWith("-")) {
            isNegative = true;
            value = value.substring(1);
        } else if (value.startsWith("+")) {
            value = value.substring(1);
        }
        int total = Integer.parseInt(value);

        //loop through total dividing down
        for (int i = offset, j = size - 1; i < (size + offset); i++, j--) {
            myRecordData[i] = Helper.byteFromInt(total / Helper.power(2, j * 8));
            total %= Helper.power(2, j * 8);
        }
        if (isNegative) {
            twosComplement(offset, size);
        }
    }
}
