/*
 * Copyright (c) 2011, 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:
//         dclarke/tware - initial
package org.eclipse.persistence.jpa.rs.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.internal.descriptors.PersistenceEntity;
import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.jpa.CMP3Policy;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.sessions.DatabaseSession;

/**
 * EclipseLink helper class used for converting composite key values passed into
 * JAX-RS calls as query or matrix parameters into a value that can be used in a
 * find.
 *
 * @author dclarke
 * @since EclipseLink 2.4.0
 */
public class IdHelper {

    private static final String SEPARATOR_STRING = "+";

    @SuppressWarnings("rawtypes")
    public static Object buildId(PersistenceContext app, String entityName, String idString) {
        DatabaseSession session = app.getServerSession();
        ClassDescriptor descriptor = app.getDescriptor(entityName);
        List<DatabaseMapping> pkMappings = descriptor.getObjectBuilder().getPrimaryKeyMappings();
        List<SortableKey> pkIndices = new ArrayList<>();
        int index = 0;
        int multitenantPKMappings = 0;
        for (DatabaseMapping mapping : pkMappings) {
            if (mapping.isMultitenantPrimaryKeyMapping()) {
                multitenantPKMappings++;
            } else {
                pkIndices.add(new SortableKey(mapping, index));
                index++;
            }
        }
        Collections.sort(pkIndices);

        // Handle composite key in map
        Object[] keyElements = new Object[pkMappings.size() - multitenantPKMappings];
        StringTokenizer tokenizer = new StringTokenizer(idString, SEPARATOR_STRING);
        int tokens = tokenizer.countTokens();
        if (tokens + multitenantPKMappings != pkMappings.size()) {
            throw new RuntimeException("Failed, incorrect number of keys values");
        }
        index = 0;
        Iterator<SortableKey> iterator = pkIndices.iterator();
        while (tokenizer.hasMoreTokens()) {
            SortableKey key = iterator.next();
            String token = tokenizer.nextToken();
            DatabaseMapping mapping = key.getMapping();
            Class<?> attributeClasification = mapping.getAttributeClassification();
            if (attributeClasification == null) {
                if ((mapping.getFields() != null) && (!mapping.getFields().isEmpty())) {
                    attributeClasification = mapping.getFields().get(0).getType();
                }
            }

            Object idValue = session.getDatasourcePlatform().getConversionManager().convertObject(token, attributeClasification);
            keyElements[key.getIndex()] = idValue;
            index++;
        }

        if (descriptor.hasCMPPolicy()) {
            CMP3Policy policy = (CMP3Policy) descriptor.getCMPPolicy();
            return policy.createPrimaryKeyInstanceFromPrimaryKeyValues((AbstractSession) session, new int[] { 0 }, keyElements);
        }

        if (keyElements.length == 1) {
            return keyElements[0];
        }
        return keyElements;
    }

    public static String stringifyId(Object entity, String typeName, PersistenceContext app) {
        ClassDescriptor descriptor = app.getDescriptor(typeName);
        List<DatabaseMapping> pkMappings = descriptor.getObjectBuilder().getPrimaryKeyMappings();
        if (pkMappings.isEmpty()) {
            return "";
        }
        List<SortableKey> pkIndices = new ArrayList<>();
        int index = 0;
        for (DatabaseMapping mapping : pkMappings) {
            pkIndices.add(new SortableKey(mapping, index));
            index++;
        }
        Collections.sort(pkIndices);
        StringBuilder key = new StringBuilder();
        Iterator<SortableKey> sortableKeys = pkIndices.iterator();
        List<DatabaseField> refObjectdbFields = null;
        while (sortableKeys.hasNext()) {
            DatabaseMapping mapping = sortableKeys.next().getMapping();
            ClassDescriptor refDesc = mapping.getReferenceDescriptor();
            List<DatabaseField> dbFields = mapping.getDescriptor().getPrimaryKeyFields();
            if (refDesc != null) {
                refObjectdbFields = refDesc.getFields();
            }

            if ((refObjectdbFields != null) && (!refObjectdbFields.isEmpty())) {
                for (DatabaseField dbField : dbFields) {
                    String dbFieldName = dbField.getName();
                    String refObjectDbFieldName = null;
                    if (refDesc != null) {
                        for (DatabaseField refObjectDbField : refObjectdbFields) {
                            refObjectDbFieldName = refObjectDbField.getName();
                            if ((refObjectDbFieldName != null) && (dbFieldName != null)) {
                                if (dbFieldName.equals(refObjectDbFieldName)) {
                                    List<DatabaseMapping> refMappings = refDesc.getMappings();
                                    for (DatabaseMapping refMapping : refMappings) {//
                                        DatabaseField field = refMapping.getField();
                                        if (field != null) {
                                            String fieldName = field.getName();
                                            if (mapping instanceof OneToOneMapping) {
                                                Map<DatabaseField, DatabaseField> targetToSourceKeyFields = ((OneToOneMapping) mapping).getTargetToSourceKeyFields();
                                                Map<DatabaseField, DatabaseField> sourceToTargetFields = ((OneToOneMapping) mapping).getTargetToSourceKeyFields();
                                                if ((targetToSourceKeyFields != null) && (!targetToSourceKeyFields.isEmpty())) {
                                                    if (targetToSourceKeyFields.containsKey(refObjectDbField)) {
                                                        if ((sourceToTargetFields != null) && (!sourceToTargetFields.isEmpty())) {
                                                            if (sourceToTargetFields.containsKey(field)) {
                                                                if ((fieldName != null) && (dbFieldName.equals(fieldName))) {
                                                                    Object value = descriptor.getObjectBuilder().getBaseValueForField(dbField, entity);
                                                                    Object realAttributeValue = refMapping.getRealAttributeValueFromAttribute(refMapping.getAttributeValueFromObject(value), value, (AbstractSession) app.getServerSession());
                                                                    key.append(realAttributeValue);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                Object part = mapping.getAttributeValueFromObject(entity);
                key.append(part);
            }
            if (sortableKeys.hasNext()) {
                key.append(SEPARATOR_STRING);
                refObjectdbFields = null;
            }
        }
        return key.toString();
    }

    /**
     * build a shell of an object based on a primary key.  The object shell will be an instance of the object with
     * only primary key populated
     */
    public static Object buildObjectShell(PersistenceContext context, String entityType, Object id) {
        ClassDescriptor descriptor = context.getDescriptor(entityType);
        List<DatabaseMapping> pkMappings = descriptor.getObjectBuilder().getPrimaryKeyMappings();
        Object entity = null;
        if (descriptor.hasCMPPolicy()) {
            CMP3Policy policy = (CMP3Policy) descriptor.getCMPPolicy();
            entity = policy.createBeanUsingKey(id, (AbstractSession) context.getServerSession());
        } else if (DynamicEntity.class.isAssignableFrom(descriptor.getJavaClass())) {
            DynamicEntityImpl dynamicEntity = (DynamicEntityImpl) context.newEntity(entityType);
            // if there is only one PK mapping, we assume the id object
            // represents the value of that mapping
            if (pkMappings.size() == 1) {
                dynamicEntity.set(pkMappings.get(0).getAttributeName(), id);
            } else {
                // If there are more that one PK, we assume an array as produced
                // by buildId() above with the keys
                // based on a sorted order of PK fields
                List<SortableKey> pkIndices = new ArrayList<>();
                int index = 0;
                for (DatabaseMapping mapping : pkMappings) {
                    pkIndices.add(new SortableKey(mapping, index));
                    index++;
                }
                Collections.sort(pkIndices);
                Object[] keyElements = (Object[]) id;
                for (SortableKey key : pkIndices) {
                    dynamicEntity.set(key.getMapping().getAttributeName(), keyElements[key.getIndex()]);
                }
            }
            entity = dynamicEntity;
        } else {
            throw new RuntimeException("Could not create shell for entity.");
        }

        if (entity instanceof PersistenceEntity) {
            ((PersistenceEntity) entity)._persistence_setId(id);
        }
        if (entity instanceof FetchGroupTracker) {
            ((FetchGroupTracker) entity)._persistence_setSession(JpaHelper.getDatabaseSession(context.getEmf()));
        }

        return entity;
    }

    static List<SortableKey> getPrimaryKey(PersistenceContext context, String entityName) {
        ClassDescriptor descriptor = context.getDescriptor(entityName);
        List<DatabaseMapping> pkMappings = descriptor.getObjectBuilder().getPrimaryKeyMappings();
        List<SortableKey> pkIndices = new ArrayList<>();
        int index = 0;
        for (DatabaseMapping mapping : pkMappings) {
            if (!mapping.isMultitenantPrimaryKeyMapping()) {
                pkIndices.add(new SortableKey(mapping, index));
                index++;
            }
        }
        Collections.sort(pkIndices);
        return pkIndices;
    }

    private static class SortableKey implements Comparable<SortableKey> {
        private DatabaseMapping mapping;
        private int index;

        public SortableKey(DatabaseMapping mapping, int index) {
            this.mapping = mapping;
            this.index = index;
        }

        @Override
        public int compareTo(SortableKey o) {
            if (this.equals(o)) {
                return 0;
            } else if (mapping.getAttributeName().equals(o.getMapping().getAttributeName())) {
                return Integer.compare(index, o.getIndex());
            } else {
                return mapping.getAttributeName().compareTo(o.getMapping().getAttributeName());
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            SortableKey that = (SortableKey) o;

            if (index != that.index) return false;
            if (!mapping.equals(that.mapping)) return false;

            return true;
        }

        @Override
        public int hashCode() {
            int result = mapping.hashCode();
            result = 31 * result + index;
            return result;
        }

        public DatabaseMapping getMapping() {
            return mapping;
        }

        public int getIndex() {
            return index;
        }
    }
}
