//
//  ========================================================================
//  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.quickstart;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

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

/**
 * Normalize Attribute to String.
 * <p>
 * Replaces and expands:
 * <ul>
 * <li>${WAR}</li>
 * <li>${WAR.path}</li>
 * <li>${WAR.uri}</li>
 * <li>${jetty.base}</li>
 * <li>${jetty.base.uri}</li>
 * <li>${jetty.home}</li>
 * <li>${jetty.home.uri}</li>
 * <li>${user.home}</li>
 * <li>${user.home.uri}</li>
 * <li>${user.dir}</li>
 * <li>${user.dir.uri}</li>
 * </ul>
 */
public class AttributeNormalizer
{
    private static final Logger LOG = Log.getLogger(AttributeNormalizer.class);
    private static final Pattern __propertyPattern = Pattern.compile("(?<=[^$]|^)\\$\\{([^}]*)\\}");
    
    private static class Attribute
    {
        final String key;
        final String value;
        final int weight;
        
        public Attribute(String key, String value, int weight)
        {
            this.key = key;
            this.value = value;
            this.weight = weight;
        }
    }

    private static URI toCanonicalURI(URI uri)
    {
        uri = uri.normalize();
        String ascii = uri.toASCIIString();
        if (ascii.endsWith("/"))
        {
            try
            {
                uri = new URI(ascii.substring(0,ascii.length()-1));
            }
            catch(URISyntaxException e)
            {
                throw new IllegalArgumentException(e);
            }
        }
        return uri;
    }
    
    private static Path toCanonicalPath(String path)
    {
        if (path == null)
            return null;
        if (path.length()>1 && path.endsWith("/"))
            path = path.substring(0,path.length()-1);
        return toCanonicalPath(FileSystems.getDefault().getPath(path));
    }
    
    private static Path toCanonicalPath(Path path)
    {
        if (path == null)
        {
            return null;
        }
        if (Files.exists(path))
        {
            try
            {
                return path.toRealPath();
            }
            catch (IOException e)
            {
                throw new IllegalArgumentException(e);
            }
        }
        return path.toAbsolutePath();
    }
    
    private static class PathAttribute extends Attribute
    {
        public final Path path;
        
        public PathAttribute(String key, Path path, int weight)
        {
            super(key,path.toString(),weight);
            this.path = path;
        }
        
        @Override
        public String toString()
        {
            return String.format("PathAttribute[%s=>%s]",key,path);
        }
    }
    
    private static class URIAttribute extends Attribute
    {
        public final URI uri;
        
        public URIAttribute(String key, URI uri, int weight)
        {
            super(key,uri.toASCIIString(),weight);
            this.uri = uri;
        }
        
        @Override
        public String toString()
        {
            return String.format("URIAttribute[%s=>%s]",key,uri);
        }
    }
    
    private static Comparator<Attribute> attrComparator = new Comparator<Attribute>()
    {
        @Override
        public int compare(Attribute o1, Attribute o2)
        {
            if( (o1.value == null) && (o2.value != null) )
            {
                return -1;
            }
            
            if( (o1.value != null) && (o2.value == null) )
            {
                return 1;
            }
            
            if( (o1.value == null) && (o2.value == null) )
            {
                return 0;
            }
            
            // Different lengths?
            int diff = o2.value.length() - o1.value.length();
            if(diff != 0)
            {
                return diff;
            }
            
            // Different names?
            diff = o2.value.compareTo(o1.value);
            if(diff != 0)
            {
                return diff;
            }
            
            // The paths are the same, base now on weight
            return o2.weight - o1.weight;
        }
    };

    private static void add(List<PathAttribute>paths,List<URIAttribute> uris,String key,int weight)
    {
        String value = System.getProperty(key);
        if (value!=null)
        {
            Path path = toCanonicalPath(value);
            paths.add(new PathAttribute(key,path,weight));
            uris.add(new URIAttribute(key+".uri",toCanonicalURI(path.toUri()),weight));
        }
    }

    private URI warURI;
    private Map<String,Attribute> attributes = new HashMap<>();
    private List<PathAttribute> paths = new ArrayList<>();
    private List<URIAttribute> uris = new ArrayList<>();
    
    public AttributeNormalizer(Resource baseResource)
    {
        if (baseResource==null)
            throw new IllegalArgumentException("No base resource!");
            
        warURI = toCanonicalURI(baseResource.getURI());
        if (!warURI.isAbsolute())
            throw new IllegalArgumentException("WAR URI is not absolute: " + warURI);
        
        add(paths,uris,"jetty.base",9);
        add(paths,uris,"jetty.home",8);
        add(paths,uris,"user.home",7);
        add(paths,uris,"user.dir",6);

        if (warURI.getScheme().equalsIgnoreCase("file"))
            paths.add(new PathAttribute("WAR.path",toCanonicalPath(new File(warURI).toString()),10));
        uris.add(new URIAttribute("WAR.uri", warURI,9)); // preferred encoding
        uris.add(new URIAttribute("WAR", warURI,8)); // legacy encoding
        
        Collections.sort(paths,attrComparator);
        Collections.sort(uris,attrComparator);
        
        Stream.concat(paths.stream(),uris.stream()).forEach(a->attributes.put(a.key,a));        
        
        if (LOG.isDebugEnabled())
        {
            for (Attribute attr : attributes.values())
            {
                LOG.debug(attr.toString());
            }
        }
    }

    /**
     * Normalize a URI, URL, or File reference by replacing known attributes with ${key} attributes.
     *
     * @param o the object to normalize into a string
     * @return the string representation of the object, with expansion keys.
     */
    public String normalize(Object o)
    {
        try
        {
            // Find a URI
            URI uri = null;
            Path path = null;
            if (o instanceof URI)
                uri = toCanonicalURI(((URI)o));
            else if (o instanceof Resource)
                uri = toCanonicalURI(((Resource)o).getURI());
            else if (o instanceof URL)
                uri = toCanonicalURI(((URL)o).toURI());
            else if (o instanceof File)
                path = ((File)o).getAbsoluteFile().getCanonicalFile().toPath();
            else if (o instanceof Path)
                path = (Path)o;
            else
            {
                String s = o.toString();
                try
                {
                    uri = new URI(s);
                    if (uri.getScheme() == null)
                    {
                        // Unknown scheme? not relevant to normalize
                        return s;
                    }
                }
                catch(URISyntaxException e)
                {
                    // This path occurs for many reasons, but most common is when this
                    // is executed on MS Windows, on a string like "D:\jetty"
                    // and the new URI() fails for
                    // java.net.URISyntaxException: Illegal character in opaque part at index 2: D:\jetty
                    return s;
                }
            }

            if (uri!=null)
            {
                if ("jar".equalsIgnoreCase(uri.getScheme()))
                {
                    String raw = uri.getRawSchemeSpecificPart();
                    int bang = raw.indexOf("!/");
                    String normal = normalize(raw.substring(0,bang));
                    String suffix = raw.substring(bang);
                    return "jar:" + normal + suffix;
                }
                else
                {
                    if(uri.isAbsolute())
                    {
                        return normalizeUri(uri);
                    }
                }
            }
            else if (path!=null)
                return normalizePath(path);
        }
        catch (Exception e)
        {
            LOG.warn(e);
        }
        return String.valueOf(o);
    }
    
    protected String normalizeUri(URI uri)
    {
        for (URIAttribute a : uris)
        {
            try
            {
                if (uri.compareTo(a.uri)==0)
                    return String.format("${%s}",a.key);

                if (!a.uri.getScheme().equalsIgnoreCase(uri.getScheme()))
                    continue;
                if (a.uri.getHost()==null && uri.getHost()!=null)
                    continue;
                if (a.uri.getHost()!=null && !a.uri.getHost().equals(uri.getHost()))
                    continue;

                if (a.uri.getPath().equals(uri.getPath()))
                    return a.value;

                if (!uri.getPath().startsWith(a.uri.getPath()))
                    continue;

                String s = uri.getPath().substring(a.uri.getPath().length());

                if (s.charAt(0)!='/')
                    continue;

                return String.format("${%s}%s",a.key,new URI(s).toASCIIString());
            }
            catch(URISyntaxException e)
            {
                LOG.ignore(e);
            }
        }
        return uri.toASCIIString();
    }

    protected String normalizePath(Path path)
    {
        for (PathAttribute a : paths)
        {
            try
            {
                if (path.equals(a.path) || Files.isSameFile(path,a.path))
                    return String.format("${%s}",a.key);
            }
            catch (IOException ignore)
            {
                LOG.ignore(ignore);
            }

            if (path.startsWith(a.path))
                return String.format("${%s}%c%s",a.key,File.separatorChar,a.path.relativize(path).toString());
        }

        return path.toString();
    }

    public String expand(String str)
    {
        return expand(str,new Stack<String>());
    }

    public String expand(String str, Stack<String> seenStack)
    {
        if (str == null)
        {
            return str;
        }

        if (str.indexOf("${") < 0)
        {
            // Contains no potential expressions.
            return str;
        }

        Matcher mat = __propertyPattern.matcher(str);
        StringBuilder expanded = new StringBuilder();
        int offset = 0;
        String property;
        String value;

        while (mat.find(offset))
        {
            property = mat.group(1);

            // Loop detection
            if (seenStack.contains(property))
            {
                StringBuilder err = new StringBuilder();
                err.append("Property expansion loop detected: ");
                int idx = seenStack.lastIndexOf(property);
                for (int i = idx; i < seenStack.size(); i++)
                {
                    err.append(seenStack.get(i));
                    err.append(" -> ");
                }
                err.append(property);
                throw new RuntimeException(err.toString());
            }

            seenStack.push(property);

            // find property name
            expanded.append(str.subSequence(offset,mat.start()));
            // get property value
            value = getString(property);
            if (value == null)
            {
                if(LOG.isDebugEnabled())
                    LOG.debug("Unable to expand: {}",property);
                expanded.append(mat.group());
            }
            else
            {
                // recursively expand
                value = expand(value,seenStack);
                expanded.append(value);
            }
            // update offset
            offset = mat.end();
        }

        // leftover
        expanded.append(str.substring(offset));

        // special case for "$$"
        if (expanded.indexOf("$$") >= 0)
        {
            return expanded.toString().replaceAll("\\$\\$","\\$");
        }

        return expanded.toString();
    }

    private String getString(String property)
    {
        if(property==null)
        {
            return null;
        }

        Attribute a = attributes.get(property);
        if (a!=null)
            return a.value;

        // Use system properties next
        return System.getProperty(property);
    }
}
