/*
 *
 *  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.flex.compiler.common;

import org.apache.flex.compiler.definitions.INamespaceDefinition;
import org.apache.flex.compiler.internal.definitions.NamespaceDefinition;
import org.apache.flex.compiler.internal.workspaces.Workspace;
import org.apache.flex.compiler.workspaces.IWorkspace;

public class ASImportTarget implements IImportTarget
{
    private final NamespaceDefinition.ILanguageNamespaceDefinition importedPublicPackageNamespace;
    private final String definitionName;

    public static ASImportTarget get(IWorkspace w, String target)
    {
        String packageName = null;
        String definitionName = null;
        int lastDotIndex = target.lastIndexOf('.');
        if (lastDotIndex == -1)
        {
            packageName = "";
            if (!target.equals("*"))
            {
                definitionName = target;
            }
        }
        else
        {
            packageName = target.substring(0, lastDotIndex);
            String afterLastDot = target.substring(lastDotIndex + 1);
            if (!afterLastDot.equals("*"))
                definitionName = afterLastDot;
        }
        Workspace workspace = (Workspace)w;
        NamespaceDefinition.ILanguageNamespaceDefinition packagePublicNamespace = 
            workspace.getPackageNamespaceDefinitionCache().get(packageName, false);
        return new ASImportTarget(packagePublicNamespace, definitionName);
    }
    
    /**
     * Create an ASImport from a package-style XML namespace
     * @param xmlNamespace  package-style XML namespace (e.g. mycontrols.* from xmlns:my="mycontrols.*")
     * @return              ASImport representing the imported classes (e.g. mycontrols.*)
     */
    public static IImportTarget buildImportFromXMLNamespace(IWorkspace w, String xmlNamespace)
    {
        String directory = xmlNamespace;
        if (xmlNamespace != null && xmlNamespace.endsWith("*"))
        {
            directory = directory.substring(0, directory.length()-1);

            // make sure the namespace id is actually a package name and not a URI
            // like http://foo.adobe.com/2006/mxml
            if (directory.indexOf("/") == -1 &&
                    directory.indexOf(":") == -1)
            {
                return get(w, xmlNamespace); //new ASImportTarget(xmlNamespace);
            }
        }
        return null;
    }
    
    /**
     * Create an ASImport from a package name (as it appears in a package definition)
     * @param packageName       package name (e.g. mx.controls)
     * @return                  ASImport representing the imported classes (e.g. mx.controls.*)
     */
    public static IImportTarget buildImportFromPackageName(IWorkspace w, String packageName)
    {
        if (packageName == null || (packageName.length() == 1 && packageName.charAt(0) == '*') || packageName.length() == 0) 
            packageName = "";
        Workspace workspace = (Workspace)w;
        NamespaceDefinition.ILanguageNamespaceDefinition packagePublicNamespace = 
            workspace.getPackageNamespaceDefinitionCache().get(packageName, false);
        return new ASImportTarget(packagePublicNamespace, null);
    }
    
	/**
	 * Constructor
	 * @param target	import target (e.g. mx.controls.* or mx.controls.Button)
	 */
	private ASImportTarget(NamespaceDefinition.ILanguageNamespaceDefinition namespace, String definitionName)
	{
		this.importedPublicPackageNamespace = namespace;
		this.definitionName = definitionName;
	}
	
	@Override
    public String getTargetPackage()
	{
		return importedPublicPackageNamespace.getURI();
	}
	
	@Override
    public boolean isWildcard()
	{
		return definitionName == null;
	}
	
	@Override
    public String getTargetName() {
		return definitionName == null ? "" : definitionName;
	}
	
	@Override
    public String getQualifiedName(String reference)
	{
	    int lastIndexOfDotInReferece = reference.lastIndexOf('.');
		// If we're referring to a short name (e.g. Button)...
		if (lastIndexOfDotInReferece == -1)
		{
			if ((definitionName == null) || (reference.equals(definitionName)))	// importing a whole package (e.g. mx.controls.*)
			{
				StringBuilder builder = new StringBuilder();
				String uri = importedPublicPackageNamespace.getURI();
				if (uri != null && uri.length() > 0) {
				    builder.append(uri);
				    builder.append('.');
				}
				builder.append(reference);
				return builder.toString();
			}
			return null; // no match! (e.g. mx.controls.Button and RadioButton)
			
		}
		String packageNameInReference = reference.substring(0, lastIndexOfDotInReferece);
		if (!packageNameInReference.equals(importedPublicPackageNamespace.getURI()))
		    return null; // package names don't match ( e.g. mx.core and mx.controls.Button
		
		if (definitionName == null)	// importing a whole package (e.g. mx.controls.*)
		    return reference;
		
		String definitionNameInReference = reference.substring(lastIndexOfDotInReferece + 1);
		if (definitionNameInReference.equals(definitionName))		// exact match! (e.g. mx.controls.Button and mx.controls.Button)
			return reference;
		// no match! (e.g. mx.controls.Button and mx.controls.RadioButton)
		return null;
		
	}
	
	/**
	 * Get the import target as a string (as it would appear after the keyword "import").
	 * @return		the string representation of the import target
	 */
	@Override
	public String toString()
	{
	    String packageName = importedPublicPackageNamespace.getURI();
	    int definitionNameLen = definitionName == null ? 2 : definitionName.length();
	    StringBuilder builder = new StringBuilder(packageName.length() + definitionNameLen);
		builder.append(packageName);
		builder.append('.');
		builder.append(definitionName == null ? "*" : definitionName);
	    return builder.toString();
	}
	
	@Override
    public INamespaceDefinition getNamespace()
	{
	    return this.importedPublicPackageNamespace;
	}
}
