/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.common;

import javax.xml.namespace.QName;
import java.util.*;

public class NameUtil {
    // punctuation characters
    public final static char HYPHEN = '\u002D';
    public final static char PERIOD = '\u002E';
    public final static char COLON = '\u003A';
    public final static char USCORE = '\u005F';
    public final static char DOT = '\u00B7';
    public final static char TELEIA = '\u0387';
    public final static char AYAH = '\u06DD';
    public final static char ELHIZB = '\u06DE';

    private final static Set<String> javaWords = new HashSet<>(Arrays.asList(
        "assert",
        "abstract",
        "boolean",
        "break",
        "byte",
        "case",
        "catch",
        "char",
        "class",
        "const",
        "continue",
        "default",
        "do",
        "double",
        "else",
        "enum", // since JDK1.5
        "extends",
        "false", // not a keyword
        "final",
        "finally",
        "float",
        "for",
        "goto",
        "if",
        "implements",
        "import",
        "instanceof",
        "int",
        "interface",
        "long",
        "native",
        "new",
        "null", // not a keyword
        "package",
        "private",
        "protected",
        "public",
        "return",
        "short",
        "static",
        "strictfp",
        "super",
        "switch",
        "synchronized",
        "this",
        "threadsafe",
        "throw",
        "throws",
        "transient",
        "true", // not a keyword
        "try",
        "void",
        "volatile",
        "while"));

    private final static Set<String> extraWords = new HashSet<>(Arrays.asList(
        "i",          // used for indexes
        "target",     // used for parameter
        "org",        // used for package names
        "com"        // used for package names
    ));

    /*
    private final static Set javaNames = new HashSet(Arrays.asList(
        new String[]
        {
            "CharSequence",
            "Cloneable",
            "Comparable",
            "Runnable",

            "Boolean",
            "Byte",
            "Character",
            "Class",
            "ClassLoader",
            "Compiler",
            "Double",
            "Float",
            "InheritableThreadLocal",
            "Integer",
            "Long",
            "Math",
            "Number",
            "Object",
            "Package",
            "Process",
            "Runtime",
            "RuntimePermission",
            "SecurityManager",
            "Short",
            "StackTraceElement",
            "StrictMath",
            "String",
            "StringBuffer",
            "System",
            "Thread",
            "ThreadGroup",
            "ThreadLocal",
            "Throwable",
            "Void",

            "ArithmeticException",
            "ArrayIndexOutOfBoundsException",
            "ArrayStoreException",
            "ClassCastException",
            "ClassNotFoundException",
            "CloneNotSupportedException",
            "Exception",
            "IllegalAccessException",
            "IllegalArgumentException",
            "IllegalMonitorStateException",
            "IllegalStateException",
            "IllegalThreadStateException",
            "IndexOutOfBoundsException",
            "InstantiationException",
            "InterruptedException",
            "NegativeArraySizeException",
            "NoSuchFieldException",
            "NoSuchMethodException",
            "NullPointerException",
            "NumberFormatException",
            "RuntimeException",
            "SecurityException",
            "StringIndexOutOfBoundsException",
            "UnsupportedOperationException",

            "AbstractMethodError",
            "AssertionError",
            "ClassCircularityError",
            "ClassFormatError",
            "Error",
            "ExceptionInInitializerError",
            "IllegalAccessError",
            "IncompatibleClassChangeError",
            "InstantiationError",
            "InternalError",
            "LinkageError",
            "NoClassDefFoundError",
            "NoSuchFieldError",
            "NoSuchMethodError",
            "OutOfMemoryError",
            "StackOverflowError",
            "ThreadDeath",
            "UnknownError",
            "UnsatisfiedLinkError",
            "UnsupportedClassVersionError",
            "VerifyError",
            "VirtualMachineError",
        }
    ));
    */

    private final static Set<String> javaNames = new HashSet<>(Arrays.asList(
        // 1. all the Java.lang classes [1.4.1 JDK].
        "CharSequence",
        "Cloneable",
        "Comparable",
        "Runnable",

        "Boolean",
        "Byte",
        "Character",
        "Class",
        "ClassLoader",
        "Compiler",
        "Double",
        "Float",
        "InheritableThreadLocal",
        "Integer",
        "Long",
        "Math",
        "Number",
        "Object",
        "Package",
        "Process",
        "Runtime",
        "RuntimePermission",
        "SecurityManager",
        "Short",
        "StackTraceElement",
        "StrictMath",
        "String",
        "StringBuffer",
        "System",
        "Thread",
        "ThreadGroup",
        "ThreadLocal",
        "Throwable",
        "Void",

        "ArithmeticException",
        "ArrayIndexOutOfBoundsException",
        "ArrayStoreException",
        "ClassCastException",
        "ClassNotFoundException",
        "CloneNotSupportedException",
        "Exception",
        "IllegalAccessException",
        "IllegalArgumentException",
        "IllegalMonitorStateException",
        "IllegalStateException",
        "IllegalThreadStateException",
        "IndexOutOfBoundsException",
        "InstantiationException",
        "InterruptedException",
        "NegativeArraySizeException",
        "NoSuchFieldException",
        "NoSuchMethodException",
        "NullPointerException",
        "NumberFormatException",
        "RuntimeException",
        "SecurityException",
        "StringIndexOutOfBoundsException",
        "UnsupportedOperationException",

        "AbstractMethodError",
        "AssertionError",
        "ClassCircularityError",
        "ClassFormatError",
        "Error",
        "ExceptionInInitializerError",
        "IllegalAccessError",
        "IncompatibleClassChangeError",
        "InstantiationError",
        "InternalError",
        "LinkageError",
        "NoClassDefFoundError",
        "NoSuchFieldError",
        "NoSuchMethodError",
        "OutOfMemoryError",
        "StackOverflowError",
        "ThreadDeath",
        "UnknownError",
        "UnsatisfiedLinkError",
        "UnsupportedClassVersionError",
        "VerifyError",
        "VirtualMachineError",

        // 2. other classes used as primitive types by xml beans
        "BigInteger",
        "BigDecimal",
        "Enum",
        "Date",
        "GDate",
        "GDuration",
        "QName",
        "List",

        // 3. the top few org.apache.xmlbeans names
        "XmlObject",
        "XmlCursor",
        "XmlBeans",
        "SchemaType"));

    public static boolean isValidJavaIdentifier(String id) {
        if (id == null) {
            throw new IllegalArgumentException("id cannot be null");
        }

        int len = id.length();
        if (len == 0) {
            return false;
        }

        if (javaWords.contains(id)) {
            return false;
        }

        if (!Character.isJavaIdentifierStart(id.charAt(0))) {
            return false;
        }

        for (int i = 1; i < len; i++) {
            if (!Character.isJavaIdentifierPart(id.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    public static String getClassNameFromQName(QName qname) {
        return getClassNameFromQName(qname, false);
    }

    public static String getClassNameFromQName(QName qname, boolean useJaxRpcRules) {
        String java_type = upperCamelCase(qname.getLocalPart(), useJaxRpcRules);

        String uri = qname.getNamespaceURI();

        String java_pkg = getPackageFromNamespace(uri, useJaxRpcRules);

        if (java_pkg != null) {
            return java_pkg + "." + java_type;
        } else {
            return java_type;
        }
    }

    private static final String JAVA_NS_PREFIX = "java:";

    public static String getNamespaceFromPackage(final Class<?> clazz) {
        Class<?> curr_clazz = clazz;

        while (curr_clazz.isArray()) {
            curr_clazz = curr_clazz.getComponentType();
        }

        String fullname = clazz.getName();
        int lastdot = fullname.lastIndexOf('.');
        String pkg_name = lastdot < 0 ? "" : fullname.substring(0, lastdot);

        //special case for builtin types
        /*
        if (curr_clazz.isPrimitive())
        {
            pkg_name = c.getJavaLanguageNamespaceUri();
        }
        else if (pkg_name.startsWith(LANG_PREFIX))
        {
            final String rem_str = pkg_name.substring(LANG_PREFIX.length());
            pkg_name = c.getJavaLanguageNamespaceUri() + "." + rem_str;
        }
        */
        return JAVA_NS_PREFIX + pkg_name;
    }

    private static boolean isUriSchemeChar(char ch) {
        return (ch >= 'a' && ch <= 'z' ||
                ch >= 'A' && ch <= 'Z' ||
                ch >= '0' && ch <= '9' ||
                ch == '-' || ch == '.' || ch == '+');
    }

    private static boolean isUriAlphaChar(char ch) {
        return (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z');
    }

    private static int findSchemeColon(String uri) {
        int len = uri.length();
        if (len == 0) {
            return -1;
        }
        if (!isUriAlphaChar(uri.charAt(0))) {
            return -1;
        }
        int i;
        for (i = 1; i < len; i++) {
            if (!isUriSchemeChar(uri.charAt(i))) {
                break;
            }
        }
        if (i == len) {
            return -1;
        }
        if (uri.charAt(i) != ':') {
            return -1;
        }
        // consume consecutive colons
        for (; i < len; i++) {
            if (uri.charAt(i) != ':') {
                break;
            }
        }
        // for the "scheme:::" case, return len-1
        return i - 1;
    }

    private static String jls77String(String name) {
        StringBuilder buf = new StringBuilder(name);
        for (int i = 0; i < name.length(); i++) {
            // We need to also make sure that our package names don't contain the
            // "$" character in them, which, although a valid Java identifier part,
            // would create confusion when trying to generate fully-qualified names
            if (!Character.isJavaIdentifierPart(buf.charAt(i)) || '$' == buf.charAt(i)) {
                buf.setCharAt(i, '_');
            }
        }
        if (buf.length() == 0 || !Character.isJavaIdentifierStart(buf.charAt(0))) {
            buf.insert(0, '_');
        }
        if (isJavaReservedWord(name)) {
            buf.append('_');
        }
        return buf.toString();
    }

    private static List<String> splitDNS(String dns) {
        // JAXB says: only split+reverse DNS if TLD matches known TLDs or ISO 3166
        // We are ignoring this now (TH)

        List<String> result = new ArrayList<>();

        int end = dns.length();
        int begin = dns.lastIndexOf('.');
        for (; begin != -1; begin--) {
            if (dns.charAt(begin) == '.') {
                result.add(jls77String(dns.substring(begin + 1, end)));
                end = begin;
            }
        }
        result.add(jls77String(dns.substring(0, end)));

        // JAXB draft example implies removal of www
        if (result.size() >= 3 &&
            result.get(result.size() - 1).toLowerCase(Locale.ROOT).equals("www")) {
            result.remove(result.size() - 1);
        }

        return result;
    }

    private static String processFilename(String filename) {
        // JAXB says: strip 2 or 3 letter extension or ".html"

        int i = filename.lastIndexOf('.');
        if (i > 0 && (
            i + 1 + 2 == filename.length() ||
            i + 1 + 3 == filename.length() ||
            "html".equals(filename.substring(i + 1).toLowerCase(Locale.ROOT)))) {
            return filename.substring(0, i);
        }

        return filename;
    }

    public static String getPackageFromNamespace(String uri) {
        return getPackageFromNamespace(uri, false);
    }

    public static String getPackageFromNamespace(String uri, boolean useJaxRpcRules) {
        // special case: no namespace -> package "noNamespace"
        if (uri == null || uri.length() == 0) {
            return "noNamespace";
        }

        // apply draft JAXB rules
        int len = uri.length();
        int i = findSchemeColon(uri);
        List<String> result;

        if (i == len - 1) {
            // XMLBEANS-57: colon is at end so just use scheme as the package name
            result = new ArrayList<>();
            result.add(uri.substring(0, i));
        } else if (i >= 0 && uri.substring(0, i).equals("java")) {
            result = Arrays.asList(uri.substring(i + 1).split("\\."));
        } else {
            result = new ArrayList<>();
            outer:
            for (i = i + 1; i < len; ) {
                while (uri.charAt(i) == '/') {
                    if (++i >= len) {
                        break outer;
                    }
                }
                int start = i;
                while (uri.charAt(i) != '/') {
                    if (++i >= len) {
                        break;
                    }
                }
                int end = i;
                result.add(uri.substring(start, end));
            }
            if (result.size() > 1) {
                result.set(result.size() - 1, processFilename(result.get(result.size() - 1)));
            }

            if (result.size() > 0) {
                List<String> splitdns = splitDNS(result.get(0));
                result.remove(0);
                result.addAll(0, splitdns);
            }
        }

        StringBuilder buf = new StringBuilder();
        for (String s : result) {
            String part = nonJavaKeyword(lowerCamelCase(s, useJaxRpcRules, true));
            if (part.length() > 0) {
                buf.append(part);
                buf.append('.');
            }
        }
        if (buf.length() == 0) {
            return "noNamespace";
        }
        if (useJaxRpcRules) {
            return buf.substring(0, buf.length() - 1).toLowerCase(Locale.ROOT);
        }
        return buf.substring(0, buf.length() - 1); // chop off extra dot
    }

    public static void main(String[] args) {
        for (String arg : args) {
            System.out.println(upperCaseUnderbar(arg));
        }
    }

    /**
     * Returns a upper-case-and-underbar string using the JAXB rules.
     * Always starts with a capital letter that is a valid
     * java identifier start. (If JAXB rules don't produce
     * one, then "X_" is prepended.)
     */
    public static String upperCaseUnderbar(String xml_name) {
        StringBuilder buf = new StringBuilder();
        List<String> words = splitWords(xml_name, false);

        final int sz = words.size() - 1;
        if (sz >= 0 && !Character.isJavaIdentifierStart(words.get(0).charAt(0))) {
            buf.append("X_");
        }

        for (int i = 0; i < sz; i++) {
            buf.append(words.get(i));
            buf.append(USCORE);
        }

        if (sz >= 0) {
            buf.append(words.get(sz));
        }

        //upcase entire buffer
        final int len = buf.length();
        for (int j = 0; j < len; j++) {
            char c = buf.charAt(j);
            buf.setCharAt(j, Character.toUpperCase(c));
        }

        return buf.toString();
    }

    /**
     * Returns a camel-cased string using the JAXB rules.
     * Always starts with a capital letter that is a valid
     * java identifier start. (If JAXB rules don't produce
     * one, then "X" is prepended.)
     */
    public static String upperCamelCase(String xml_name) {
        return upperCamelCase(xml_name, false);
    }

    /**
     * Returns a camel-cased string, but either JAXB or JAX-RPC rules
     * are used
     */
    public static String upperCamelCase(String xml_name, boolean useJaxRpcRules) {
        StringBuilder buf = new StringBuilder();
        List<String> words = splitWords(xml_name, useJaxRpcRules);

        if (words.size() > 0) {
            if (!Character.isJavaIdentifierStart(words.get(0).charAt(0))) {
                buf.append("X");
            }

            for (String word : words) {
                buf.append(word);
            }
        }
        return buf.toString();
    }

    /**
     * Returns a camel-cased string using the JAXB rules,
     * where the first component is lowercased. Note that
     * if the first component is an acronym, the whole
     * thigns gets lowercased.
     * Always starts with a lowercase letter that is a valid
     * java identifier start. (If JAXB rules don't produce
     * one, then "x" is prepended.)
     */
    public static String lowerCamelCase(String xml_name) {
        return lowerCamelCase(xml_name, false, true);
    }

    /**
     * Returns a camel-cased string using the JAXB or JAX-RPC rules
     */
    public static String lowerCamelCase(String xml_name, boolean useJaxRpcRules,
                                        boolean fixGeneratedName) {
        StringBuilder buf = new StringBuilder();
        List<String> words = splitWords(xml_name, useJaxRpcRules);

        if (words.size() > 0) {
            String first = words.get(0).toLowerCase(Locale.ROOT);
            char f = first.charAt(0);
            if (!Character.isJavaIdentifierStart(f) && fixGeneratedName) {
                buf.append("x");
            }
            buf.append(first);

            Iterator<String> itr = words.iterator();
            itr.next(); // skip already-lowercased word
            while (itr.hasNext()) {
                buf.append(itr.next());
            }
        }
        return buf.toString();
    }

    public static String upperCaseFirstLetter(String s) {
        if (s.length() == 0 || Character.isUpperCase(s.charAt(0))) {
            return s;
        }

        StringBuilder buf = new StringBuilder(s);
        buf.setCharAt(0, Character.toUpperCase(buf.charAt(0)));
        return buf.toString();
    }


    /**
     * split an xml name into words via JAXB approach, upcasing first
     * letter of each word as needed, if upcase is true
     * <p>
     * ncname is xml ncname (i.e. no colons).
     */
    private static void addCapped(List<String> list, String str) {
        if (str.length() > 0) {
            list.add(upperCaseFirstLetter(str));
        }
    }

    public static List<String> splitWords(String name, boolean useJaxRpcRules) {
        List<String> list = new ArrayList<>();
        int len = name.length();
        int start = 0;
        int prefix = START;
        for (int i = 0; i < len; i++) {
            int current = getCharClass(name.charAt(i), useJaxRpcRules);
            if (prefix != PUNCT && current == PUNCT) {
                addCapped(list, name.substring(start, i));
                while ((current = getCharClass(name.charAt(i), useJaxRpcRules)) == PUNCT) {
                    if (++i >= len) {
                        return list;
                    }
                }
                start = i;
            } else if ((prefix == DIGIT) != (current == DIGIT) ||
                       (prefix == LOWER && current != LOWER) ||
                       (isLetter(prefix) != isLetter(current))) {
                addCapped(list, name.substring(start, i));
                start = i;
            } else if (prefix == UPPER && current == LOWER && i > start + 1) {
                addCapped(list, name.substring(start, i - 1));
                start = i - 1;
            }
            prefix = current;
        }
        addCapped(list, name.substring(start));
        return list;
    }

    //char classes
    private final static int START = 0;
    private final static int PUNCT = 1;
    private final static int DIGIT = 2;
    private final static int MARK = 3;
    private final static int UPPER = 4;
    private final static int LOWER = 5;
    private final static int NOCASE = 6;

    public static int getCharClass(char c, boolean useJaxRpcRules) {
        //ordering is important here.
        if (isPunctuation(c, useJaxRpcRules)) {
            return PUNCT;
        } else if (Character.isDigit(c)) {
            return DIGIT;
        } else if (Character.isUpperCase(c)) {
            return UPPER;
        } else if (Character.isLowerCase(c)) {
            return LOWER;
        } else if (Character.isLetter(c)) {
            return NOCASE;
        } else if (Character.isJavaIdentifierPart(c)) {
            return MARK;
        } else {
            return PUNCT; // not covered by JAXB: treat it as punctuation
        }
    }

    private static boolean isLetter(int state) {
        return (state == UPPER
                || state == LOWER
                || state == NOCASE);
    }

    public static boolean isPunctuation(char c, boolean useJaxRpcRules) {
        return (c == HYPHEN
                || c == PERIOD
                || c == COLON
                || c == DOT
                || (c == USCORE && !useJaxRpcRules)
                || c == TELEIA
                || c == AYAH
                || c == ELHIZB);
    }

    /**
     * Intended to be applied to a lowercase-starting identifier that
     * may collide with a Java keyword.  If it does collide, this
     * prepends the letter "x".
     */
    public static String nonJavaKeyword(String word) {
        if (isJavaReservedWord(word)) {
            return 'x' + word;
        }
        return word;
    }

    /**
     * Intended to be applied to a lowercase-starting identifier that
     * may collide with a Java keyword.  If it does collide, this
     * prepends the letter "x".
     */
    public static String nonExtraKeyword(String word) {
        return isExtraReservedWord(word) ? word + "Value" : word;
    }

    /**
     * Intended to be applied to an uppercase-starting identifier that
     * may collide with a java.lang.* classname.  If it does collide, this
     * prepends the letter "X".
     */
    public static String nonJavaCommonClassName(String name) {
        if (isJavaCommonClassName(name)) {
            return "X" + name;
        }
        return name;
    }

    private static boolean isJavaReservedWord(String word) {
        return javaWords.contains(word.toLowerCase(Locale.ROOT));
    }

    private static boolean isExtraReservedWord(String word) {
        return extraWords.contains(word.toLowerCase(Locale.ROOT));
    }

    public static boolean isJavaCommonClassName(String word) {
        return javaNames.contains(word);
    }
}
