/*
* Copyright (c) 2002 IBM Corporation and others.
* All rights reserved.   This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* 
* Contributors:
*   IBM - Initial API and implementation
*   Jens Lukowski/Innoopract - initial renaming/restructuring
* 
*/
package org.eclipse.wst.common.uriresolver.internal.util;

import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;


public class URIHelper
{                       
  protected static final String FILE_PROTOCOL = "file:";
  protected static final String PLATFORM_RESOURCE_PROTOCOL = "platform:/resource/";
  protected static final String PROTOCOL_PATTERN = ":"; 

  public static String normalize(String uri)
  {                           
    if (uri != null)
    {                      
      String protocol = getProtocol(uri);
      String file = uri;
           
      if (protocol != null)
      {               
        try
        {   
          // 
          URL url = new URL(uri); 
          // we use a 'Path' on the 'file' part of the url in order to normalize the '.' and '..' segments
          IPath path = new Path(url.getFile()); 
          URL url2 = new URL(url.getProtocol(), url.getHost(), url.getPort(), path.toString());
          uri = url2.toString();                               
        }                        
        catch (Exception e)
        {  
        }
      }   
      else
      {      
        IPath path = new Path(file);
        uri = path.toString();
      }
    }
    return uri;
  }


  /**
   * a 'null' rootLocation argument will causes uri that begins with a '/' to be treated as a workspace relative resource
   * (i.e. the string "platform:/resource" is prepended and the uri is resolved via the Platform object)
   */
  public static String normalize(String uri, String resourceLocation, String rootLocation)
  {
    String result = null;

    if (uri != null)
    { 
      // is the uri a url
      if (hasProtocol(uri))
      {                  
        if (isPlatformResourceProtocol(uri))
        {
          result = resolvePlatformUrl(uri);
        }
        else
        {
          result = uri;
        }
      }
   
      // is uri absolute
      //
      if (result == null)
      {
        if (uri.indexOf(":") != -1 || uri.startsWith("/") || uri.startsWith("\\"))
        {                   
          result = uri;
        }
      }
  
      // if uri is relative to the resourceLocation
      //
      if (result == null && resourceLocation != null)
      {          
        if (resourceLocation.endsWith("/"))
        {
			    result = resourceLocation + uri;
        }
		    else
        {
			    result = resourceLocation + "/../" + uri;
        }
      }
      
      if (result == null)
      {
        result = uri;
      }
  
      result = normalize(result);
    }

    //System.out.println("normalize(" + uri + ", " + resourceLocation + ", " + rootLocation + ") = " + result);
    return result;
  }


  public static boolean isURL(String uri)
  {
    return uri.indexOf(":/") > 2; // test that the index is > 2 so that C:/ is not considered a protocol
  }


  public static String getLastSegment(String uri)
  {
    String result = uri;
    int index = Math.max(uri.lastIndexOf("/"), uri.lastIndexOf("\\"));
    if (index != -1)
    {
      result = uri.substring(index + 1);
    }
    return result;
  }


  public static String getFileExtension(String uri)
  {
    String result = null;
    int dotIndex = getExtensionDotIndex(uri);
               
    if (dotIndex != -1)
    {
      result = uri.substring(dotIndex + 1);
    }

    return result;
  }


  public static String removeFileExtension(String uri)
  {
    String result = null;
    int dotIndex = getExtensionDotIndex(uri);

    if (dotIndex != -1)
    {
      result = uri.substring(0, dotIndex);
    }

    return result;
  }   
             

  // here we use the Platform to resolve a workspace relative path to an actual url
  //
  protected static String resolvePlatformUrl(String urlspec)
  {
    String result = null;
    try
    {                        
      urlspec = urlspec.replace('\\', '/'); 
      URL url = new URL(urlspec);
      URL resolvedURL = Platform.resolve(url);
      result = resolvedURL.toString();
    }
    catch (Exception e)
    {
    }
    return result;
  }


  protected static int getExtensionDotIndex(String uri)
  {
    int result = -1;
    int dotIndex = uri.lastIndexOf(".");
    int slashIndex = Math.max(uri.lastIndexOf("/"), uri.lastIndexOf("\\"));

    if (dotIndex != -1 && dotIndex > slashIndex)
    {
      result = dotIndex;
    }

    return result;
  }
  

  public static boolean isPlatformResourceProtocol(String uri)
  {                                                     
    return uri != null && uri.startsWith(PLATFORM_RESOURCE_PROTOCOL);
  }                                                   

  public static String removePlatformResourceProtocol(String uri)
  {  
    if (uri != null && uri.startsWith(PLATFORM_RESOURCE_PROTOCOL))
    {
      uri = uri.substring(PLATFORM_RESOURCE_PROTOCOL.length());
    }                                                          
    return uri;
  }            


  public static String prependPlatformResourceProtocol(String uri)
  {  
    if (uri != null && !uri.startsWith(PLATFORM_RESOURCE_PROTOCOL))
    {
      uri = PLATFORM_RESOURCE_PROTOCOL + uri;
    }                                                          
    return uri;
  } 
  

  public static String prependFileProtocol(String uri)
  {  
    if (uri != null && !uri.startsWith(FILE_PROTOCOL))
    {
      uri = FILE_PROTOCOL + uri;
    }                                                          
    return uri;
  } 
            
  public static boolean hasProtocol(String uri)
  {
    boolean result = false;     
    if (uri != null)
    {
      int index = uri.indexOf(PROTOCOL_PATTERN);
      if (index != -1 && index > 2) // assume protocol with be length 3 so that the'C' in 'C:/' is not interpreted as a protocol
      {
        result = true;
      }
    }
    return result;
  }     
                      

  public static boolean isAbsolute(String uri)
  {
    boolean result = false;     
    if (uri != null)
    {
      int index = uri.indexOf(PROTOCOL_PATTERN);
      if (index != -1 || uri.startsWith("/"))
      {
        result = true;
      }
    }
    return result;
  }


  public static String addImpliedFileProtocol(String uri)
  {  
    if (!hasProtocol(uri))
    {                           
      String prefix = FILE_PROTOCOL;
      prefix += uri.startsWith("/") ? "//" : "///";
      uri = prefix + uri;
    }
    return uri;
  }
             
  // todo... need to revisit this before we publicize it
  // 
  protected static String getProtocol(String uri)
  {  
    String result = null;     
    if (uri != null)
    {
      int index = uri.indexOf(PROTOCOL_PATTERN);
      if (index > 2) // assume protocol with be length 3 so that the'C' in 'C:/' is not interpreted as a protocol
      {
        result = uri.substring(0, index + PROTOCOL_PATTERN.length());
      }
    }
    return result;
  } 
 

  public static String removeProtocol(String uri)
  {
    String result = uri;     
    if (uri != null)
    {
      int index = uri.indexOf(PROTOCOL_PATTERN);
      if (index > 2)
      {
        result = result.substring(index + PROTOCOL_PATTERN.length());                 
      }
    }
    return result;
  } 


  protected static boolean isProtocolFileOrNull(String uri)
  {                                    
    String protocol = getProtocol(uri);   
    return protocol == null || protocol.equals(FILE_PROTOCOL);
  }  

                                           
  protected static boolean isMatchingProtocol(String uri1, String uri2)
  { 
    boolean result = false;  

    String protocol1 = getProtocol(uri1);
    String protocol2 = getProtocol(uri2);

    if (isProtocolFileOrNull(protocol1) && isProtocolFileOrNull(protocol2))
    {                                                                      
      result = true;
    } 
    else
    {
      result = protocol1 != null && protocol2 != null && protocol1.equals(protocol2);
    }             

    return result;
  }

  /**
   * warning... this method not fully tested yet
   */
  public static String getRelativeURI(String uri, String resourceLocation)
  {                                      
    String result = uri;  
    if (isMatchingProtocol(uri, resourceLocation)) 
    {
      result = getRelativeURI(new Path(removeProtocol(uri)),
                              new Path(removeProtocol(resourceLocation)));
    }            

    return result;
  }

  /**
   * warning... this method not fully tested yet
   */
  public static String getRelativeURI(IPath uri, IPath resourceLocation)
  {            
    String result = null;
    int nMatchingSegments = 0;       
    resourceLocation = resourceLocation.removeLastSegments(1);
    while (true)
    {                   
      String a = uri.segment(nMatchingSegments); 
      String b = resourceLocation.segment(nMatchingSegments); 
      if (a != null && b != null && a.equals(b))
      {
        nMatchingSegments++;
      }
      else
      {
        break;
      }
    }                 

    if (nMatchingSegments == 0)
    {
      result = uri.toOSString();
    }
    else
    {    
      result = "";   
      boolean isFirst = true;
      String[] segments = resourceLocation.segments();
      for (int i = nMatchingSegments; i < segments.length; i++)
      {  
        result += isFirst ? ".." : "/..";     
        if (isFirst)
        {
          isFirst = false;
        }        
      }
      // 
      segments = uri.segments();
      for (int i = nMatchingSegments; i < segments.length; i++)
      {                      
        result += isFirst ? segments[i] : ("/" + segments[i]);     
        if (isFirst)
        {
          isFirst = false;
        } 
      }
    }   
    return result;
  }


  public static String getPlatformURI(IResource resource)
  {                            
    String fullPath = resource.getFullPath().toString();
    if (fullPath.startsWith("/"))
    {
      fullPath = fullPath.substring(1);
    }
    return PLATFORM_RESOURCE_PROTOCOL + fullPath;
  }
  

  /**
   * This methods is used as a quick test to see if a uri can be resolved to an existing resource.   
   */
  public static boolean isReadableURI(String uri, boolean testRemoteURI)
  {  
    boolean result = true;  
    if (uri != null)
    {   
      try
      {                               
        uri = normalize(uri, null, null);
        if (isProtocolFileOrNull(uri))
        {
          uri = removeProtocol(uri);                            
          File file = new File(uri);
          result = file.exists() && file.isFile();
        }
        else if (isPlatformResourceProtocol(uri))
        {
          // Note - If we are here, uri has been failed to resolve
          // relative to the Platform. See normalize() to find why.
          result = false;
        }
        else if (testRemoteURI)
        {
          URL url = new URL(uri);
          InputStream is = url.openConnection().getInputStream();
          is.close();
          // the uri is readable if we reach here.
          result = true;
        }
      }
      catch (Exception e)
      {
        result = false;
      }
    }
    else // uri is null
      result = false;

    return result;
  }  

  /**
   * return true if this is a valid uri
   */
  public static boolean isValidURI(String uri)
  {                       
    boolean result = false;
    try                                                              
    {
      new URI(uri);
      result = true;
    }
    catch (Exception e)
    {
    }               
    return result;
  }

  /**
   * returns an acceptable URI for a file path
   */
  public static String getURIForFilePath(String filePath)
  {
    String result = addImpliedFileProtocol(filePath);
    if (!isValidURI(result))
    {
      result = URIEncoder.encode(result);
    }
    return result;
  }
}
