/*
 * 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.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.persistence.internal.helper.DatabaseField;

/**
* <b>Purpose</b>: This class represents metadata for composite fields.  It exetends
* <code>ElementaryFieldMetaData</code> and adds teh attribute <code>myCompositeFields</code>
* which is a collection of subordinate fields.
*/
public class CompositeFieldMetaData extends ElementaryFieldMetaData implements CompositeObject {

    /** collection containing this fields subordinate fields */
    protected Vector<FieldMetaData> myCompositeFields;

    public CompositeFieldMetaData() {
        super.initialize();
        initialize();
    }

    public CompositeFieldMetaData(String fieldName, String recordName) {
        super.initialize(fieldName, recordName);
        initialize();
    }

    public CompositeFieldMetaData(String fieldName, RecordMetaData record) {
        super.initialize(fieldName, record);
        initialize();
    }

    public CompositeFieldMetaData(String fieldName, RecordMetaData record, Vector<FieldMetaData> fields) {
        super.initialize(fieldName, record);
        initialize(fields);
    }

    @Override
    protected void initialize() {
        myCompositeFields = new Vector<>();
    }

    protected void initialize(Vector<FieldMetaData> fields) {
        myCompositeFields = fields;
    }

    /**
    * performs a deep copy of all subordiate fields in the <code>myCompositeFields</code> attribute
    */
    @Override
    public FieldMetaData deepCopy() {
        CompositeFieldMetaData fieldCopy = new CompositeFieldMetaData(myName, myRecord.getName());
        fieldCopy.setIsFieldRedefine(isRedefine);
        fieldCopy.setDecimalPosition(decimalPosition);
        fieldCopy.setArraySize(myArraySize);
        fieldCopy.setSize(mySize);
        fieldCopy.setOffset(myOffset);
        fieldCopy.setType(myType);
        if (isFieldRedefine()) {
            fieldCopy.setFieldRedefined(myFieldRedefined.deepCopy());
        }
        fieldCopy.setDependentFieldName(myDependentFieldName);
        Enumeration<FieldMetaData> fieldsEnum = myCompositeFields.elements();
        while (fieldsEnum.hasMoreElements()) {
            FieldMetaData field = fieldsEnum.nextElement();
            fieldCopy.addField(field.deepCopy());
        }
        return fieldCopy;
    }

    /**
    * overides <code>ElementaryFieldMetaData</code> to calculate the fields size from all the sizes
    * of its subordinate fields.
    */
    @Override
    public int getSize() {
        Enumeration<FieldMetaData> fieldsEnum = myCompositeFields.elements();
        int size = 0;
        while (fieldsEnum.hasMoreElements()) {
            FieldMetaData field = fieldsEnum.nextElement();
            if (!field.isFieldRedefine()) {
                size += field.getSize();
            }
        }

        /*if(isArray())
            return size * myArraySize;
        else*/
        return size;
    }

    /**
    * we don't want to set the size for a composite field because its size is determined from its
    * subordinate fields.
    */
    @Override
    public void setSize(int size) {
        //do nothing
    }

    /**
    * a composite field can't have a decimal position
    */
    @Override
    public boolean hasDecimal() {
        return false;
    }

    /**
    * a composite field can't have a decimal position
    */
    @Override
    public int getDecimalPosition() {
        return -1;
    }

    /**
    * a composite field can't have a decimal position
    */
    public void setDecimalPosition() {
        //do nothing
    }

    /**
    * a composite field is by definition going to be composite
    */
    @Override
    public boolean isComposite() {
        return true;
    }

    /**
    * a composite field is by definition going to be composite
    */
    @Override
    public int getType() {
        return FieldMetaData.COMPOSITE;
    }

    /**
    * a composite field is by definition going to be composite, so this cannot be changed
    */
    @Override
    public void setType(int type) {
        //do nothing
    }

    /**
    * returns a collection of subordinate fields
    */
    @Override
    public Vector<FieldMetaData> getFields() {
        return myCompositeFields;
    }

    /**
    * sets the composite field attribute to the new collection
    */
    @Override
    public void setFields(Vector<FieldMetaData> newCompositeFields) {
        myCompositeFields = newCompositeFields;
    }

    /**
    * adds a field to the collection
    */
    @Override
    public void addField(FieldMetaData newField) {
        myCompositeFields.addElement(newField);
    }

    /**
    * returns the first subordinate field with a name matching the string in <code>fieldName</code>
    */
    @Override
    public FieldMetaData getFieldNamed(String fieldName) {
        Enumeration<FieldMetaData> fieldsEnum = getFields().elements();
        while (fieldsEnum.hasMoreElements()) {
            FieldMetaData field = fieldsEnum.nextElement();
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }
        return null;
    }

    /**
    * loops through the subordinate fields extracting the value from each.
    */
    @Override
    public Object extractValueFromArray(byte[] recordData) {
        List<CobolRow> fieldValue = new ArrayList<>(getFields().size());
        if (this.isArray()) {
            int offset = this.getOffset();
            for (int i = this.getArraySize(); i > 0; i--) {
                //must change offset to read the appropriate section of the byte array
                CompositeFieldMetaData fieldCopy = (CompositeFieldMetaData)this.deepCopy();
                fieldCopy.setOffset(offset);
                fieldCopy.resetChildOffsets();
                CobolRow compositeRow = new CobolRow();
                fieldCopy.writeCompositeOnRow(compositeRow, recordData);
                fieldValue.add(compositeRow);
                offset += this.getSize();
            }
        } else {
            CobolRow compositeRow = new CobolRow();
            writeCompositeOnRow(compositeRow, recordData);
            fieldValue.add(compositeRow);
        }
        return fieldValue;
    }

    /**
    * writes individual fields on given row
    */
    public void writeCompositeOnRow(CobolRow row, byte[] recordData) {
        Enumeration<FieldMetaData> fields = getFields().elements();
        while (fields.hasMoreElements()) {
            FieldMetaData currentField = fields.nextElement();
            currentField.writeOnRow(row, recordData);
        }
    }

    /**
    * extracts the value from the record data for the field and writes it to the row.
    */
    @Override
    public void writeOnRow(CobolRow row, byte[] recordData) {
        Object value;

        //check for array first adjust size if necessary
        if (this.isArray() && this.dependsOn()) {
            adjustArraySize(row);
        }
        DatabaseField field = new DatabaseField(getName(), getRecord().getName());
        if (this.isFieldRedefine()) {
            value = new CobolRedefinedFieldValue(this, recordData);
        } else {
            value = extractValueFromArray(recordData);
        }
        row.add(field, value);
    }

    /**
    * takes the value from the row for this field and writes it to the byte array
    */
    @Override
    public void writeOnArray(CobolRow row, byte[] recordData) {
        Object obj = row.get(this.getName());
        @SuppressWarnings({"unchecked"})
        List<CobolRow> fieldValue = (List<CobolRow>)obj;
        if (this.isArray()) {
            //check for array first adjust size if necessary
            if (this.dependsOn()) {
                adjustArraySize(row);
            }
            int offset = this.getOffset();
            Iterator<CobolRow> elements = fieldValue.iterator();
            for (int i = this.getArraySize(); i > 0; i--) {
                //must change offset to write to the appropriate section of the byte array
                CompositeFieldMetaData fieldCopy = (CompositeFieldMetaData)this.deepCopy();
                fieldCopy.setOffset(offset);
                fieldCopy.resetChildOffsets();
                CobolRow compositeRow = elements.next();
                fieldCopy.writeCompositeOnArray(compositeRow, recordData);
                offset += this.getSize();
            }
        } else {
            CobolRow compositeRow = fieldValue.get(0);
            this.writeCompositeOnArray(compositeRow, recordData);
        }
    }

    /**
    * This method is used by fields that are array values to write themselves to arrays
    */
    protected void writeCompositeOnArray(CobolRow row, byte[] recordData) {
        Enumeration<FieldMetaData> fields = getFields().elements();
        while (fields.hasMoreElements()) {
            FieldMetaData currentField = fields.nextElement();
            currentField.writeOnArray(row, recordData);
        }
    }

    /**
    * method resets offsets of subordinate fields, should be called when the offset of the parent
    * is changed.
    */
    protected void resetChildOffsets() {
        Enumeration<FieldMetaData> childFieldsEnum = myCompositeFields.elements();
        int offset = this.getOffset();
        while (childFieldsEnum.hasMoreElements()) {
            FieldMetaData field = childFieldsEnum.nextElement();
            field.setOffset(offset);
            if (field.isComposite()) {
                ((CompositeFieldMetaData)field).resetChildOffsets();
            }
            offset += field.getSize();
        }
    }
}
