package com.metaweb.lessen.tokenizers;

import com.metaweb.lessen.tokens.Token;
import com.metaweb.lessen.tokens.UriToken;
import com.metaweb.lessen.tokens.Token.Type;


public class UrlRewritingTokenizer implements Tokenizer {
    final protected Tokenizer   _tokenizer;
    final protected String      _relativePath;
    final protected String[]    _segments;
    protected Token             _token;
    
    /**
     * relativePath specifies how to get from the output CSS's URL to
     * the input CSS's URL. For example, say the input CSS is served at
     * 
     *   some-path/modules/foo/styles/detail-page.css
     * 
     * which is to be bundled with other CSS files to produce a CSS
     * bundle to be served at
     * 
     *   some-path/bundles/foo.css
     *   
     * then the relative path is
     * 
     *   ../modules/foo/styles/
     *   
     * because from foo.css, we need to go up one directory level to
     * some-path, and then down modules/foo/styles/ to get to
     * detail-page.css. If detail-page.css contains
     * 
     *   url(../images/watermark.png)
     * 
     * then it'll be resolved to
     * 
     *   url(../modules/foo/images/watermark.png)
     *   
     * in foo.css so that foo.css effectively references the same image.
     * 
     * @param tokenizer
     * @param relativePath
     */
    public UrlRewritingTokenizer(Tokenizer tokenizer, String relativePath) {
        _tokenizer = tokenizer;
        _relativePath = relativePath;
        
        if (relativePath.endsWith("/")) {
            relativePath = relativePath.substring(0, relativePath.length() - 1);
        }
        _segments = _relativePath.split("/");
        
        _token = _tokenizer.getToken();
        resolve();
    }
    
    @Override
    public Token getToken() {
        return _token;
    }

    @Override
    public void next() {
        _tokenizer.next();
        _token = _tokenizer.getToken();
        resolve();
    }
    
    protected void resolve() {
        if (_token != null && _token.type == Type.Uri) {
            UriToken t = (UriToken) _token;
            if (t.prefix.equals("url")) {
                String url = t.unquotedText;
                if (url.indexOf("://") < 0 && !url.startsWith("/")) { // not absolute URLs
                    int lastSegment = _segments.length;
                    while (url.length() > 0) {
                        if (url.startsWith("./")) {
                            url = url.substring(2);
                        } else if (url.startsWith("../")) {
                            url = url.substring(3);
                            lastSegment--;
                        } else {
                            break;
                        }
                    }
                    
                    StringBuffer sb = new StringBuffer();
                    if (lastSegment > 0) {
                        for (int i = 0; i < lastSegment; i++) {
                            sb.append(_segments[i]);
                            sb.append('/');
                        }
                    } else {
                        while (lastSegment < 0) {
                            sb.append("../");
                            lastSegment++;
                        }
                    }
                    
                    String url2 = sb.toString() + url;
                    String text = t.prefix + "(\"" + url2 + "\")";
                    
                    _token = new UriToken(
                        t.start,
                        t.end,
                        text,
                        t.prefix,
                        url2
                    );
                }
            }
        }
    }
}
