/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 * 
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.masterfs;

import org.openide.util.Utilities;

import java.util.WeakHashMap;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.File;

/**
 * Encapsulates independent view of hierarchical resource path.
 * Implemented as immutable.
 *
 * @author Radek Matous
 */
final class ResourcePath {
    private final String resourcePath;

    private static final ResourcePath root = new ResourcePath("/");

    ResourcePath(final String resourcePath) {
        assert resourcePath != null;
        this.resourcePath = getNormalizedPath(resourcePath);
        assert this.resourcePath.length() > 0 && this.resourcePath.charAt(0) == '/';
    }

    static ResourcePath getRoot() {
        return root;
    }

    boolean isRoot() {
        return (getParent() == null) ? true : false;
    }

    File getFile () {         
        // XXX this is ugly and fragile; revisit
        if ((Utilities.isWindows () || (Utilities.getOperatingSystem () == Utilities.OS_OS2))) {
            File retVal = null;             
            // Windows: resourcePath is e.g. /d:/temp/foo.txt
            if (!isRoot()) {
                String filePath = resourcePath.substring(1).replace('/', File.separatorChar);//NOI18N
                if (getParent().isRoot() && !filePath.endsWith("/")) { //NOI18N
                    filePath = filePath + "/";//NOI18N     
                } 
                retVal = new File(filePath);
            }
            
            return retVal;
        } else {
            // Unix (or similar): resourcePath is e.g. /tmp/foo.txt
            return new File(resourcePath);
        }
    }
    
    final String getNormalizedPath() {
        return resourcePath;
    }

    Enumeration getElements () {
        StringTokenizer sTokens = new StringTokenizer(resourcePath, "/");
        return sTokens;
    }

    ResourcePath getChild(final String nameExt) {
        ResourcePath retVal = null;
        StringBuffer sb = new StringBuffer(resourcePath);
        if (!resourcePath.endsWith("/")) sb.append("/");//NOI18N
        sb.append(nameExt);
        retVal = new ResourcePath(sb.toString());
        return retVal;
    }

    ResourcePath getChild(final String name, final String ext) {
        final StringBuffer sb = new StringBuffer(resourcePath);
        if (!resourcePath.endsWith("/")) sb.append("/");//NOI18N
        sb.append(name);
        if (ext != null && ext.length() != 0)
            sb.append('.').append(ext);//NOI18N
        return new ResourcePath(sb.toString());
    }

    ResourcePath getParent() {
        final int idx = resourcePath.lastIndexOf('/');
        if (idx == 0 && resourcePath.length() == 1) return null;
        return new ResourcePath((idx <= 0) ? "/" : resourcePath.substring(0, idx));//NOI18N
    }

    String getExt() {
        final String resName = resourcePath;
        final int idx0 = resName.lastIndexOf('.') + 1;
        final int idx1 = resName.lastIndexOf('/');
        return idx0 <= 1 || idx0 == resName.length() || idx0 < idx1 ? "" : resName.substring(idx0); // NOI18N
    }

    /**
     * Implements abstract FileObject.getName()
     */
    String getName() {
        int idx0 = resourcePath.lastIndexOf('/');//NOI18N
        assert idx0 != -1 : resourcePath;
        idx0++;
        int idx1 = resourcePath.lastIndexOf('.');//NOI18N
        idx1 = (idx1 == -1 | idx1 < idx0) ? resourcePath.length() : (idx1);
        return resourcePath.substring(idx0, idx1);
    }

    /**
     * Overrides FileObject.getNameExt() to return only substring rather than newly created String
     */
    String getNameExt() {
        int idx0 = resourcePath.lastIndexOf('/');//NOI18N
        assert idx0 != -1 : resourcePath;
        idx0++;
        return resourcePath.substring(idx0);
    }

    String getPath() {
        return resourcePath.substring(1);
    }

    /** Adds slash at first position if necessary and removes slash from last position */
    static String getNormalizedPath(String resPath) {
        if (resPath == null) return resPath;
        resPath = resPath.replace('\\', '/');//NOI18N

        if (!resPath.startsWith("/")) //NOI18N
            resPath = "/" + resPath; //NOI18N

        if (resPath.endsWith("/") && resPath.length() != "/".length()) //NOI18N
            resPath = resPath.substring(0, resPath.length() - 1);

        return resPath;
    }

    public int hashCode() {
        return resourcePath.hashCode();
    }

    public boolean equals(final Object obj) {
        String resPath = null;
        if (obj instanceof String) {
            resPath = (String) obj;
        } else if (obj instanceof ResourcePath) {
            resPath = ((ResourcePath) obj).getNormalizedPath();
        }
        return resourcePath.equals(resPath);
    }

    public String toString() {
        return getNormalizedPath();
    }
}
