/*
 * Copyright (c) 1998, 2020 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.sessions;

import java.io.StringWriter;
import java.util.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.internal.helper.DatabaseField;

/**
 * PERF: Optimized record implementation using arrays instead of Vector.
 * Currently only used when fetch rows from the database.
 */
public class ArrayRecord extends DatabaseRecord {
    protected DatabaseField[] fieldsArray;
    protected Object[] valuesArray;

    protected ArrayRecord() {
        super();
    }

    public ArrayRecord(Vector fields, DatabaseField[] fieldsArray, Object[] valuesArray) {
        super(fields, null, fieldsArray.length);
        this.fieldsArray = fieldsArray;
        this.valuesArray = valuesArray;
    }

    /**
     * Reset the fields and values from the arrays.
     * This removes the optimization if a non-optimized method is called.
     */
    protected void checkValues() {
        if (this.values == null) {
            this.values = new NonSynchronizedVector(this.valuesArray.length);
            for (Object value : this.valuesArray) {
                this.values.add(value);
            }
        }
    }

    /**
     * INTERNAL:
     * Add the field-value pair to the row.  Will not check,
     * will simply add to the end of the row
     */
    @Override
    public void add(DatabaseField key, Object value) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        super.add(key, value);
    }

    /**
     * PUBLIC:
     * Clear the contents of the row.
     */
    @Override
    public void clear() {
        this.fieldsArray = null;
        this.valuesArray = null;
        super.clear();
    }

    /**
     * INTERNAL:
     * Clone the row and its values.
     */
    @Override
    public AbstractRecord clone() {
        checkValues();
        return super.clone();
    }

    /**
     * INTERNAL:
     * Check if the field is contained in the row.
     */
    @Override
    public boolean containsKey(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return true;
                }
            }
            for (DatabaseField field : this.fieldsArray) {
                if ((field == key) || field.equals(key)) {
                    return true;
                }
            }
            return false;
        } else {
            return super.containsKey(key);
        }
    }

    /**
     * PUBLIC:
     * Check if the value is contained in the row.
     */
    @Override
    public boolean containsValue(Object value) {
        if (this.valuesArray != null) {
            for (Object rowValue : this.valuesArray) {
                if ((value == rowValue) || rowValue.equals(value)) {
                    return true;
                }
            }
            return false;
        } else {
            return super.containsValue(value);
        }
    }

    /**
     * INTERNAL:
     * Retrieve the value for the field. If missing null is returned.
     */
    @Override
    public Object get(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return this.valuesArray[index];
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    // PERF: If the fields index was not set, then set it.
                    if (index == -1) {
                        key.setIndex(fieldIndex);
                    }
                    return this.valuesArray[fieldIndex];
                }
            }
            return null;
        } else {
            return super.get(key);
        }
    }

    /**
     * INTERNAL:
     * Retrieve the value for the field. If missing DatabaseRow.noEntry is returned.
     */
    @Override
    public Object getIndicatingNoEntry(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return this.valuesArray[index];
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    // PERF: If the fields index was not set, then set it.
                    if (index == -1) {
                        key.setIndex(fieldIndex);
                    }
                    return this.valuesArray[fieldIndex];
                }
            }
            return AbstractRecord.noEntry;
        } else {
            return super.get(key);
        }
    }

    /**
     * INTERNAL:
     * Returns the row's field with the same name.
     */
    @Override
    public DatabaseField getField(DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    return field;
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    return field;
                }
            }
            return null;
        } else {
            return super.getField(key);
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public Vector getFields() {
        checkValues();
        return super.getFields();
    }

    /**
     * INTERNAL:
     */
    @Override
    public Vector getValues() {
        checkValues();
        return super.getValues();
    }

    /**
     * INTERNAL:
     * Add the field-value pair to the row.
     */
    @Override
    public Object put(DatabaseField key, Object value) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        return super.put(key, value);
    }

    /**
     * INTERNAL:
     * Remove the field key from the row.
     */
    @Override
    public Object remove(DatabaseField key) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        return super.remove(key);
    }

    /**
     * INTERNAL:
     * replaces the value at index with value
     */
    @Override
    public void replaceAt(Object value, int index) {
        if (this.valuesArray != null) {
            this.valuesArray[index] = value;
        } else {
            super.replaceAt(value, index);
        }
    }

    /**
     * INTERNAL:
     * replaces the value at field with value
     */
    @Override
    public void replaceAt(Object value, DatabaseField key) {
        if (this.fieldsArray != null) {
            // Optimize check.
            int index = key.index;
            if ((index >= 0) && (index < this.size)) {
                DatabaseField field = this.fieldsArray[index];
                if ((field == key) || field.equals(key)) {
                    this.valuesArray[index] = value;
                    return;
                }
            }
            for (int fieldIndex = 0; fieldIndex < this.size; fieldIndex++) {
                DatabaseField field = this.fieldsArray[fieldIndex];
                if ((field == key) || field.equals(key)) {
                    // PERF: If the fields index was not set, then set it.
                    if (index == -1) {
                        key.setIndex(fieldIndex);
                    }
                    this.valuesArray[fieldIndex] = value;
                    return;
                }
            }
        } else {
            super.replaceAt(value, key);
        }
    }

    @Override
    protected void setFields(Vector fields) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        super.setFields(fields);
    }

    @Override
    protected void setValues(Vector values) {
        checkValues();
        this.fieldsArray = null;
        this.valuesArray = null;
        super.setValues(values);
    }

    /**
     * PUBLIC:
     * Return the number of field/value pairs in the row.
     */
    @Override
    public int size() {
        if (this.fieldsArray == null) {
            return this.fields.size();
        } else {
            return this.fieldsArray.length;
        }
    }

    @Override
    public String toString() {
        if (this.valuesArray != null) {
            StringWriter writer = new StringWriter();
            writer.write(Helper.getShortClassName(getClass()));
            writer.write("(");
            writer.write(toStringAditional());
            for (int index = 0; index < this.fieldsArray.length; index++) {
                writer.write(Helper.cr());
                writer.write("\t");
                writer.write(String.valueOf(this.fieldsArray[index]));
                writer.write(" => ");
                writer.write(String.valueOf(this.valuesArray[index]));
            }
            if (this.sopObject != null) {
                writer.write(Helper.cr());
                writer.write(" sopObject = ");
                writer.write(this.sopObject.toString());
            }
            writer.write(")");

            return writer.toString();
        } else {
            return super.toString();
        }
    }

    protected String toStringAditional() {
        return "";
    }
}
