/*
 * Copyright (c) 2011, 2019 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.
     * @param classLoader
     */
    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.
     * @param group
     * @param subGroups
     * @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() : "");
    }
}
