//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.webapp;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.EmptyResource;
import org.eclipse.jetty.util.resource.Resource;




/**
 * MetaData
 *
 * All data associated with the configuration and deployment of a web application.
 */
public class MetaData
{
    private static final Logger LOG = Log.getLogger(MetaData.class);

    public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
    public static final Resource NON_FRAG_RESOURCE = EmptyResource.INSTANCE;

    protected Map<String, OriginInfo> _origins  =new HashMap<String,OriginInfo>();
    protected WebDescriptor _webDefaultsRoot;
    protected WebDescriptor _webXmlRoot;
    protected final List<WebDescriptor> _webOverrideRoots=new ArrayList<WebDescriptor>();
    protected boolean _metaDataComplete;  
    protected final List<DescriptorProcessor> _descriptorProcessors = new ArrayList<DescriptorProcessor>();
    protected final List<FragmentDescriptor> _webFragmentRoots = new ArrayList<FragmentDescriptor>();
    protected final Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
    protected final Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
    protected final Map<Resource, List<DiscoveredAnnotation>> _annotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
    protected final List<Resource> _webInfClasses = new ArrayList<Resource>();
    protected final List<Resource> _webInfJars = new ArrayList<Resource>();
    protected final List<Resource> _orderedContainerResources = new ArrayList<Resource>();
    protected final List<Resource> _orderedWebInfResources = new ArrayList<Resource>();
    protected Ordering _ordering;//can be set to RelativeOrdering by web-default.xml, web.xml, web-override.xml
    protected boolean allowDuplicateFragmentNames = false;





    public static class OriginInfo
    {
        private final String name;
        private final Origin origin;
        private final Descriptor descriptor;
        private final Annotation annotation;
        private final Class<?> annotated;

        public OriginInfo (String n, Annotation a,Class<?> ac)
        {
            name=n;
            origin=Origin.Annotation;
            descriptor=null;
            annotation=a;
            annotated=ac;
        }
        
        public OriginInfo (String n, Descriptor d)
        {
            name = n;
            descriptor = d;
            annotation=null;
            annotated=null;
            if (d == null)
                throw new IllegalArgumentException("No descriptor");
            if (d instanceof FragmentDescriptor)
                origin = Origin.WebFragment;
            else if (d instanceof OverrideDescriptor)
                origin =  Origin.WebOverride;
            else if (d instanceof DefaultsDescriptor)
                origin =  Origin.WebDefaults;
            else
                origin = Origin.WebXml;
        }

        public OriginInfo(String n)
        {
            name = n;
            origin = Origin.API;
            annotation=null;
            descriptor=null;
            annotated=null;
        }

        public String getName()
        {
            return name;
        }

        public Origin getOriginType()
        {
            return origin;
        }

        public Descriptor getDescriptor()
        {
            return descriptor;
        }
        
        public String toString()
        {
            if (descriptor!=null)
                return descriptor.toString();
            if (annotation!=null)
                return "@"+annotation.annotationType().getSimpleName()+" on "+annotated.getName();
            return origin.toString();
        }
    }

    public MetaData ()
    {
    }

    /**
     * Empty ready for reuse
     */
    public void clear ()
    {
        _webDefaultsRoot = null;
        _origins.clear();
        _webXmlRoot = null;
        _webOverrideRoots.clear();
        _metaDataComplete = false;
        _annotations.clear();
        _descriptorProcessors.clear();
        _webFragmentRoots.clear();
        _webFragmentNameMap.clear();
        _webFragmentResourceMap.clear();
        _annotations.clear();
        _webInfJars.clear();
        _orderedWebInfResources.clear();
        _orderedContainerResources.clear();
        _ordering = null;
        allowDuplicateFragmentNames = false;
    }

    public void setDefaults (Resource webDefaults)
    throws Exception
    {
        _webDefaultsRoot =  new DefaultsDescriptor(webDefaults);
        _webDefaultsRoot.parse();
        if (_webDefaultsRoot.isOrdered())
        {
            Ordering ordering = getOrdering();
            if (ordering == null)
               ordering = new Ordering.AbsoluteOrdering(this);

            List<String> order = _webDefaultsRoot.getOrdering();
            for (String s:order)
            {
                if (s.equalsIgnoreCase("others"))
                    ((Ordering.AbsoluteOrdering)ordering).addOthers();
                else
                    ((Ordering.AbsoluteOrdering)ordering).add(s);
            }
            
            //(re)set the ordering to cause webinf jar order to be recalculated
            setOrdering(ordering);
        }
    }

    public void setWebXml (Resource webXml)
    throws Exception
    {
        _webXmlRoot = new WebDescriptor(webXml);
        _webXmlRoot.parse();
        _metaDataComplete=_webXmlRoot.getMetaDataComplete() == MetaDataComplete.True;

        if (_webXmlRoot.isOrdered())
        {
            Ordering ordering = getOrdering();
            if (ordering == null)
                ordering = new Ordering.AbsoluteOrdering(this);

            List<String> order = _webXmlRoot.getOrdering();
            for (String s:order)
            {
                if (s.equalsIgnoreCase("others"))
                    ((Ordering.AbsoluteOrdering)ordering).addOthers();
                else
                    ((Ordering.AbsoluteOrdering)ordering).add(s);
            }
            
            //(re)set the ordering to cause webinf jar order to be recalculated
            setOrdering(ordering);
        }
    }

    public void addOverride (Resource override)
    throws Exception
    {
        OverrideDescriptor webOverrideRoot = new OverrideDescriptor(override);
        webOverrideRoot.setValidating(false);
        webOverrideRoot.parse();

        switch(webOverrideRoot.getMetaDataComplete())
        {
            case True:
                _metaDataComplete=true;
                break;
            case False:
                _metaDataComplete=false;
                break;
            case NotSet:
                break;
        }

        if (webOverrideRoot.isOrdered())
        {
            Ordering ordering = getOrdering();
            
            if (ordering == null)
               ordering = new Ordering.AbsoluteOrdering(this);

            List<String> order = webOverrideRoot.getOrdering();
            for (String s:order)
            {
                if (s.equalsIgnoreCase("others"))
                    ((Ordering.AbsoluteOrdering)ordering).addOthers();
                else
                    ((Ordering.AbsoluteOrdering)ordering).add(s);
            }
            
            //set or reset the ordering to cause the webinf jar ordering to be recomputed
            setOrdering(ordering);
        }
        _webOverrideRoots.add(webOverrideRoot);
    }


    /**
     * Add a web-fragment.xml
     *
     * @param jarResource the jar the fragment is contained in
     * @param xmlResource the resource representing the xml file
     * @throws Exception
     */
    public void addFragment (Resource jarResource, Resource xmlResource)
    throws Exception
    {
        if (_metaDataComplete)
            return; //do not process anything else if web.xml/web-override.xml set metadata-complete

        //Metadata-complete is not set, or there is no web.xml
        FragmentDescriptor descriptor = new FragmentDescriptor(xmlResource);
        _webFragmentResourceMap.put(jarResource, descriptor);
        _webFragmentRoots.add(descriptor);

        descriptor.parse();

        if (descriptor.getName() != null)
        {
            Descriptor existing = _webFragmentNameMap.get(descriptor.getName());
            if (existing != null && !isAllowDuplicateFragmentNames())
            {
                throw new IllegalStateException("Duplicate fragment name: "+descriptor.getName()+" for "+existing.getResource()+" and "+descriptor.getResource());
            }
            else
                _webFragmentNameMap.put(descriptor.getName(), descriptor);
        }


        //only accept an ordering from the fragment if there is no ordering already established
        if (_ordering == null && descriptor.isOrdered())
        {
            setOrdering(new Ordering.RelativeOrdering(this));
            return;
        }
        
        //recompute the ordering with the new fragment name
        orderFragments();
    }

    /**
     * Annotations not associated with a WEB-INF/lib fragment jar.
     * These are from WEB-INF/classes or the ??container path??
     * @param annotations
     */
    public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
    {
        if (annotations == null)
            return;
        for (DiscoveredAnnotation a:annotations)
        {
            addDiscoveredAnnotation(a);       
        }
    }

    
    /**
     * Add an annotation that has been discovered on a class, method or field within a resource
     * eg a jar or dir.
     * 
     * This method is synchronized as it is anticipated that it may be called by many threads
     * during the annotation scanning phase.
     * 
     * @param annotation
     */
    public synchronized void addDiscoveredAnnotation (DiscoveredAnnotation annotation)
    {
        if (annotation == null)
            return;
        
        //if no resource associated with an annotation or the resource is not one of the WEB-INF/lib jars,
        //map it to empty resource
        Resource resource = annotation.getResource();
        if (resource == null ||  !_webInfJars.contains(resource))
            resource = EmptyResource.INSTANCE;

        List<DiscoveredAnnotation> list = _annotations.get(resource);
        if (list == null)
        {
            list = new ArrayList<DiscoveredAnnotation>();
            _annotations.put(resource, list);
        }
        list.add(annotation);           
    }


    public void addDescriptorProcessor(DescriptorProcessor p)
    {
        _descriptorProcessors.add(p);
    }
    
    public void removeDescriptorProcessor(DescriptorProcessor p)
    {
        _descriptorProcessors.remove(p);
    }

    
    public void orderFragments ()
    {
        _orderedWebInfResources.clear();
        if (getOrdering() != null)
            _orderedWebInfResources.addAll(getOrdering().order(_webInfJars));
    }


    /**
     * Resolve all servlet/filter/listener metadata from all sources: descriptors and annotations.
     *
     */
    public void resolve (WebAppContext context)
    throws Exception
    {
        LOG.debug("metadata resolve {}",context);

        //Ensure origins is fresh
        _origins.clear();

        // Set the ordered lib attribute
        List<Resource> orderedWebInfJars = null;
        if (getOrdering() != null)
        {
            orderedWebInfJars = getOrderedWebInfJars();
            List<String> orderedLibs = new ArrayList<String>();
            for (Resource webInfJar:orderedWebInfJars)
            {
                //get just the name of the jar file
                String fullname = webInfJar.getName();
                int i = fullname.indexOf(".jar");
                int j = fullname.lastIndexOf("/", i);
                orderedLibs.add(fullname.substring(j+1,i+4));
            }
            context.setAttribute(ServletContext.ORDERED_LIBS, orderedLibs);
        }

        // set the webxml version
        if (_webXmlRoot != null)
        {
            context.getServletContext().setEffectiveMajorVersion(_webXmlRoot.getMajorVersion());
            context.getServletContext().setEffectiveMinorVersion(_webXmlRoot.getMinorVersion());
        }

        for (DescriptorProcessor p:_descriptorProcessors)
        {
            p.process(context,getWebDefault());
            p.process(context,getWebXml());
            for (WebDescriptor wd : getOverrideWebs())
            {
                LOG.debug("process {} {}",context,wd);
                p.process(context,wd);
            }
        }

        //get an apply the annotations that are not associated with a fragment (and hence for
        //which no ordering applies
        List<DiscoveredAnnotation> nonFragAnnotations = _annotations.get(NON_FRAG_RESOURCE);
        if (nonFragAnnotations != null)
        {
            for (DiscoveredAnnotation a:nonFragAnnotations)
            {
                LOG.debug("apply {}",a);
                a.apply();
            }
        }
      
        //apply the annotations that are associated with a fragment, according to the 
        //established ordering
        List<Resource> resources = null;
        
        if (getOrdering() != null)
            resources = orderedWebInfJars;
        else
            resources = getWebInfJars();
        
        for (Resource r:resources)
        {
            FragmentDescriptor fd = _webFragmentResourceMap.get(r);
            if (fd != null)
            {
                for (DescriptorProcessor p:_descriptorProcessors)
                {
                    LOG.debug("process {} {}",context,fd);
                    p.process(context,fd);
                }
            }

            List<DiscoveredAnnotation> fragAnnotations = _annotations.get(r);
            if (fragAnnotations != null)
            {
                for (DiscoveredAnnotation a:fragAnnotations)
                {
                    LOG.debug("apply {}",a);
                    a.apply();
                }
            }
        }

    }

    public boolean isDistributable ()
    {
        boolean distributable = (
                (_webDefaultsRoot != null && _webDefaultsRoot.isDistributable())
                || (_webXmlRoot != null && _webXmlRoot.isDistributable()));

        for (WebDescriptor d : _webOverrideRoots)
            distributable&=d.isDistributable();

        if (getOrdering() != null)
        {
            List<Resource> orderedResources = getOrderedWebInfJars();
            for (Resource r: orderedResources)
            {
                FragmentDescriptor d = _webFragmentResourceMap.get(r);
                if (d!=null)
                    distributable = distributable && d.isDistributable();
            }
        }
        return distributable;
    }


    public WebDescriptor getWebXml ()
    {
        return _webXmlRoot;
    }

    public List<WebDescriptor> getOverrideWebs ()
    {
        return _webOverrideRoots;
    }

    public WebDescriptor getWebDefault ()
    {
        return _webDefaultsRoot;
    }

    public List<FragmentDescriptor> getFragments ()
    {
        return _webFragmentRoots;
    }

    public List<Resource> getOrderedWebInfJars()
    {
        return _orderedWebInfResources;
    }

    public List<FragmentDescriptor> getOrderedFragments ()
    {
        List<FragmentDescriptor> list = new ArrayList<FragmentDescriptor>();
        if (getOrdering() == null)
            return list;

        for (Resource r:getOrderedWebInfJars())
        {
            FragmentDescriptor fd = _webFragmentResourceMap.get(r);
            if (fd != null)
                list.add(fd);
        }
        return list;
    }

    public Ordering getOrdering()
    {
        return _ordering;
    }

    public void setOrdering (Ordering o)
    {    
        _ordering = o;
        orderFragments();
    }

    public FragmentDescriptor getFragment (Resource jar)
    {
        return _webFragmentResourceMap.get(jar);
    }

    public FragmentDescriptor getFragment(String name)
    {
        return _webFragmentNameMap.get(name);
    }

    public Resource getJarForFragment (String name)
    {
        FragmentDescriptor f = getFragment(name);
        if (f == null)
            return null;

        Resource jar = null;
        for (Resource r: _webFragmentResourceMap.keySet())
        {
            if (_webFragmentResourceMap.get(r).equals(f))
                jar = r;
        }
        return jar;
    }

    public Map<String,FragmentDescriptor> getNamedFragments ()
    {
        return Collections.unmodifiableMap(_webFragmentNameMap);
    }


    public Origin getOrigin (String name)
    {
        OriginInfo x =  _origins.get(name);
        if (x == null)
            return Origin.NotSet;

        return x.getOriginType();
    }

    public OriginInfo getOriginInfo (String name)
    {
        OriginInfo x =  _origins.get(name);
        if (x == null)
            return null;

        return x;
    }

    public Descriptor getOriginDescriptor (String name)
    {
        OriginInfo o = _origins.get(name);
        if (o == null)
            return null;
        return o.getDescriptor();
    }

    public void setOrigin (String name, Descriptor d)
    {
        OriginInfo x = new OriginInfo (name, d);
        _origins.put(name, x);
    }

    public void setOrigin (String name, Annotation annotation, Class<?> annotated)
    {
        if (name == null)
            return;

        OriginInfo x = new OriginInfo (name, annotation, annotated);
        _origins.put(name, x);
    }
    
    public void setOriginAPI(String name)
    {
        if (name == null)
            return;
       
        OriginInfo x = new OriginInfo (name);
        _origins.put(name, x);
    }

    public boolean isMetaDataComplete()
    {
        return _metaDataComplete;
    }


    public void addWebInfJar(Resource newResource)
    {
        _webInfJars.add(newResource);
    }

    public List<Resource> getWebInfJars()
    {
        return Collections.unmodifiableList(_webInfJars);
    }

    public List<Resource> getContainerResources()
    {
        return _orderedContainerResources;
    }

    public void addContainerResource(Resource jar)
    {
        _orderedContainerResources.add(jar);
    }
    
    public void setWebInfClassesDirs (List<Resource> dirs)
    {
        _webInfClasses.addAll(dirs);
    }
    
    public List<Resource> getWebInfClassesDirs ()
    {
        return _webInfClasses;
    }
    
    public boolean isAllowDuplicateFragmentNames()
    {
        return allowDuplicateFragmentNames;
    }

    public void setAllowDuplicateFragmentNames(boolean allowDuplicateFragmentNames)
    {
        this.allowDuplicateFragmentNames = allowDuplicateFragmentNames;
    }

    public Map<String,OriginInfo> getOrigins()
    {
        return Collections.unmodifiableMap(_origins);
    }
}
