/*
 * 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;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;

import org.eclipse.persistence.internal.eis.cobol.helper.Helper;

/**
*   <p>
*   <b>Purpose</b>:  This class is a parser for Cobol Copy books. It will take a stream as
*   an argument in its constructor and parse the stream when <code>parse()</code> is called.
*   The <code>parse()</code> method returns a <code>Vector</code> of <code>RecordMetaData</code>
*   one for each "01" level record description in the stream.
*/
public class CopyBookParser {

    /** the maximum nested levels allowed, or in other words, the highest level number allowed */
    private static final int maximumNestingLevels = 50;

    /** the line the parser is currently on */
    private String currentLine;

    /** the current line number */
    private int currentLineNumber;

    /**
    * Default constructor
    */
    public CopyBookParser() {
        currentLine = null;
        currentLineNumber = 0;
    }

    /**
    * This method is the primary public api for this class, it takes an <code>InputStream</code>
    * as an argument then parses this stream looking for "01" level record entries.  It returns
    * a <code>Vector</code> containing <code>RecordMetaData</code> for each "01" record defintion
    * encountered in the stream.
     */
    public Vector<RecordMetaData> parse(InputStream stream) throws Exception {
        Vector<RecordMetaData> records;
        currentLineNumber = 0;
        //read file and prepare for parsing
        try {
            //FileInputStream fileInput = new FileInputStream(myParseFile);
            byte[] bytes = new byte[stream.available()];
            stream.read(bytes);
            String copyBookString = new String(bytes);

            //parse through string and determine hierarchy and field sizes
            records = buildStructure(copyBookString);

            //calculate the field offsets from the records
            for (int i = 0; i < records.size(); i++) {
                setOffsetsForComposite(records.elementAt(i), 0);
            }
        } catch (IOException exception) {
            throw CopyBookParseException.ioException(exception);
        }
        return records;
    }

    /**
    * This is a private method that handles the actual parsing of the string tokens, it scans
    * each line looking for a "01" level record definition, when it is encountered, it builds the
    * hierarchical structure for the <code>RecordMetaData</code>
    */
    private Vector<RecordMetaData> buildStructure(String fileString) throws Exception {
        Vector<RecordMetaData> records = new Vector<>();
        StringTokenizer lineTokenizer = new StringTokenizer(fileString, System.getProperty("line.separator"), false);
        RecordMetaData record = new RecordMetaData();
        Vector<String> recordLines = new Vector<>();
        Vector<Integer> lineNums = new Vector<>();

        //first pass removes all non-record data and brings all lines together
        while (lineTokenizer.hasMoreTokens() && !"procedure division.".equalsIgnoreCase(currentLine)) {
            currentLine = lineTokenizer.nextToken();
            currentLineNumber++;
            if (!currentLine.trim().startsWith("*") && (currentLine.trim().length() > 0)) {
                StringTokenizer lineTokens = new StringTokenizer(currentLine);
                String firstToken = lineTokens.nextToken();
                if (firstToken.endsWith(".")) {
                    firstToken = firstToken.substring(0, currentLine.lastIndexOf('.'));
                }
                Integer levelNumber = Helper.integerFromString(firstToken);
                if ((levelNumber != null) && (levelNumber < 50)) {
                    //assure we've gotten entire line
                    while (!currentLine.trim().endsWith(".")) {
                        currentLine += lineTokenizer.nextToken();
                        currentLineNumber++;
                    }
                    currentLine = currentLine.substring(0, currentLine.lastIndexOf('.'));
                    recordLines.addElement(currentLine);
                    lineNums.addElement(currentLineNumber);
                }
            }
        }

        //second pass will build the structure
        int nestingLevel = maximumNestingLevels;
        Stack<CompositeObject> parents = new Stack<>();
        Hashtable<Object, Integer> parentsToLevels = new Hashtable<>();
        Enumeration<String> recordsEnum = recordLines.elements();
        Enumeration<Integer> recordLineNums = lineNums.elements();
        while (recordsEnum.hasMoreElements()) {
            currentLine = recordsEnum.nextElement();
            currentLineNumber = recordLineNums.nextElement();
            StringTokenizer lineTokens = new StringTokenizer(currentLine);
            if (lineTokens.hasMoreTokens()) {
                String firstToken = lineTokens.nextToken();
                Integer levelNumber = Helper.integerFromString(firstToken);
                Object component;

                //process record
                if (levelNumber == 1) {
                    nestingLevel = maximumNestingLevels;
                    parents = new Stack<>();
                    parentsToLevels = new Hashtable<>();
                    component = buildRecord(lineTokens);
                    record = (RecordMetaData)component;
                    records.addElement(record);
                }
                //process subordinate field
                else if (levelNumber >= nestingLevel) {
                    component = buildField(lineTokens);
                    parents.peek().addField((FieldMetaData)component);
                }
                //field is no longer subordinate skip back to original level
                else {
                    while (parentsToLevels.get(parents.peek()) >= levelNumber) {
                        parents.pop();
                    }
                    component = buildField(lineTokens);
                    parents.peek().addField((FieldMetaData)component);
                }
                nestingLevel = levelNumber;
                if (component instanceof FieldMetaData) {
                    ((FieldMetaData)component).setRecord(record);
                }
                if (component instanceof CompositeObject) {
                    parents.push((CompositeObject) component);
                    parentsToLevels.put(component, levelNumber);
                }
            }
        }
        return records;
    }

    /**
    * This method cascades down through the records built in the <code>buildStructure</code>
    * method setting the  offsets for the fields, this must be done now, because the sizes
    * for the fields must allready be determined.
    */
    private void setOffsetsForComposite(CompositeObject object, int offset) {
        int currentOffset = offset;
        int previousFieldSize = 0;
        Vector<FieldMetaData> fields = object.getFields();
        Enumeration<FieldMetaData> fieldEnum = fields.elements();
        FieldMetaData previousField = null;

        //loop through fields setting their offsets and redefines if it applies
        while (fieldEnum.hasMoreElements()) {
            FieldMetaData field = fieldEnum.nextElement();

            //if its a redefine, must first see if it larger and reset offset accordingly
            if (field.isFieldRedefine()) {
                field.setFieldRedefined(previousField);
                if (field instanceof CompositeObject) {
                    setOffsetsForComposite((CompositeObject)field, previousField.getOffset());
                }
                field.setOffset(previousField.getOffset());
                if (previousFieldSize < field.getSize()) {
                    currentOffset += (field.getSize() - previousFieldSize);
                    previousFieldSize = field.getSize();
                }
            } else {
                if (field instanceof CompositeObject) {
                    setOffsetsForComposite((CompositeObject)field, currentOffset);
                }
                field.setOffset(currentOffset);
                currentOffset += field.getSize();
                previousField = field;
                previousFieldSize = field.getSize();
            }
        }
    }

    /**
    * This method processes "01" level lines building a <code>RecordMetaData</code> and
    * returning it.
    */
    private RecordMetaData buildRecord(StringTokenizer lineTokens) {
        RecordMetaData record;
        if (lineTokens.hasMoreTokens()) {
            String recordName = lineTokens.nextToken();
            record = new RecordMetaData(recordName);
            return record;
        } else {
            throw invalidCopyBookException("The record has no name.");
        }
    }

    /**
    * This method handles all "02" through "49" level lines building  a field from the line.
    * it returns <code>FieldMetaData</code> for either composite or elementary fields
    * appropriately.
    */
    private FieldMetaData buildField(StringTokenizer lineTokens) throws Exception {
        FieldMetaData field;
        String fieldName;
        boolean redefine = false;
        int arraySize = -1;
        String[] tokens = new String[lineTokens.countTokens()];
        int index = 0;
        String dependentField = "";

        //build token array first so that backtracking can be done if necessary
        while (lineTokens.hasMoreTokens()) {
            tokens[index++] = lineTokens.nextToken();
        }
        index = 0;
        if (tokens.length > 0) {
            if (isKeyWord(tokens[index])) {
                fieldName = "filler";
            } else {
                fieldName = tokens[index];
            }
        }
        //composite without name
        else {
            field = new CompositeFieldMetaData();
            field.setName("filler");
            return field;
        }

        //find the pic statement
        for (int i = 0;
                 (i < tokens.length) && !tokens[index].equalsIgnoreCase("pic") && !tokens[index].equalsIgnoreCase("picture");
                 i++) {
            if (tokens[index].equalsIgnoreCase("redefines")) {
                redefine = true;
            }
            if (tokens[index].equalsIgnoreCase("occurs")) {
                arraySize = handleOccursStatement(tokens, ++index);
                index--;
            }
            if (tokens[index].equalsIgnoreCase("depending")) {
                dependentField = handleDependeningStatement(tokens, ++index);
                index--;
            }
            index++;

        }

        //elementary field
        if ((index < tokens.length) && (tokens[index].equalsIgnoreCase("pic") || tokens[index].equalsIgnoreCase("picture"))) {
            field = buildElementaryField(fieldName, tokens, index);
        }
        //composite field
        else {
            field = new CompositeFieldMetaData();
            field.setName(fieldName);
        }
        field.setIsFieldRedefine(redefine);
        field.setArraySize(arraySize);
        field.setDependentFieldName(dependentField);
        return field;
    }

    /**
    * This method handles the "depending" statement returning the name of the field that
    * this field depends on.
    */
    private String handleDependeningStatement(String[] tokens, int index) {
        String fieldName = null;
        try {
            if (index < tokens.length) {
                fieldName = tokens[index];
                if (fieldName.equalsIgnoreCase("on")) {
                    fieldName = tokens[++index];
                }
            }

            //there was no name following the depending clause or on clause
        } catch (ArrayIndexOutOfBoundsException exception) {
            throw invalidCopyBookException("There was no field name following the depending clause.", exception);
        }
        return fieldName;
    }

    /**
    * This method handles the "occurs" statment, returning the maximum number of times this field
    * should occur.
    */
    private int handleOccursStatement(String[] tokens, int index) throws Exception {
        try {
            int size = 0;
            if (index < tokens.length) {
                size = Helper.integerFromString(tokens[index]);
                if (tokens[++index].equalsIgnoreCase("to")) {
                    int newSize = Helper.integerFromString(tokens[++index]);
                    if (size > 0) {
                        newSize = newSize - size;
                    }
                    size = newSize;
                }
            }
            if (size < 1) {
                throw invalidCopyBookException("Must occur at least once.");
            }
            return size;
            //there was no integer following the occurs statment or one after the to statement
        } catch (ArrayIndexOutOfBoundsException exception) {
            throw invalidCopyBookException("Occurs clause must be folowed by and integer.", exception);
        }
    }

    /**
    * This method build elementary fields getting the pertinent size
    * information from the pic statement
    */
    private FieldMetaData buildElementaryField(String fieldName, String[] tokens, int index) throws Exception {
        FieldMetaData field = new ElementaryFieldMetaData();
        String picStatment;
        int size = 0;
        try {
            field.setName(fieldName);
            picStatment = tokens[++index];

            if (picStatment.equalsIgnoreCase("is")) {
                picStatment = tokens[++index];
            }

            //either the pic statement didn't follow the pic clause or didn't follow the is clause
        } catch (ArrayIndexOutOfBoundsException exception) {
            throw invalidCopyBookException("Picture clause must be followed by a pic statement.", exception);
        }

        //set type and calculate size
        if (picStatment.toUpperCase().startsWith("A")) {
            field.setType(FieldMetaData.ALPHABETIC);
            size = calculateSizeOfAlphaNumeric(picStatment, field);
        } else if (picStatment.toUpperCase().startsWith("X")) {
            field.setType(FieldMetaData.ALPHA_NUMERIC);
            size = calculateSizeOfAlphaNumeric(picStatment, field);
        } else if (picStatment.toUpperCase().startsWith("9") || picStatment.toUpperCase().startsWith("V") || picStatment.toUpperCase().startsWith("Z") || picStatment.startsWith("+") || picStatment.startsWith("-") || picStatment.toUpperCase().startsWith("S")) {
            field.setType(FieldMetaData.NUMERIC);
            size = calculateSizeOfNumeric(picStatment, tokens, index, field);
        }

        field.setSize(size);
        return field;

    }

    /**
    * This method calculates the size of alphanumeric pic statments that begin with "A" or "X"
    */
    private int calculateSizeOfAlphaNumeric(String picStatement, FieldMetaData field) throws Exception {
        //parse through statement and determine size
        char[] picChars = picStatement.toCharArray();
        int length = picChars.length;
        int index = 0;
        int size = 0;

        while (index < length) {
            char currentChar = picChars[index];
            switch (currentChar) {
            case '(':
                StringBuilder number = new StringBuilder();
                index++;
                size--;
                currentChar = picChars[index];
                while ((index < length) && (currentChar != ')')) {
                    number.append(currentChar);
                    index++;
                    currentChar = picChars[index];
                }
                try {
                    int value = Integer.parseInt(number.toString());
                    size += value;
                } catch (NumberFormatException exception) {
                    throw invalidCopyBookException("In pic statement a valid integer must be enclosed by the parenthesis.", exception);
                }
                if (currentChar == ')') {
                    index++;
                } else {
                    throw invalidCopyBookException("An open parenthesis must be followed by a close parenthesis.");
                }
                break;
            case 'p':
            case 'P':
            case 'Z':
            case 'z':
            case '+':
            case '-':
            case 'x':
            case 'X':
            case 'a':
            case 'A':
            case '9':
                size++;
                index++;
                break;
            case 'V':
            case 'v':
                field.setDecimalPosition(size);
                index++;
                break;
            case 'S':
            case 's':
                index++;
                break;
            case '.':
                if (index == (length - 1)) {
                    return size;
                } else {
                    index++;
                }
                size++;
                break;
            default:
                throw invalidCopyBookException("Invalid character: " + currentChar + " in pic statement.");
            }
        }
        return size;
    }

    /**
    * This method calculates the size of numeric fields in which the pic statement begins with "9"
    */
    private int calculateSizeOfNumeric(String picStatement, String[] tokens, int index, FieldMetaData field) throws Exception {
        int size = 0;
        int digits = 0;

        if (picStatement.toUpperCase().startsWith("S")) {
            field.setIsSigned(true);
        }

        for (int i = index; i < tokens.length; i++, index++) {
            String nextStatement = tokens[i];

            //determine if there is usage other than display default
            if (nextStatement.equalsIgnoreCase("comp") || nextStatement.equalsIgnoreCase("computational")) {
                digits = calculateSizeOfAlphaNumeric(picStatement, field);
                field.setType(FieldMetaData.BINARY);
                if (digits < 3) {
                    size = 1;
                } else if (digits < 5) {
                    size = 2;
                } else if (digits < 8) {
                    size = 3;
                } else if (digits < 10) {
                    size = 4;
                } else if (digits < 13) {
                    size = 5;
                } else if (digits < 15) {
                    size = 6;
                } else if (digits < 17) {
                    size = 7;
                } else if (digits < 20) {
                    size = 8;
                }
                if (field.isSigned() && ((digits == 7) || (digits == 12) || (digits == 19))) {
                    size++;
                }
            } else if (nextStatement.equalsIgnoreCase("comp-2") || nextStatement.equalsIgnoreCase("computational-2")) {
                //size of float, should not be encountered
                field.setType(FieldMetaData.MANTISSA);
                return 4;
            } else if (nextStatement.equalsIgnoreCase("comp-3") || nextStatement.equalsIgnoreCase("computational-3") || nextStatement.equalsIgnoreCase("packed-decimal")) {
                int tempSize = calculateSizeOfAlphaNumeric(picStatement, field);
                field.setType(FieldMetaData.PACKED_DECIMAL);
                size = (tempSize + 1) / 2;
                if (((tempSize + 1) % 2) > 0) {
                    size++;
                }
            } else if (nextStatement.equalsIgnoreCase("seperate")) {
                size = calculateSizeOfAlphaNumeric(picStatement, field);
                size++;
            } else {
                field.setType(FieldMetaData.ALPHA_NUMERIC);
                size = calculateSizeOfAlphaNumeric(picStatement, field);
            }
        }
        return size;
    }

    /**
    * This method returns true if the string word equals one of a list of keywords.
    */
    private boolean isKeyWord(String word) {
        String[] keyWords = { "pic", "picture", "redefines", "blank", "external", "global", "justified", "just", "occurs" };

        for (int i = 0; i < keyWords.length; i++) {
            if (word.equalsIgnoreCase(keyWords[i])) {
                return true;
            }
        }
        return false;
    }

    /**
    * This method will create a invalid copybook exception and add the line number and line
    * at which the exception occurred
    */
    private CopyBookParseException invalidCopyBookException(String message) {
        return CopyBookParseException.invalidCopyBookException(message + " Error occrured on line " + currentLineNumber + ":" + currentLine);
    }

    /**
    * This method adds the internal exception if it is provided
    */
    private CopyBookParseException invalidCopyBookException(String message, Exception internalException) {
        CopyBookParseException exception = invalidCopyBookException(message);
        exception.setInternalException(internalException);
        return exception;
    }
}
