/*
 * 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:
//     Matt MacIvor - 2.5 - initial implementation
package org.eclipse.persistence.core.queries;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;

/**
 * INTERNAL
 * <b>Purpose</b>: Generic superclass for AttributeItem.
 *
 * @author matt macivor
 * @since EclipseLink 2.5
 */
public class CoreAttributeItem<ATTRIBUTE_GROUP extends CoreAttributeGroup> implements Serializable, Cloneable {

    protected String attributeName;

    protected ATTRIBUTE_GROUP parent;

    protected ATTRIBUTE_GROUP group;

    protected ATTRIBUTE_GROUP keyGroup;

    protected Map<Object, ATTRIBUTE_GROUP> subGroups;

    protected Map<Object, ATTRIBUTE_GROUP> keyGroups;

//    private transient DatabaseMapping mapping;

    protected CoreAttributeItem() {
    }

    public CoreAttributeItem(ATTRIBUTE_GROUP parent, String attributeName) {
        this.parent = parent;
        this.attributeName = attributeName;
    }

    /**
     * INTERNAL:
     * Adds the list of groups as to the item
     */
    public void addGroups(Collection<ATTRIBUTE_GROUP> groups) {
        for (ATTRIBUTE_GROUP group : groups){
            addSubGroup(group);
        }
    }

    public void addKeyGroup(ATTRIBUTE_GROUP keyGroup) {
        if (keyGroup != null){
            if (this.keyGroups == null){
                this.keyGroups = new HashMap<>();
            }
            if (this.keyGroup == null){
                this.keyGroup = keyGroup;
            }
            Object type = keyGroup.getType();
            if (type == null){
                type = keyGroup.getTypeName();
            }
            if (type == null){
                type = CoreClassConstants.OBJECT;
                if (this.keyGroups.containsKey(type)){
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("only_one_root_subgraph"));
                }
            }
            this.keyGroups.put(type, keyGroup);
            if (orderInheritance(keyGroup, this.keyGroups)){
                keyGroup.insertSubClass(this.keyGroup);
                this.keyGroup = keyGroup;
            }
        }
    }

    public void addKeyGroups(Collection<ATTRIBUTE_GROUP> keyGroups) {
        for (ATTRIBUTE_GROUP group : keyGroups){
            this.addKeyGroup(group);
        }
    }

    public void addSubGroup(ATTRIBUTE_GROUP group) {
        if (group != null){
            if (this.subGroups == null){
                this.subGroups = new HashMap<>();
            }
            if (this.group == null){
                this.group = group;
            }
            Object type = group.getType();
            if (type == null){
                type = group.getTypeName();
            }
            if (type == null){
                type = CoreClassConstants.OBJECT;
                if (this.subGroups.containsKey(type)){
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("only_one_root_subgraph"));
                }
            }
            this.subGroups.put(type, group);
            if (orderInheritance(group, this.subGroups)){
                group.insertSubClass(this.group);
                this.group = group;
            }
        }
    }

    public CoreAttributeItem<ATTRIBUTE_GROUP> clone(Map<ATTRIBUTE_GROUP, ATTRIBUTE_GROUP> cloneMap, ATTRIBUTE_GROUP parentClone){
        CoreAttributeItem clone = null;
        try {
            clone = (CoreAttributeItem) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);
        }
        clone.attributeName = this.attributeName;
        if (this.group != null){
            clone.group = this.group.clone(cloneMap);
        }
        if (clone.keyGroup != null){
            clone.keyGroup = this.keyGroup.clone(cloneMap);
        }
        clone.parent = parentClone;
        if (this.subGroups != null){
            clone.subGroups = new HashMap<Object, ATTRIBUTE_GROUP>();
            for (Entry<Object, ATTRIBUTE_GROUP> group : this.subGroups.entrySet()){
                clone.subGroups.put(group.getKey(), group.getValue().clone(cloneMap));
            }
        }
        if (this.keyGroups != null){
            clone.keyGroups = new HashMap<Object, ATTRIBUTE_GROUP>();
            for (Entry<Object, ATTRIBUTE_GROUP> group : this.keyGroups.entrySet()){
                clone.keyGroups.put(group.getKey(), group.getValue().clone(cloneMap));
            }
        }
        return clone;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this Descriptor to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    public void convertClassNamesToClasses(ClassLoader classLoader){
        Map<Object, ATTRIBUTE_GROUP> newMap = new HashMap<>();
        if (this.subGroups != null){
            for (ATTRIBUTE_GROUP entry : this.subGroups.values()){
                entry.convertClassNamesToClasses(classLoader);
                if(!(entry.getSubClassGroups().isEmpty())) {
                    newMap.putAll(entry.getSubClassGroups());
                }
                newMap.put(entry.getType(), entry);
                entry.setAllSubclasses(newMap);
            }
        }
        this.subGroups = newMap;

        newMap = new HashMap<>();
        if (this.keyGroups != null){
            for (ATTRIBUTE_GROUP entry : this.keyGroups.values()){
                entry.convertClassNamesToClasses(classLoader);
                newMap.put(entry.getType(), entry);
                entry.setAllSubclasses(newMap);
            }
        }
        this.keyGroups = newMap;
        for (ATTRIBUTE_GROUP group : this.subGroups.values()){
            if (orderInheritance(group, this.subGroups)){
                group.insertSubClass(this.group);
                this.group = group;
            }
        }
        for (ATTRIBUTE_GROUP group : this.keyGroups.values()){
            if (orderInheritance(group, this.keyGroups)){
                group.insertSubClass(this.keyGroup);
                this.keyGroup = group;
            }

        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this != obj) {
            if(obj == null) {
                return false;
            }
            CoreAttributeItem anotherItem = null;
            try {
                anotherItem = (CoreAttributeItem)obj;
            } catch (ClassCastException cce) {
                return false;
            }

            if(this.subGroups != null) {
                if (anotherItem.subGroups == null){
                    return false;
                }
                if (this.subGroups.size() == anotherItem.subGroups.size()){
                    for (Map.Entry<Object, ATTRIBUTE_GROUP> entry : this.subGroups.entrySet()){
                        ATTRIBUTE_GROUP anotherGroup = (ATTRIBUTE_GROUP)anotherItem.subGroups.get(entry.getKey());
                        if (! entry.getValue().equals(anotherGroup)){
                            return false;
                        }
                    }
                }else{
                    return false;
                }
            } else if (anotherItem.subGroups != null){
                return false;
            }

            if(this.keyGroups != null) {
                if (anotherItem.keyGroups == null){
                    return false;
                }
                if (this.keyGroups.size() == anotherItem.keyGroups.size()){
                    for (Map.Entry<Object, ATTRIBUTE_GROUP> entry : this.keyGroups.entrySet()){
                        ATTRIBUTE_GROUP anotherGroup = (ATTRIBUTE_GROUP)anotherItem.keyGroups.get(entry.getKey());
                        if (! entry.getValue().equals(anotherGroup)){
                            return false;
                        }
                    }
                }else{
                    return false;
                }
            } else if (anotherItem.keyGroups != null){
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = subGroups != null ? subGroups.hashCode() : 0;
        result = 31 * result + (keyGroups != null ? keyGroups.hashCode() : 0);
        return result;
    }

    public String getAttributeName() {
        return this.attributeName;
    }

    public ATTRIBUTE_GROUP getGroup() {
        if (this.group == null){
            return null;
        }
        return this.group;
    }

    public ATTRIBUTE_GROUP getGroup(Class type) {
        if (this.subGroups == null || type == null){
            return null;
        }
        ATTRIBUTE_GROUP result = this.subGroups.get(type);
        while(result == null && !type.equals(CoreClassConstants.OBJECT)){
            type = type.getSuperclass();
            if (type == null){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("subclass_sought_not_a_managed_type", new Object[]{null, this.attributeName}));
            }
            result = this.subGroups.get(type);
        }
        return result;
    }

    public Map<Object, ATTRIBUTE_GROUP> getGroups(){
        return this.subGroups;
    }

    public ATTRIBUTE_GROUP getKeyGroup() {
        if (this.keyGroups == null){
            return null;
        }
        return this.keyGroups.get(CoreClassConstants.OBJECT);
    }

    public ATTRIBUTE_GROUP getKeyGroup(Class type) {
        if (this.keyGroups == null || type == null){
            return null;
        }
        ATTRIBUTE_GROUP result = this.keyGroups.get(type);
        Class currentType = type;
        while(result == null && !currentType.equals(CoreClassConstants.OBJECT)){
            currentType = currentType.getSuperclass();
            if (currentType == null){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("subclass_sought_not_a_managed_type", new Object[]{type, this.attributeName}));
            }
            result = this.keyGroups.get(currentType);
        }
        return result;
    }

    public Map<Object, ATTRIBUTE_GROUP> getKeyGroups(){
        return this.keyGroups;
    }

    public ATTRIBUTE_GROUP getParent() {
        return this.parent;
    }

    /**
     * Will order the subGroups based on hierarchy.  Returns true if the group is the new root.
     * @return true if the group is the new root.
     */
    protected static boolean orderInheritance(CoreAttributeGroup group, Map<Object, ? extends CoreAttributeGroup> subGroups) {
        Class type = group.getType();
        if (type != null){
            CoreAttributeGroup superClass = null;
            while (!type.equals(CoreClassConstants.OBJECT) && superClass == null){
                type = type.getSuperclass();
                superClass = subGroups.get(type);
            }
            if (superClass != null){
                superClass.insertSubClass(group);
            }else{
                return true;
            }
        }
        return false;
    }

    public void setRootGroup(ATTRIBUTE_GROUP group) {
        this.group = group;
        this.addSubGroup(group);
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "(" + getAttributeName() + ")" + (this.subGroups!=null ? " => " + this.subGroups.toString() : "") + (this.keyGroups!=null ? " => " + this.keyGroups.toString() : "");
    }

    public String toStringNoClassName() {
        return getAttributeName() + (this.subGroups!=null ? " => " + this.subGroups.toString() : "")+ (this.keyGroups!=null ? " => " + this.keyGroups.toString() : "");
    }
}
