/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.server.model;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.store.ConfiguredObjectDependency;
import org.apache.qpid.server.store.ConfiguredObjectIdDependency;
import org.apache.qpid.server.store.ConfiguredObjectNameDependency;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.UnresolvedConfiguredObject;

public abstract class AbstractUnresolvedObject<C extends ConfiguredObject<C>> implements UnresolvedConfiguredObject<C>
{
    private final Class<C> _clazz;
    private final Collection<ConfiguredObjectDependency<?>> _unresolvedObjects = new ArrayList<ConfiguredObjectDependency<?>>();
    private final ConfiguredObjectRecord _record;
    private final ConfiguredObject<?> _parent;

    protected AbstractUnresolvedObject(Class<C> clazz,
                                       ConfiguredObjectRecord record,
                                       ConfiguredObject<?> parent)
    {
        _clazz = clazz;
        _record = record;
        _parent = parent;

        Collection<ConfiguredObjectAttribute<? super C, ?>> attributes =
                parent.getModel().getTypeRegistry().getAttributes(clazz);
        for(ConfiguredObjectAttribute<? super C, ?> attribute : attributes)
        {
            if(attribute.isPersisted())
            {
                final Class<?> attributeType = attribute.getType();
                if (ConfiguredObject.class.isAssignableFrom(attributeType))
                {
                    addUnresolvedObject((Class<? extends ConfiguredObject>) attributeType,
                                        attribute.getName(),
                                        attribute.isAutomated() && ((ConfiguredSettableAttribute<? super C,?>)attribute).isMandatory());
                }
                else if (Collection.class.isAssignableFrom(attributeType))
                {
                    Type returnType = attribute.getGenericType();
                    Class<? extends ConfiguredObject> attrClass = getMemberType(returnType);
                    if (attrClass != null)
                    {
                        Object attrValue = _record.getAttributes().get(attribute.getName());
                        if (attrValue != null)
                        {
                            if (attrValue instanceof Collection)
                            {
                                for (Object val : (Collection) attrValue)
                                {
                                    addUnresolvedObject(attrClass, attribute.getName(), val);
                                }
                            }
                            else if (attrValue instanceof Object[])
                            {
                                for (Object val : (Object[]) attrValue)
                                {
                                    addUnresolvedObject(attrClass, attribute.getName(), val);
                                }
                            }
                            else
                            {
                                addUnresolvedObject(attrClass, attribute.getName(), attrValue);
                            }
                        }
                    }


                }
            }
        }
    }

    private Class<? extends ConfiguredObject> getMemberType(Type returnType)
    {
        Class<? extends ConfiguredObject> categoryClass = null;

        if (returnType instanceof ParameterizedType)
        {
            Type type = ((ParameterizedType) returnType).getActualTypeArguments()[0];
            if (type instanceof Class && ConfiguredObject.class.isAssignableFrom((Class)type))
            {
                categoryClass = (Class<? extends ConfiguredObject>) type;
            }
            else if (type instanceof ParameterizedType)
            {
                Type rawType = ((ParameterizedType) type).getRawType();
                if (rawType instanceof Class && ConfiguredObject.class.isAssignableFrom((Class)rawType))
                {
                    categoryClass = (Class<? extends ConfiguredObject>) rawType;
                }
            }
            else if (type instanceof TypeVariable)
            {
                Type[] bounds = ((TypeVariable) type).getBounds();
                for(Type boundType : bounds)
                {
                    categoryClass = getMemberType(boundType);
                    if(categoryClass != null)
                    {
                        break;
                    }
                }
            }
        }
        return categoryClass;
    }


    public ConfiguredObjectRecord getRecord()
    {
        return _record;
    }

    @Override
    public ConfiguredObject<?> getParent()
    {
        return _parent;
    }

    private void addUnresolvedObject(final Class<? extends ConfiguredObject> clazz,
                                     final String attributeName,
                                     boolean mandatory)
    {
        Object attrValue = _record.getAttributes().get(attributeName);
        if(attrValue != null)
        {
            addUnresolvedObject(clazz, attributeName, attrValue);
        }
        else if(mandatory)
        {
            throw new IllegalConfigurationException("Missing attribute " + attributeName + " has no value");
        }
    }

    private void addUnresolvedObject(final Class<? extends ConfiguredObject> clazz,
                                     final String attributeName,
                                     final Object attrValue)
    {
        if(attrValue instanceof UUID)
        {
            _unresolvedObjects.add(new IdDependency(clazz, attributeName, (UUID) attrValue));
        }
        else if(attrValue instanceof String)
        {
            String interpolatedValue = AbstractConfiguredObject.interpolate(_parent, (String) attrValue);

            try
            {
                _unresolvedObjects.add(new IdDependency(clazz, attributeName, UUID.fromString(interpolatedValue)));
            }
            catch(IllegalArgumentException e)
            {
                _unresolvedObjects.add(new NameDependency(clazz, attributeName, interpolatedValue));
            }
        }
        else if(!clazz.isInstance(attrValue))
        {
            throw new IllegalArgumentException("Cannot convert from type " + attrValue.getClass() + " to a configured object dependency");
        }
    }


    protected abstract  <X extends ConfiguredObject<X>>  void resolved(ConfiguredObjectDependency<X> dependency, X value);

    @Override
    public Collection<ConfiguredObjectDependency<?>> getUnresolvedDependencies()
    {
        return _unresolvedObjects;
    }

    @Override
    public String toString()
    {
        return getClass().getSimpleName() + "{" +
               "class=" + _clazz.getSimpleName() +
               ", unresolvedObjects=" + _unresolvedObjects +
               '}';
    }

    private abstract class Dependency<X extends ConfiguredObject<X>> implements ConfiguredObjectDependency<X>
    {
        private final Class<X> _clazz;
        private final String _attributeName;

        public Dependency(final Class<X> clazz,
                          final String attributeName)
        {
            _clazz = clazz;
            _attributeName = attributeName;
        }

        @Override
        public final Class<X> getCategoryClass()
        {
            return _clazz;
        }

        @Override
        public final void resolve(final X object)
        {
            _unresolvedObjects.remove(this);
            resolved(this, object);
        }

        public final String getAttributeName()
        {
            return _attributeName;
        }

    }

    private class IdDependency<X extends ConfiguredObject<X>> extends Dependency<X> implements ConfiguredObjectIdDependency<X>
    {
        private final UUID _id;

        public IdDependency(final Class<X> clazz,
                            final String attributeName,
                            final UUID id)
        {
            super(clazz, attributeName);
            _id = id;
        }

        @Override
        public UUID getId()
        {
            return _id;
        }

        @Override
        public String toString()
        {
            return "IdDependency{" + getCategoryClass().getSimpleName() + ", " + _id + " }";
        }
    }

    private class NameDependency<X extends ConfiguredObject<X>> extends Dependency<X> implements ConfiguredObjectNameDependency<X>
    {

        private final String _name;

        public NameDependency(final Class<X> clazz,
                              final String attributeName,
                              final String attrValue)
        {
            super(clazz, attributeName);
            _name = attrValue;
        }

        @Override
        public String getName()
        {
            return _name;
        }

        @Override
        public String toString()
        {
            return "NameDependency{" + getCategoryClass().getSimpleName() + ", \"" + _name + "\" }";
        }
    }
}


