/*
 * Copyright (c) 2011, 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
package org.eclipse.persistence.nosql.adapters.nosql;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import jakarta.resource.cci.InteractionSpec;
import jakarta.resource.cci.MappedRecord;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.descriptors.SelectedFieldsLockingPolicy;
import org.eclipse.persistence.eis.EISAccessor;
import org.eclipse.persistence.eis.EISDOMRecord;
import org.eclipse.persistence.eis.EISDescriptor;
import org.eclipse.persistence.eis.EISException;
import org.eclipse.persistence.eis.EISMappedRecord;
import org.eclipse.persistence.eis.EISPlatform;
import org.eclipse.persistence.eis.interactions.EISInteraction;
import org.eclipse.persistence.eis.interactions.MappedInteraction;
import org.eclipse.persistence.eis.interactions.XMLInteraction;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.nosql.adapters.nosql.OracleNoSQLInteractionSpec;
import org.eclipse.persistence.internal.nosql.adapters.nosql.OracleNoSQLOperation;
import org.eclipse.persistence.internal.nosql.adapters.nosql.OracleNoSQLRecord;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sequencing.UUIDSequence;
import org.w3c.dom.Element;

import oracle.kv.Consistency;
import oracle.kv.Durability;
import oracle.kv.Version;

/**
 * Platform for Oracle NoSQL database.
 *
 * @author James
 * @since EclipseLink 2.4
 */
public class OracleNoSQLPlatform extends EISPlatform {

    /** OracleNoSQL interaction spec properties. */
    public static String OPERATION = "nosql.operation";
    public static String CONSISTENCY = "nosql.consistency";
    public static String DURABILITY = "nosql.durability";
    public static String TIMEOUT = "nosql.timeout";
    public static String VERSION = "nosql.version";

    /**
     * Default constructor.
     */
    public OracleNoSQLPlatform() {
        super();
        setShouldConvertDataToStrings(true);
        setIsMappedRecordSupported(true);
        setIsIndexedRecordSupported(false);
        setIsDOMRecordSupported(true);
        setSupportsLocalTransactions(true);
    }

    /**
     * Allow the platform to build the interaction spec based on properties defined in the interaction.
     */
    @Override
    public InteractionSpec buildInteractionSpec(EISInteraction interaction) {
        InteractionSpec spec = interaction.getInteractionSpec();
        if (spec == null) {
            OracleNoSQLInteractionSpec noSqlSpec = new OracleNoSQLInteractionSpec();
            Object operation = interaction.getProperty(OPERATION);
            if (operation == null) {
                throw new EISException("'" + OPERATION + "' property must be set on the query's interation.");
            }
            if (operation instanceof String) {
                operation = OracleNoSQLOperation.valueOf((String)operation);
            }
            noSqlSpec.setOperation((OracleNoSQLOperation)operation);

            // Allows setting of consistency as a property.
            Object consistency = interaction.getProperty(CONSISTENCY);
            if (consistency == null) {
                // Default to session property.
                consistency = interaction.getQuery().getSession().getProperty(CONSISTENCY);
            }
            if (consistency instanceof Consistency) {
                noSqlSpec.setConsistency((Consistency)consistency);
            } else if (consistency instanceof String) {
                String constant = (String)consistency;
                if (constant.equals("ABSOLUTE")) {
                    noSqlSpec.setConsistency(Consistency.ABSOLUTE);
                } else if (constant.equals("NONE_REQUIRED")) {
                    noSqlSpec.setConsistency(Consistency.NONE_REQUIRED );
                } else {
                    throw new EISException("Invalid consistency property value: " + constant);
                }
            }

            // Allows setting of durability as a property.
            Object durability = interaction.getProperty(DURABILITY);
            if (durability == null) {
                // Default to session property.
                durability = interaction.getQuery().getSession().getProperty(DURABILITY);
            }
            if (durability instanceof Durability) {
                noSqlSpec.setDurability((Durability)durability);
            } else if (durability instanceof String) {
                String constant = (String)durability;
                if (constant.equals("COMMIT_NO_SYNC")) {
                    noSqlSpec.setDurability(Durability.COMMIT_NO_SYNC);
                } else if (constant.equals("COMMIT_SYNC")) {
                    noSqlSpec.setDurability(Durability.COMMIT_SYNC );
                }  else if (constant.equals("COMMIT_WRITE_NO_SYNC")) {
                    noSqlSpec.setDurability(Durability.COMMIT_WRITE_NO_SYNC );
                } else {
                    throw new EISException("Invalid durability property value: " + constant);
                }
            }

            // Allows setting of timeout as a property.
            Object timeout = interaction.getProperty(TIMEOUT);
            if (timeout == null) {
                // Default to session property.
                timeout = interaction.getQuery().getSession().getProperty(TIMEOUT);
            }
            if (timeout instanceof Number) {
                noSqlSpec.setTimeout(((Number)timeout).longValue());
            } else if (timeout instanceof String) {
                noSqlSpec.setTimeout(Long.valueOf(((String)timeout)));
            } else if (interaction.getQuery().getQueryTimeout() > 0) {
                noSqlSpec.setTimeout(interaction.getQuery().getQueryTimeout());
            }

            // Allows setting of version as a property.
            Object version = interaction.getProperty(VERSION);
            if (version == null) {
                // Default to session property.
                version = interaction.getQuery().getSession().getProperty(VERSION);
            }
            if (version == null) {
                if (interaction.getQuery().getDescriptor() != null) {
                    ClassDescriptor descriptor = interaction.getQuery().getDescriptor();
                    if (descriptor.usesOptimisticLocking() && descriptor.getOptimisticLockingPolicy() instanceof SelectedFieldsLockingPolicy) {
                        DatabaseField field = ((SelectedFieldsLockingPolicy)descriptor.getOptimisticLockingPolicy()).getLockFields().get(0);
                        if (interaction.getInputRow() != null) {
                            version = interaction.getInputRow().get(field);
                        }
                    }
                }
            }
            if (version instanceof Version) {
                noSqlSpec.setVersion((Version)version);
            } else if (version instanceof byte[]) {
                noSqlSpec.setVersion(Version.fromByteArray((byte[])version));
            }

            spec = noSqlSpec;
        }
        return spec;
    }

    /**
     * INTERNAL:
     * Allow the platform to handle record to row conversion.
     */
    @Override
    public AbstractRecord buildRow(jakarta.resource.cci.Record record, EISInteraction interaction, EISAccessor accessor) {
        if (record == null) {
            return null;
        }
        OracleNoSQLRecord output = (OracleNoSQLRecord)record;
        if ((output.size() == 1) && (interaction.getQuery().getDescriptor() != null)) {
            // Check for a nested mapped record.
            Object value = output.values().iterator().next();
            if (value instanceof OracleNoSQLRecord) {
                convertRecordBytesToString((OracleNoSQLRecord)value);
                output = (OracleNoSQLRecord)value;
            }
        }
        jakarta.resource.cci.Record result = output;
        if (getRecordConverter() != null) {
            result = getRecordConverter().converterFromAdapterRecord(output);
        }
        return interaction.buildRow(result, accessor);
    }

    /**
     * Allow the platform to handle record to row conversion.
     */
    @Override
    public Vector buildRows(jakarta.resource.cci.Record record, EISInteraction interaction, EISAccessor accessor) {
        if (record == null) {
            return new Vector(0);
        }
        OracleNoSQLRecord output = (OracleNoSQLRecord)record;
        if ((output.size() == 1) && (interaction.getQuery().getDescriptor() != null)) {
            // Check for a nested mapped record.
            Object value = output.values().iterator().next();
            if (value instanceof OracleNoSQLRecord) {
                Vector rows = new Vector(1);
                convertRecordBytesToString((OracleNoSQLRecord)value);
                rows.add(interaction.buildRow((OracleNoSQLRecord)value, accessor));
                return rows;
            } else if (value instanceof Collection) {
                Vector rows = new Vector(((Collection)value).size());
                for (Object nestedValue : (Collection)value) {
                    if (nestedValue instanceof OracleNoSQLRecord) {
                        rows.add(interaction.buildRow((OracleNoSQLRecord)nestedValue, accessor));
                    }
                }
                return rows;
            }
        }
        if (interaction.getQuery().getDescriptor() != null) {
            // Check for a map of values.
            Vector rows = new Vector();
            for (Object value : output.values()) {
                if (value instanceof OracleNoSQLRecord) {
                    convertRecordBytesToString((OracleNoSQLRecord)value);
                    rows.add(interaction.buildRow((OracleNoSQLRecord)value, accessor));
                } else if (value instanceof byte[]) {
                    EISDOMRecord domRecord = new EISDOMRecord();
                    domRecord.transformFromXML(new String((byte[])value));
                    rows.add(domRecord);
                }
            }
            return rows;
        }
        return interaction.buildRows(record, accessor);
    }

    /**
     * INTERNAL:
     * Convert the record and nested records bytes to strings.
     */
    protected void convertRecordBytesToString(OracleNoSQLRecord record) {
        // Convert byte[] to String.
        for (Iterator<Map.Entry> iterator = record.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry entry = iterator.next();
            if (entry.getValue() instanceof byte[]) {
                entry.setValue(new String((byte[])entry.getValue()));
            } else if (entry.getValue() instanceof OracleNoSQLRecord) {
                convertRecordBytesToString((OracleNoSQLRecord)entry.getValue());
            }
        }
    }

    /**
     * Allow the platform to create the appropriate type of record for the interaction.
     * Convert the nested local mapped record to a flat global keyed record.
     */
    @Override
    public jakarta.resource.cci.Record createInputRecord(EISInteraction interaction, EISAccessor accessor) {
        if (interaction instanceof XMLInteraction) {
            return super.createInputRecord(interaction, accessor);
        } if (interaction instanceof MappedInteraction) {
            MappedRecord input = (MappedRecord)interaction.createInputRecord(accessor);
            // Create the key from the objects id.
            ClassDescriptor descriptor = interaction.getQuery().getDescriptor();
            if (descriptor == null) {
                if (getRecordConverter() != null) {
                    return getRecordConverter().converterToAdapterRecord(input);
                }
                return input;
            }
            Object key = createMajorKey(descriptor, new EISMappedRecord(input, accessor), interaction, accessor);
            OracleNoSQLRecord record = new OracleNoSQLRecord();
            record.put(key, input);
            if (getRecordConverter() != null) {
                return getRecordConverter().converterToAdapterRecord(record);
            }
            return record;
        } else {
            return super.createInputRecord(interaction, accessor);
        }
    }

    /**
     * Stores the XML DOM value into the record.
     * XML is stored in Oracle NoSQL but storing the XML text, keyed on the object's {@literal "&lt;dataTypeName&gt;/&lt;id&gt;"}.
     */
    @Override
    public void setDOMInRecord(Element dom, jakarta.resource.cci.Record record, EISInteraction interaction, EISAccessor accessor) {
        OracleNoSQLRecord noSqlRecord = (OracleNoSQLRecord)record;
        org.eclipse.persistence.oxm.record.DOMRecord domRecord = new org.eclipse.persistence.oxm.record.DOMRecord(dom);
        domRecord.setSession(interaction.getQuery().getSession());
        // Create the key from the objects id.
        ClassDescriptor descriptor = interaction.getQuery().getDescriptor();
        if (descriptor == null) {
            throw new EISException("XMLInteraction is only valid for object queries, use MappedIneraction for native queries: " + interaction);
        }
        Object key = createMajorKey(descriptor, domRecord, interaction, accessor);
        noSqlRecord.put(key, domRecord.transformToXML().getBytes());
    }

    /**
     * NoSQL stores the data in a single big map.
     * The keys are called major keys (minor keys are used to store the attributes).
     * Major keys can have multiple values (and normally do).
     * The first value is normally the type, then the id.
     */
    protected Object createMajorKey(ClassDescriptor descriptor, AbstractRecord record, EISInteraction interaction, EISAccessor accessor) {
        Object id = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(record, interaction.getQuery().getSession());
        List key = new ArrayList(descriptor.getPrimaryKeyFields().size() + 1);
        if (((EISDescriptor)descriptor).getDataTypeName().length() > 0) {
            key.add(((EISDescriptor)descriptor).getDataTypeName());
        }
        if (id != null) {
            if (id instanceof CacheId) {
                Object[] idValues = ((CacheId)id).getPrimaryKey();
                for (Object idValue : idValues) {
                    String idString = (String)accessor.getDatasourcePlatform().getConversionManager().convertObject(idValue, String.class);
                    key.add(idString);
                }
            } else {
                String idString = (String)accessor.getDatasourcePlatform().getConversionManager().convertObject(id, String.class);
                key.add(idString);
            }
        }
        return key;
    }

    /**
     * Allow the platform to handle the creation of the Record for the DOM record.
     * Creates a DOM record from the XML data stored as a value in the OracleNoSQLRecord.
     */
    @Override
    public AbstractRecord createDatabaseRowFromDOMRecord(jakarta.resource.cci.Record record, EISInteraction call, EISAccessor accessor) {
        if (record == null) {
            return null;
        }
        EISDOMRecord domRecord = null;
        OracleNoSQLRecord noSqlRecord = (OracleNoSQLRecord)record;
        if (noSqlRecord.size() == 0) {
            return null;
        } else if (noSqlRecord.size() == 1) {
            domRecord = new EISDOMRecord();
            Object value = noSqlRecord.values().iterator().next();
            String xml = null;
            if (value instanceof byte[]) {
                xml = new String ((byte[])value);
            } else {
                xml = (String) value;
            }
            if (xml != null) {
                domRecord.transformFromXML(xml);
            }
        } else {
            domRecord = new EISDOMRecord();
            for (Map.Entry entry : (Set<Map.Entry>)noSqlRecord.entrySet()) {
                Object value = entry.getValue();
                String xml = null;
                if (value instanceof byte[]) {
                    xml = new String ((byte[])value);
                } else {
                    xml = (String)value;
                }
                if (xml != null) {
                    EISDOMRecord dom = new EISDOMRecord();
                    dom.transformFromXML(xml);
                    domRecord.put(entry.getKey(), dom);
                }
            }

        }
        return domRecord;
    }

    /**
     * INTERNAL:
     * Allow the platform to initialize the CRUD queries to defaults.
     * Configure the CRUD operations using GET/PUT and DELETE.
     */
    @Override
    public void initializeDefaultQueries(DescriptorQueryManager queryManager, AbstractSession session) {
        boolean isXML = ((EISDescriptor)queryManager.getDescriptor()).isXMLFormat();
        // Insert
        if (!queryManager.hasInsertQuery()) {
            EISInteraction call = isXML ? new XMLInteraction() : new MappedInteraction();
            call.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.PUT_IF_ABSENT);
            queryManager.setInsertCall(call);
        }

        // Update
        if (!queryManager.hasUpdateQuery()) {
            EISInteraction call = isXML ? new XMLInteraction() : new MappedInteraction();
            call.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.PUT_IF_PRESENT);
            queryManager.setUpdateCall(call);
        }

        // Read
        if (!queryManager.hasReadObjectQuery()) {
            MappedInteraction call = isXML ? new XMLInteraction() : new MappedInteraction();
            call.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.GET);
            for (DatabaseField field : queryManager.getDescriptor().getPrimaryKeyFields()) {
                call.addArgument(field.getName());
            }
            queryManager.setReadObjectCall(call);
        }

        // Read-all
        if (!queryManager.hasReadAllQuery()) {
            MappedInteraction call = isXML ? new XMLInteraction() : new MappedInteraction();
            call.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.ITERATOR);
            queryManager.setReadAllCall(call);
        }

        // Delete
        if (!queryManager.hasDeleteQuery()) {
            MappedInteraction call = isXML ? new XMLInteraction() : new MappedInteraction();
            call.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.DELETE);
            for (DatabaseField field : queryManager.getDescriptor().getPrimaryKeyFields()) {
                call.addArgument(field.getName());
            }
            queryManager.setDeleteCall(call);
        }
    }

    /**
     * Do not prepare to avoid errors being triggered for id and all queries.
     */
    @Override
    public boolean shouldPrepare(DatabaseQuery query) {
        return (query.getDatasourceCall() instanceof EISInteraction);
    }

    /**
     * INTERNAL:
     * NoSQL does not support id generation, so use UUID as the default.
     */
    @Override
    protected Sequence createPlatformDefaultSequence() {
        return new UUIDSequence();
    }
}
