/*
 * Licensed Material - Property of IBM
 * (C) Copyright IBM Corp. 2002 - All Rights Reserved.
 * US Government Users Restricted Rights - Use, duplication or disclosure
 * restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 * plugins/com.ibm.etools.xmlutility/src/com/ibm/etools/xmlutility/uri/URIEncoder.java, com.ibm.etools.xmlutility, wsa.xml.v51, 20030718_1605.o
 *
 * @version 1.3 7/18/03
 */

package org.eclipse.wst.wsi.internal;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.BitSet;

/**
 *  This class is a modified version of java.lang.URLEncoder.
 */
public class URIEncoder
{
  static BitSet dontNeedEncoding;
  static final int caseDiff = ('a' - 'A');
  static String dfltEncName = null;

  static {
    dontNeedEncoding = new BitSet(256);
    int i;
    for (i = 'a'; i <= 'z'; i++)
    {
      dontNeedEncoding.set(i);
    }
    for (i = 'A'; i <= 'Z'; i++)
    {
      dontNeedEncoding.set(i);
    }
    for (i = '0'; i <= '9'; i++)
    {
      dontNeedEncoding.set(i);
    }

    //dontNeedEncoding.set(' '); // cs.. removed so that space character will be replaced by %20
    dontNeedEncoding.set('-');
    dontNeedEncoding.set('_');
    dontNeedEncoding.set('.');
    dontNeedEncoding.set('*');
    dontNeedEncoding.set(':'); // cs.. added 
    dontNeedEncoding.set('/');
    // cs.. added so that slashes don't get encoded as %2F

    // dfltEncName = (String)AccessController.doPrivileged(new GetPropertyAction("file.encoding"));
    // As discussed with Sandy, we should encode URIs with UTF8
    dfltEncName = "UTF8";
    //System.out.println("dfltEncName " + dfltEncName);
  }

  /**
   * You can't call the constructor.
   */
  private URIEncoder()
  {
  }

  /**
   * Translates a string into <code>x-www-form-urlencoded</code>
   * format. This method uses the platform's default encoding
   * as the encoding scheme to obtain the bytes for unsafe characters.
   *
   * @param   s   <code>String</code> to be translated.
   * @return  the translated <code>String</code>.
   */
  public static String encode(String s)
  {
    String str = null;
    try
    {
      str = encode(s, dfltEncName);
    }
    catch (UnsupportedEncodingException e)
    {
      // The system should always have the platform default
    }
    return str;
  }

  /**
   * Translates a string into <code>application/x-www-form-urlencoded</code>
   * format using a specific encoding scheme. This method uses the
   * supplied encoding scheme to obtain the bytes for unsafe
   * characters.
   * <p>
   * <em><strong>Note:</strong> The <a href=
   * "http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars">
   * World Wide Web Consortium Recommendation</a> states that
   * UTF-8 should be used. Not doing so may introduce
   * incompatibilites.</em>
   *
   * @param   s   <code>String</code> to be translated.
   * @param   enc   The name of a supported 
   *    <a href="../lang/package-summary.html#charenc">character
   *    encoding</a>.
   * @return  the translated <code>String</code>.
   * @exception  UnsupportedEncodingException
   *             If the named encoding is not supported
   * @see URLDecoder#decode(java.lang.String, java.lang.String)
   */
  public static String encode(String s, String enc)
    throws UnsupportedEncodingException
  {
    boolean needToChange = false;
    boolean wroteUnencodedChar = false;
    int maxBytesPerChar = 10; // rather arbitrary limit, but safe for now
    StringBuffer out = new StringBuffer(s.length());
    ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar);
    BufferedWriter writer =
      new BufferedWriter(new OutputStreamWriter(buf, enc));

    for (int i = 0; i < s.length(); i++)
    {
      int c = (int) s.charAt(i);
      //System.out.println("Examining character: " + c);
      if (dontNeedEncoding.get(c))
      {
        //if (c == ' ')
        //{
        //  c = '+';
        //  needToChange = true;
        //}
        //System.out.println("Storing: " + c);
        out.append((char) c);
        wroteUnencodedChar = true;
      }
      else
      {
        // convert to external encoding before hex conversion
        try
        {
          if (wroteUnencodedChar)
          { // Fix for 4407610
            writer = new BufferedWriter(new OutputStreamWriter(buf, enc));
            wroteUnencodedChar = false;
          }
          writer.write(c);

          // If this character represents the start of a Unicode
          // surrogate pair, then pass in two characters. It's not
          // clear what should be done if a bytes reserved in the 
          // surrogate pairs range occurs outside of a legal
          // surrogate pair. For now, just treat it as if it were 
          // any other character.
          // 
          if (c >= 0xD800 && c <= 0xDBFF)
          {
            //  System.out.println(Integer.toHexString(c) + " is high surrogate");			      
            if ((i + 1) < s.length())
            {
              int d = (int) s.charAt(i + 1);
              // System.out.println("\tExamining " + Integer.toHexString(d));			      
              if (d >= 0xDC00 && d <= 0xDFFF)
              {
                // System.out.println("\t" + Integer.toHexString(d) + " is low surrogate");				
                writer.write(d);
                i++;
              }
            }
          }
          writer.flush();
        }
        catch (IOException e)
        {
          buf.reset();
          continue;
        }
        byte[] ba = buf.toByteArray();

        for (int j = 0; j < ba.length; j++)
        {
          out.append('%');
          char ch = Character.forDigit((ba[j] >> 4) & 0xF, 16);
          // converting to use uppercase letter as part of
          // the hex value if ch is a letter.
          if (Character.isLetter(ch))
          {
            ch -= caseDiff;
          }
          out.append(ch);
          ch = Character.forDigit(ba[j] & 0xF, 16);
          if (Character.isLetter(ch))
          {
            ch -= caseDiff;
          }
          out.append(ch);
        }
        buf.reset();
        needToChange = true;
      }
    }
    return (needToChange ? out.toString() : s);
  }
}
