/*
 * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (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.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.templating;


import com.arsdigita.web.URL;
import com.arsdigita.web.Web;
import com.arsdigita.util.StringUtils;

import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.sitenode.SiteNodeRequestContext;
import com.arsdigita.kernel.SiteNode;
import com.arsdigita.util.Assert;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;


/**
 * Generates a set of pattern values based on the URL path
 * info for the current request. Slashes in the request are
 * translated into hyphens; the file extension is stripped;
 * the any 'index' is removed, except for the top level.
 *
 * So some examples:
 * 
 * /content/admin/item.jsp -> { "admin-item", "admin", "index" }
 * /content/admin/index.jsp -> { "admin", "index" }
 * /content/admin/ -> { "admin", "index" }
 * /content/index.jsp -> { "index" }
 * /content/ -> { "index" }
 */
public class URLPatternGenerator implements PatternGenerator {

    private static final Logger s_log = 
         Logger.getLogger(URLPatternGenerator.class);

    private static final String DEFAULT_URL_MATCH = "index";

    public String[] generateValues(String key,
                                   HttpServletRequest req) {
        String path = getPath();

        if (s_log.isDebugEnabled()) {
            s_log.debug("Substituting values for url " + path);
        }
        
        // Check for a file extension & strip it.
        int dotIndex = path.lastIndexOf(".");
        int slashIndex = path.lastIndexOf("/");
        if (dotIndex > -1
            && dotIndex > slashIndex) {
            path = path.substring(0, dotIndex);
        }
        
        // Strip '/index' if any
        if (path != null &&
            path.endsWith("/" + DEFAULT_URL_MATCH)) {
            path = path.substring(0, path.length() - 
                                  DEFAULT_URL_MATCH.length());
        }
        
        // Now strip trailing & leading slash
        if (path != null &&
            path.startsWith("/")) {
            path = path.substring(1);
        }
        if (path != null &&
            path.endsWith("/")) {
            path = path.substring(0, path.length()-1);
        }

        if (path == null) {
            path = "";
        }

        if (s_log.isDebugEnabled()) {
            s_log.debug("Normalized path is '" + path + "'");
        }
        String[] bits = StringUtils.split(path, '/');
        if (s_log.isDebugEnabled()) {
            for (int i = 0 ; i < bits.length ; i++) {
                s_log.debug(" -> '" + bits[i] + "'");
            }
        }
        
        // Now we've cut off the file extension, it's time to do the
        // funky concatenation trick. 
        for (int i = 1; i < bits.length; i++) {
            bits[i] = bits[i-1] + "-" + bits[i];
        }
                
        // Now we have to reverse it, so matching goes from most specific
        // to most general & add in the default 'index' match
        
        String[] reverseBits = new String[bits.length+1];
        
        for ( int i = bits.length - 1, j = 0; i > -1; i--,j++ ) {
            reverseBits[j] = bits [i];
        }
        reverseBits[reverseBits.length-1] = DEFAULT_URL_MATCH;

        if (s_log.isDebugEnabled()) {
            s_log.debug("After concatenation & reversing");
            for (int i = 0 ; i < reverseBits.length ; i++) {
                s_log.debug(" -> '" + reverseBits[i] + "'");
            }
        }
        
        return reverseBits;
    }

    
    private String getPath() {
        String base = getBasePath();
        String url = Web.getContext().getRequestURL().getPathInfo();

        if (s_log.isDebugEnabled()) {
            s_log.debug("Base is " + base + " url is " + url);
        }
        
        Assert.truth(url.startsWith(base), "URL " + url + " starts with " + base);
        
        return url.substring(base.length()-1);
    }
    
    // XXX fix me, why vcan't we get this from Web.getConfig.getRequestURL
    private String getBasePath() {
        SiteNodeRequestContext ctx = (SiteNodeRequestContext)
            DispatcherHelper.getRequestContext(Web.getRequest());
        
        SiteNode node = ctx.getSiteNode();
        Assert.exists(node, SiteNode.class);
        return node.getURL();
    }

}
