/*
 * 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 parse(InputStream stream) throws Exception {
        Vector 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((CompositeObject)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 buildStructure(String fileString) throws Exception {
        Vector records = new Vector();
        StringTokenizer lineTokenizer = new StringTokenizer(fileString, System.getProperty("line.separator"), false);
        RecordMetaData record = new RecordMetaData();
        Vector recordLines = new Vector();
        Vector 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 parents = new Stack();
        Hashtable parentsToLevels = new Hashtable();
        Enumeration recordsEnum = recordLines.elements();
        Enumeration recordLineNums = lineNums.elements();
        while (recordsEnum.hasMoreElements()) {
            currentLine = (String)recordsEnum.nextElement();
            currentLineNumber = (Integer) 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(component);
                }
                //process subordinate field
                else if (levelNumber >= nestingLevel) {
                    component = buildField(lineTokens);
                    ((CompositeObject)parents.peek()).addField((FieldMetaData)component);
                }
                //field is no longer subordinate skip back to original level
                else {
                    while ((Integer) parentsToLevels.get(parents.peek()) >= levelNumber) {
                        parents.pop();
                    }
                    component = buildField(lineTokens);
                    ((CompositeObject)parents.peek()).addField((FieldMetaData)component);
                }
                nestingLevel = levelNumber;
                if (component instanceof FieldMetaData) {
                    ((FieldMetaData)component).setRecord(record);
                }
                if (component instanceof CompositeObject) {
                    parents.push(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 fields = object.getFields();
        Enumeration fieldEnum = fields.elements();
        FieldMetaData previousField = null;

        //loop through fields setting their offsets and redefines if it applies
        while (fieldEnum.hasMoreElements()) {
            FieldMetaData field = (FieldMetaData)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) throws Exception {
        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) throws Exception {
        String fieldName = null;
        try {
            fieldName = tokens[index];
            if (index < tokens.length) {
                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 {
            Integer size = Helper.integerFromString(tokens[index]);
            if (index < tokens.length) {
                if (tokens[++index].equalsIgnoreCase("to")) {
                    Integer 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 {
                    Integer value = Integer.valueOf(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;
    }
}
