/*
 * 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.myfaces.test.mock.resource;

import org.apache.myfaces.test.mock.MockServletContext;

import javax.faces.FacesException;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.*;
import java.util.regex.Pattern;

/**
 * <p>Mock implementation of <code>ResourceHandler</code>.</p>
 * <p/>
 * $Id$
 * 
 * @since 2.0
 */
public class MockResourceHandler extends ResourceHandler
{

    private static final String IS_RESOURCE_REQUEST = "org.apache.myfaces.IS_RESOURCE_REQUEST";

    /**
     * It checks version like this: /1/, /1_0/, /1_0_0/, /100_100/
     * <p/>
     * Used on getLibraryVersion to filter resource directories
     */
    protected static Pattern VERSION_CHECKER = Pattern.compile("/\\p{Digit}+(_\\p{Digit}*)*/");

    /**
     * It checks version like this: /1.js, /1_0.js, /1_0_0.js, /100_100.js
     * <p/>
     * Used on getResourceVersion to filter resources
     */
    protected static Pattern RESOURCE_VERSION_CHECKER = Pattern.compile("/\\p{Digit}+(_\\p{Digit}*)*\\..*");

    private File _documentRoot;

    /**
     * @param documentRoot parent folder of resource directories. Must not be <code>null</code>
     */
    public MockResourceHandler(File documentRoot)
    {
        if (documentRoot == null) {
            throw new NullPointerException("documentRoot must not be null");
        }

        _documentRoot = documentRoot;

        ((MockServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext())
            .setDocumentRoot(_documentRoot);
    }

    @Override
    public Resource createResource(String resourceName)
    {
        return createResource(resourceName, null);
    }

    @Override
    public Resource createResource(String resourceName, String libraryName)
    {
        return createResource(resourceName, libraryName, null);
    }

    @Override
    public Resource createResource(String resourceName, String libraryName, String contentType)
    {
        String prefix = getLocalePrefixForLocateResource();
        String libraryVersion = getLibraryVersion(prefix + "/" + libraryName);

        String pathToResource;
        if (null != libraryVersion) {
            pathToResource = prefix + '/'
                + libraryName + '/' + libraryVersion + '/'
                + resourceName;
        }
        else {
            pathToResource = prefix + '/'
                + libraryName + '/' + resourceName;
        }

        return new MockResource(prefix, libraryName, libraryVersion, resourceName, getResourceVersion(pathToResource), _documentRoot);
    }

    @Override
    public String getRendererTypeForResourceName(String resourceName)
    {
        if (resourceName.endsWith(".js")) {
            return "javax.faces.resource.Script";
        }
        else if (resourceName.endsWith(".css")) {
            return "javax.faces.resource.Stylesheet";
        }
        return null;
    }

    @Override
    public void handleResourceRequest(FacesContext context) throws IOException
    {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isResourceRequest(FacesContext facesContext)
    {
        // Since this method could be called many times we save it
        //on request map so the first time is calculated it remains
        //alive until the end of the request
        Boolean value = (Boolean) facesContext.getExternalContext()
            .getRequestMap().get(IS_RESOURCE_REQUEST);

        if (value != null && value.booleanValue()) {
            //return the saved value
            return value.booleanValue();
        }
        else {
            // assuming that we don't have servlet mapping
            String resourceBasePath = facesContext.getExternalContext().getRequestPathInfo();

            if (resourceBasePath != null
                && resourceBasePath
                .startsWith(ResourceHandler.RESOURCE_IDENTIFIER)) {
                facesContext.getExternalContext().getRequestMap().put(
                    IS_RESOURCE_REQUEST, Boolean.TRUE);
                return true;
            }
            else {
                facesContext.getExternalContext().getRequestMap().put(
                    IS_RESOURCE_REQUEST, Boolean.FALSE);
                return false;
            }
        }
    }

    @Override
    public boolean libraryExists(String libraryName)
    {
        String localePrefix = getLocalePrefixForLocateResource();

        String pathToLib;

        if (localePrefix != null) {
            //Check with locale
            pathToLib = localePrefix + '/' + libraryName;
        }
        else {
            pathToLib = libraryName;
        }

        try {
            URL url = FacesContext.getCurrentInstance().getExternalContext().getResource("/" + pathToLib);
            return (url != null);
        }
        catch (MalformedURLException e) {
            return false;
        }
    }

    protected String getLocalePrefixForLocateResource()
    {
        String localePrefix = null;
        FacesContext context = FacesContext.getCurrentInstance();

        String bundleName = context.getApplication().getMessageBundle();

        if (null != bundleName) {
            Locale locale = context.getApplication().getViewHandler()
                .calculateLocale(context);

            ResourceBundle bundle = ResourceBundle
                .getBundle(bundleName, locale, getContextClassLoader());

            if (bundle != null) {
                try {
                    localePrefix = bundle.getString(ResourceHandler.LOCALE_PREFIX);
                }
                catch (MissingResourceException e) {
                    // Ignore it and return null
                }
            }
        }
        return localePrefix;
    }

    /**
     * Gets the ClassLoader associated with the current thread.  Includes a check for priviledges
     * against java2 security to ensure no security related exceptions are encountered.
     *
     * @return ClassLoader
     * @since 3.0.6
     */
    private static ClassLoader getContextClassLoader()
    {
        if (System.getSecurityManager() != null) {
            try {
                ClassLoader cl = AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>()
                {
                    public ClassLoader run() throws PrivilegedActionException
                    {
                        return Thread.currentThread().getContextClassLoader();
                    }
                });
                return cl;
            }
            catch (PrivilegedActionException pae) {
                throw new FacesException(pae);
            }
        }
        else {
            return Thread.currentThread().getContextClassLoader();
        }
    }

    private String getLibraryVersion(String path)
    {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();

        String libraryVersion = null;
        Set<String> libraryPaths = context.getResourcePaths("/" + path);
        if (null != libraryPaths && !libraryPaths.isEmpty()) {
            // Look in the libraryPaths for versioned libraries.
            // If one or more versioned libraries are found, take
            // the one with the "highest" version number as the value
            // of libraryVersion. If no versioned libraries
            // are found, let libraryVersion remain null.

            for (String libraryPath : libraryPaths) {
                String version = libraryPath.substring(path.length());

                if (VERSION_CHECKER.matcher(version).matches()) {
                    version = version.substring(1, version.length() - 1);
                    if (libraryVersion == null) {
                        libraryVersion = version;
                    }
                    else if (compareVersion(libraryVersion, version) < 0) {
                        libraryVersion = version;
                    }
                }
            }
        }
        return libraryVersion;
    }

    private int compareVersion(String s1, String s2)
    {
        int n1 = 0;
        int n2 = 0;
        String o1 = s1;
        String o2 = s2;

        boolean p1 = true;
        boolean p2 = true;

        while (n1 == n2 && (p1 || p2)) {
            int i1 = o1.indexOf('_');
            int i2 = o2.indexOf('_');
            if (i1 < 0) {
                if (o1.length() > 0) {
                    p1 = false;
                    n1 = Integer.valueOf(o1);
                    o1 = "";
                }
                else {
                    p1 = false;
                    n1 = 0;
                }
            }
            else {
                n1 = Integer.valueOf(o1.substring(0, i1));
                o1 = o1.substring(i1 + 1);
            }
            if (i2 < 0) {
                if (o2.length() > 0) {
                    p2 = false;
                    n2 = Integer.valueOf(o2);
                    o2 = "";
                }
                else {
                    p2 = false;
                    n2 = 0;
                }
            }
            else {
                n2 = Integer.valueOf(o2.substring(0, i2));
                o2 = o2.substring(i2 + 1);
            }
        }

        if (n1 == n2) {
            return s1.length() - s2.length();
        }
        return n1 - n2;
    }

    private String getResourceVersion(String path)
    {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        String resourceVersion = null;
        Set<String> resourcePaths = context.getResourcePaths("/" + path);

        if (null != resourcePaths && !resourcePaths.isEmpty()) {
            // resourceVersion = // execute the comment
            // Look in the resourcePaths for versioned resources.
            // If one or more versioned resources are found, take
            // the one with the "highest" version number as the value
            // of resourceVersion. If no versioned libraries
            // are found, let resourceVersion remain null.
            for (String resourcePath : resourcePaths) {
                String version = resourcePath.substring(path.length());

                if (RESOURCE_VERSION_CHECKER.matcher(version).matches()) {
                    version = version.substring(1, version.lastIndexOf('.'));
                    if (resourceVersion == null) {
                        resourceVersion = version;
                    }
                    else if (compareVersion(resourceVersion, version) < 0) {
                        resourceVersion = version;
                    }
                }
            }
        }
        return resourceVersion;
    }
}
