/*
 * 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.netbeans.modules.properties;

/**
 * Contains conversion utilities which allow reading and storing a properties file
 * while preserving formatting and comments that user may have entered.
 * <p>
 * Huge portions of this class marked by <i>// prj40 trunk compatability</i>
 * are there only for being able to run unmodified i18n module code in
 * prj40_prototype branch and trunk. Properties module is not
 * prj40 branched and it is updated by <tt>cvs up -f -rprj40_prototype</tt>.
 * <br>
 * 28th March 2003 Petr Kuzel
 *
 * @author Petr Jiricka
 * @author Petr Kuzel - simplification
 */
public class UtilConvert {

    private UtilConvert() {
    }

    /**
     * These characters play role as key-value sepsrators
     */
    public  static final String keyValueSeparators = "=: \t\r\n\f";

    public  static final String strictKeyValueSeparators = "=:";

    /** Differs from JDK's implementation in that it does not save ' ' as '\ '. */
    private static final String specialSaveChars = "=:\t\r\n\f#!";

    public  static final String whiteSpaceChars = " \t\r\n\f";


    /**
     * Escape key value. Converts string to one with escaped ' ','=',':', and last '\\'
     * in case they are not escaped already. Used for formating user input.
     * //!!! wrong semantics what does it mean if not escaped already?
     */
    public static String escapePropertiesSpecialChars (String source) {
        return source; // prj40 trunk compatability
//        if(source == null) return null;
//        StringBuffer result = new StringBuffer();
//        for(int i=0; i<source.length(); i++) {
//            char x = source.charAt(i);
//            if(x == ' ' || x == '=' || x == ':') {
//                if( i==0 || (i>0 && source.charAt(i-1) != '\\'))
//                    result.append('\\');
//            }
//            // last char == '\\'
//            if(i==source.length()-1 && x == '\\') {
//                if( i>0 && source.charAt(i-1)!='\\')
//                    result.append('\\');
//            }
//            result.append(x);
//        }
//        return result.toString();
    }
    
    /** Checks whether the string contains only spaces */
    private static boolean onlySpaces(String s){
        for (int i = 0; i<s.length(); i++){
            if (s.charAt(i) != ' ') return false;
        }
        return true;
    }
    
    /** Escapes spaces in outer part of string. */
    public static String escapeOutsideSpaces(String source){
        return source; // prj40 trunk compatability
//        if (source == null || source.length() == 0) return source;
//        StringBuffer result = new StringBuffer();
//        int i = 0;
//        while (source.charAt(i) == ' '){
//            result.append('\\');
//            result.append(' ');
//            if ((i+1) == source.length()) return result.toString();
//            i++;
//        }
//        while (!onlySpaces(source.substring(i))){
//            result.append(source.charAt(i));
//            if ((i+1) == source.length()) return result.toString();
//            i++;
//        }
//        while (i < source.length()){
//            result.append('\\');
//            result.append(' ');
//            i++;
//        }
//        return result.toString();
    }

    /**
     * Escape user's value. It escapes last '\\' character  only
     * to prevent user to wrongly create continuation line.
     */
    public static String escapeLineContinuationChar(String source) {
        return source; // prj40 trunk compatability
//        if(source == null) return null;
//        if(source.endsWith("\\")) { //NOI18N
//            if(source.length()>1 && source.charAt(source.length()-2)!='\\')
//                return new String(new StringBuffer(source).append('\\'));
//        }
//        return source;
    }

    /**
     * Converts these java special chars ('\t', '\n', '\b', '\r', '\f') to encoded escapes.
     * Note there are not converted unicode chars.
     */
    public static String escapeJavaSpecialChars(String source) {
        return source;  // prj40 trunk compatability
//        if(source == null) return null;
//        StringBuffer result = new StringBuffer();
//        for (int i=0; i<source.length(); i++) {
//            char ch = source.charAt(i);
//            switch(ch) {
//                case '\t':
//                    result.append("\\t"); //NOI18N
//                    break;
//                case '\n':
//                    result.append("\\n"); //NOI18N
//                    break;
//                case '\b':
//                    result.append("\\b"); //NOI18N
//                    break;
//                case '\r':
//                    result.append("\\r"); //NOI18N
//                    break;
//                case '\f':
//                    result.append("\\f"); //NOI18N
//                    break;
//                default:
//                    result.append(ch);
//            }
//        }
//        return result.toString();
    }


    /**
     * Converts encoded '\\uxxxx' to chars.
     * Note there are not converted '\\"', '\\'', '\\ ', '\\\\' and java special chars escapes.
     */
    public static String unicodesToChars (String theString) {
        return theString; // prj40 trunk compatability
//        if (theString == null) return null;
//        char aChar;
//        char next;
//        int len = theString.length();
//        StringBuffer outBuffer = new StringBuffer(len);
//
//        for(int x=0; x<len; x++) {
//            aChar = theString.charAt(x);
//            if(x+5 < len) { // if there is space for uXXXX chars enough
//                next = theString.charAt(x+1);
//                try {
//                    if (aChar == '\\' && next == 'u') {
//                        // Read the xxxx
//                        int value=0;
//                        for (int i=0; i<4; i++) {
//                            next = theString.charAt(x+1+i+1);
//                            switch (next) {
//                                case '0': case '1': case '2': case '3': case '4':
//                                case '5': case '6': case '7': case '8': case '9':
//                                    value = (value << 4) + next - '0';
//                                    break;
//                                case 'a': case 'b': case 'c':
//                                case 'd': case 'e': case 'f':
//                                    value = (value << 4) + 10 + next - 'a';
//                                    break;
//                                case 'A': case 'B': case 'C':
//                                case 'D': case 'E': case 'F':
//                                    value = (value << 4) + 10 + next - 'A';
//                                    break;
//                                default:
//                                    throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
//                            }
//                        }
//                        outBuffer.append((char)value);
//                        x += 5;
//                    } else
//                        outBuffer.append(aChar);
//                } catch (IllegalArgumentException iae) {
//                    outBuffer.append(aChar); // not unicode -> interpret as a normal char
//                }
//            } else
//                outBuffer.append(aChar);
//        }
//        return outBuffer.toString();
    }

    /**
     * Convert chars to encoded '\\uxxxx' using comment escaping rules.
     * @param commentString
     * @return escaped comment
     */
    public static String escapeComment(String commentString) {
        return charsToUnicodes(commentString, true);
    }

    /**
    * Converts chars to encoded '\\uxxxx'.
     * Note there are not converted '\\"', '\\'', '\\ ', '\\\\' and java special chars escapes.
    */
    public static String charsToUnicodes(String s){
        return charsToUnicodes(s, false);
    }
    
    
    /**
    * Converts chars to encoded '\\uxxxx'. If skipWhiteSpaces is true, then white spaces won't be converted
     * Note there are not converted '\\"', '\\'', '\\ ', '\\\\' and java special chars escapes.
    */
    public static String charsToUnicodes(String theString, boolean skipWhiteSpaces) {
        return theString; // prj40 trunk compatability
//        if(theString == null) return null;
//        char aChar;
//        int len = theString.length();
//        StringBuffer outBuffer = new StringBuffer(len*2);
//
//        for(int x=0; x<len; ) {
//            aChar = theString.charAt(x++);
//            if ((aChar < 20) || (aChar > 127) ) {
//
//                if (skipWhiteSpaces && Character.isWhitespace(aChar)){
//                    // do not convert white spaces
//                    outBuffer.append(aChar);
//                    continue;
//                }
//
//                outBuffer.append('\\');
//                outBuffer.append('u');
//                outBuffer.append(toHex((aChar >> 12) & 0xF));
//                outBuffer.append(toHex((aChar >> 8) & 0xF));
//                outBuffer.append(toHex((aChar >> 4) & 0xF));
//                outBuffer.append(toHex((aChar >> 0) & 0xF));
//            } else {
//                outBuffer.append(aChar);
//            }
//        }
//        return outBuffer.toString();
    }


    /**
     * Converts encoded \\uxxxx to unicode chars
     * and changes special saved chars to their original forms
     */
    public static String loadConvert (String theString) {
        char aChar;
        final int len = theString.length();
        StringBuffer outBuffer = new StringBuffer(len);

        main:
        for(int x=0; x<len; ) {
            aChar = theString.charAt(x++);
            if (aChar == '\\' && x != len) {
                aChar = theString.charAt(x++);
                if(aChar == 'u') {
                    if (x > len - 4) {
                        outBuffer.append('\\').append('u');
                        continue main;
                    }
                    // Read the xxxx
                    int value=0;
                    for (int i=0; i<4; i++) {
                        aChar = theString.charAt(x++);
                        switch (aChar) {
                        case '0': case '1': case '2': case '3': case '4':
                        case '5': case '6': case '7': case '8': case '9':
                            value = (value << 4) + aChar - '0';
                            break;
                        case 'a': case 'b': case 'c':
                        case 'd': case 'e': case 'f':
                            value = (value << 4) + 10 + aChar - 'a';
                            break;
                        case 'A': case 'B': case 'C':
                        case 'D': case 'E': case 'F':
                            value = (value << 4) + 10 + aChar - 'A';
                            break;
                        default:
                            /*
                             * Handle a malformed \\uxxxx encoding:
                             *
                             * We want to print "\\u" plus all the hexadecimal
                             * digits that passed the above switch.
                             * To achieve it, print ("\\u")...,
                             */
                            outBuffer.append('\\').append('u');

                            /* ... move 'x' back to character after "u"... */
                            x -= i + 1;

                            /* ... and continue with the main loop. */
                            continue main;
                        }
                    }
                    outBuffer.append((char)value);
                } else {
                    if (aChar == 't') aChar = '\t';
                    else if (aChar == 'r') aChar = '\r';
                    else if (aChar == 'n') aChar = '\n';
                    else if (aChar == 'f') aChar = '\f';
                    outBuffer.append(aChar);
                }
            } else
                outBuffer.append(aChar);
        }
        return outBuffer.toString();
    }

    /**
     * Converts unicodes to encoded \\uxxxx
     * and writes out any of the characters in specialSaveChars
     * with a preceding slash.
     * Differs from Sun's implementation in that it does not save ' ' as '\ '.
     */
    public static String saveConvert(String theString) {
        char aChar;
        int len = theString.length();
        StringBuffer outBuffer = new StringBuffer(len*2);

        for(int x=0; x<len; ) {
            aChar = theString.charAt(x++);
            switch(aChar) {
            case '\\':outBuffer.append('\\'); outBuffer.append('\\');
                continue;
            case '\t':outBuffer.append('\\'); outBuffer.append('t');
                continue;
            case '\n':outBuffer.append('\\'); outBuffer.append('n');
                continue;
            case '\r':outBuffer.append('\\'); outBuffer.append('r');
                continue;
            case '\f':outBuffer.append('\\'); outBuffer.append('f');
                continue;
            default:
                if ((aChar < 20) || (aChar > 127)) {
                    outBuffer.append('\\');
                    outBuffer.append('u');
                    outBuffer.append(toHex((aChar >> 12) & 0xF));
                    outBuffer.append(toHex((aChar >> 8) & 0xF));
                    outBuffer.append(toHex((aChar >> 4) & 0xF));
                    outBuffer.append(toHex((aChar >> 0) & 0xF));
                } else {
                    if (specialSaveChars.indexOf(aChar) != -1)
                        outBuffer.append('\\');
                    outBuffer.append(aChar);
                }
            }
        }
        return outBuffer.toString();
    }

    /**
     * Convert a nibble to a hex character
     * @param	nibble	the nibble to convert.
     */
    private static char toHex(int nibble) {
        return (char)hexDigit[(nibble & 0xF)];
    }

    /** A table of hex digits */
    static final byte[] hexDigit = {
        '0','1','2','3','4','5','6','7','8','9',
        'a','b','c','d','e','f'}; // #168629
}
