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

import java.io.*;
import java.util.*;

import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;

/**
 * <p>An <code>EISMappedRecord</code> acts as a <code>Record</code>
 * wrapper.  It allows database row field-value pair mappings to be used as a
 * mapped record implementation.
 *
 * @author James
 * @since OracleAS TopLink 10<i>g</i> (10.0.3)
 */
public class EISMappedRecord extends AbstractRecord {
    protected Map record;
    protected EISAccessor accessor;

    /**
     * Create a database row wrapper for the record.
     */
    public EISMappedRecord(Map record, EISAccessor accessor) {
        setRecord(record);
        setAccessor(accessor);
    }

    /**
     * INTERNAL:
     * getFields() is sued internally in a few places, so try to make that work for mapped records.
     */
    @Override
    public Vector<DatabaseField> getFields() {
        return new Vector<>(getRecord().keySet());
    }

    /**
     * INTERNAL:
     * getValues() is sued internally in a few places, so try to make that work for mapped records.
     */
    @Override
    public Vector getValues() {
        return new Vector<>(getRecord().values());
    }

    /**
     * Forward the request to the record.
     */
    @Override
    public Set keySet() {
        Set keys = getRecord().keySet();

        // Handle bug in Attunity record.  It returns null for the keys.
        if (keys == null) {
            return new HashSet(1);
        }
        return keys;
    }

    /**
     * Forward the request to the record.
     */
    @Override
    public Collection values() {
        return getRecord().values();
    }

    /**
     * Forward the request to the record.
     */
    @Override
    public int size() {
        return getRecord().size();
    }

    /**
     * Return if the row is empty.
     * For some reason Attunity MappedRecords think they are empty when not,
     * so always return false.
     */
    @Override
    public boolean isEmpty() {
        return false;
    }

    /**
     * Forward the request to the record.
     */
    @Override
    public void clear() {
        getRecord().clear();
    }

    /**
     * Forward the request to the record.
     */
    @Override
    public Object get(String key) {
        return getRecord().get(key);
    }

    /**
     * Forward the request to the record.
     * Wrapped nested records and collections to SDKFieldValues.
     */
    @Override
    public Object get(DatabaseField field) {
        Object value = get(field.getName());
        if (value instanceof Map) {
            Vector<EISMappedRecord> nestedRows = new Vector<>(1);
            nestedRows.add(new EISMappedRecord((Map)value, getAccessor()));
            value = nestedRows;
        } else if (value instanceof List) {
            List<?> values = (List<?>)value;
            Vector<Object> nestedValues = new Vector<>(values.size());
            for (int index = 0; index < values.size(); index++) {
                Object nestedValue = values.get(index);
                if (nestedValue instanceof Map) {
                    nestedValues.add(new EISMappedRecord((Map)values.get(index), getAccessor()));
                } else {
                    nestedValues.add(nestedValue);
                }
            }
            value = nestedValues;
        }
        return value;
    }

    /**
     * Check if the field is contained in the row.
     */
    @Override
    public boolean containsKey(String fieldName) {
        return get(fieldName) != null;
    }

    /**
     * Check if the field is contained in the row.
     */
    @Override
    public boolean containsKey(DatabaseField key) {
        return get(key) != null;
    }

    /**
     * Return the wrapped record.
     */
    public Map getRecord() {
        return record;
    }

    /**
     * Set the wrapped record.
     */
    public void setRecord(Map record) {
        this.record = record;
    }

    /**
     * Return the accessor.
     */
    public EISAccessor getAccessor() {
        return accessor;
    }

    /**
     * Set the accessor.
     */
    public void setAccessor(EISAccessor accessor) {
        this.accessor = accessor;
    }

    /**
     * Print all of the record keys and values.
     */
    @Override
    public String toString() {
        StringWriter writer = new StringWriter();
        writer.write(Helper.getShortClassName(getClass()));
        writer.write("(");

        for (Iterator<?> keysIterator = keySet().iterator(); keysIterator.hasNext();) {
            Object key = keysIterator.next();
            writer.write(Helper.cr());
            writer.write("\t");
            writer.write(String.valueOf(key));
            writer.write(" => ");
            writer.write(String.valueOf(get(key)));
        }
        writer.write(")");

        return writer.toString();
    }
}
