/*
 * 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.openjpa.lib.meta;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.openjpa.lib.util.ClassUtil;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;

import serp.bytecode.lowlevel.ConstantPoolTable;

/**
 * Parser used to resolve arguments into java classes.
 * Interprets command-line args as either class names, .class files or
 * resources, .java files or resources, or metadata files or resources
 * conforming to the common format defined by {@link CFMetaDataParser}.
 * Transforms the information in these args into {@link Class} instances.
 * Note that when parsing .java files, only the main class in the file
 * is detected. Other classes defined in the file, such as inner classes,
 * are not added to the returned classes list.
 *
 * @author Abe White
 */
public class ClassArgParser {

    private static final int TOKEN_EOF = -1;
    private static final int TOKEN_NONE = 0;
    private static final int TOKEN_PACKAGE = 1;
    private static final int TOKEN_CLASS = 2;
    private static final int TOKEN_PACKAGE_NOATTR = 3;
    private static final int TOKEN_CLASS_NOATTR = 4;

    private static final Localizer _loc = Localizer.forPackage
        (ClassArgParser.class);

    private ClassLoader _loader = null;
    private char[] _packageAttr = "name".toCharArray();
    private char[] _classAttr = "name".toCharArray();
    private char[][] _beginElements = { { 'p' }, { 'c' } };
    private char[][] _endElements = { "ackage".toCharArray(),
        "lass".toCharArray() };

    /**
     * The class loader with which to load parsed classes.
     */
    public ClassLoader getClassLoader() {
        return _loader;
    }

    /**
     * The class loader with which to load parsed classes.
     */
    public void setClassLoader(ClassLoader loader) {
        _loader = loader;
    }

    /**
     * Set the the relevant metadata file structure so that metadata files
     * containing class names can be parsed. Null attribute names indicate
     * that the text content of the element contains the data.
     */
    public void setMetaDataStructure(String packageElementName,
        String packageAttributeName, String[] classElementNames,
        String classAttributeName) {
        // calculate how many chars deep we have to go to identify each element
        // name as unique.  this is extremely inefficient for large N, but
        // should never be called for more than a few elements
        char[] buf = new char[classElementNames.length + 1];
        int charIdx = 0;
        for (; true; charIdx++) {
            for (int i = 0; i < buf.length; i++) {
                if (i == 0) {
                    if (charIdx == packageElementName.length())
                        throw new UnsupportedOperationException(_loc.get
                            ("cant-diff-elems").getMessage());
                    buf[i] = packageElementName.charAt(charIdx);
                } else {
                    if (charIdx == classElementNames[i - 1].length())
                        throw new UnsupportedOperationException(_loc.get
                            ("cant-diff-elems").getMessage());
                    buf[i] = classElementNames[i - 1].charAt(charIdx);
                }
            }
            if (charsUnique(buf))
                break;
        }

        _packageAttr = (packageAttributeName == null) ? null
            : packageAttributeName.toCharArray();
        _classAttr = (classAttributeName == null) ? null
            : classAttributeName.toCharArray();
        _beginElements = new char[classElementNames.length + 1][];
        _endElements = new char[classElementNames.length + 1][];
        _beginElements[0] = packageElementName.substring(0, charIdx + 1).
            toCharArray();
        _endElements[0] = packageElementName.substring(charIdx + 1).
            toCharArray();
        for (int i = 0; i < classElementNames.length; i++) {
            _beginElements[i + 1] = classElementNames[i].
                substring(0, charIdx + 1).toCharArray();
            _endElements[i + 1] = classElementNames[i].
                substring(charIdx + 1).toCharArray();
        }
    }

    /**
     * Return true if all characters in given buffer are unique.
     */
    private static boolean charsUnique(char[] buf) {
        for (int i = buf.length - 1; i >= 0; i--)
            for (int j = 0; j < i; j++)
                if (buf[j] == buf[i])
                    return false;
        return true;
    }

    /**
     * Return the {@link Class} representation of the class(es) named in the
     * given arg.
     *
     * @param arg a class name, .java file, .class file, or metadata
     * file naming the type(s) to act on
     */
    public Class<?>[] parseTypes(String arg) {
        String[] names = parseTypeNames(arg);
        Class<?>[] objs = new Class[names.length];
        for (int i = 0; i < names.length; i++)
            objs[i] = ClassUtil.toClass(names[i], _loader);
        return objs;
    }

    /**
     * Return the {@link Class} representation of the class(es) named in the
     * given metadatas.
     */
    public Class<?>[] parseTypes(MetaDataIterator itr) {
        String[] names = parseTypeNames(itr);
        Class<?>[] objs = new Class[names.length];
        for (int i = 0; i < names.length; i++)
            objs[i] = ClassUtil.toClass(names[i], _loader);
        return objs;
    }

    /**
     * Return a mapping of each metadata resource to an array of its
     * contained classes.
     */
    public Map<Object, Class<?>[]> mapTypes(MetaDataIterator itr) {
        Map<Object, String[]> map = mapTypeNames(itr);
        Map<Object, Class<?>[]> rval = new HashMap<>();
        Map.Entry<Object, String[]> entry;
        String[] names;
        Class<?>[] objs;
        for (Iterator<Map.Entry<Object, String[]>> i =
            map.entrySet().iterator(); i.hasNext();) {
            entry = i.next();
            names = entry.getValue();
            objs = new Class[names.length];
            for (int j = 0; j < names.length; j++) {
                objs[j] = ClassUtil.toClass(names[j], _loader);
            }
            rval.put(entry.getKey(), objs);
        }
        return rval;
    }

    /**
     * Return the names of the class(es) from the given arg.
     *
     * @param arg a class name, .java file, .class file, or metadata
     * file naming the type(s) to act on
     * @throws IllegalArgumentException with appropriate message on error
     */
    public String[] parseTypeNames(String arg) {
        if (arg == null)
            return new String[0];

        try {
            File file = Files.getFile(arg, _loader);
            if (arg.endsWith(".class"))
                return new String[]{ getFromClassFile(file) };
            if (arg.endsWith(".java"))
                return new String[]{ getFromJavaFile(file) };
            if ((AccessController.doPrivileged(
                J2DoPrivHelper.existsAction(file))).booleanValue()) {
                Collection<String> col = getFromMetaDataFile(file);
                return col.toArray(new String[col.size()]);
            }
        } catch (Exception e) {
            throw new RuntimeException(
                _loc.get("class-arg", arg).getMessage(), e);
        }

        // must be a class name
        return new String[]{ arg };
    }

    /**
     * Return the names of the class(es) from the given metadatas.
     */
    public String[] parseTypeNames(MetaDataIterator itr) {
        if (itr == null)
            return new String[0];

        List<String> names = new ArrayList<>();
        Object source = null;
        try {
            while (itr.hasNext()) {
                source = itr.next();
                appendTypeNames(source, itr.getInputStream(), names);
            }
        } catch (Exception e) {
            throw new RuntimeException(
                _loc.get("class-arg", source).getMessage(), e);
        }
        return names.toArray(new String[names.size()]);
    }

    /**
     * Parse the names in the given metadata iterator stream, closing the
     * stream on completion.
     */
    private void appendTypeNames(Object source, InputStream in,
        List<String> names) throws IOException {
        try {
            if (source.toString().endsWith(".class"))
                names.add(getFromClass(in));
            names.addAll(getFromMetaData(new InputStreamReader(in)));
        } finally {
            try {
                in.close();
            } catch (IOException ioe) {
            }
        }
    }

    /**
     * Return a mapping of each metadata resource to an array of its contained
     * class names.
     */
    public Map<Object, String[]> mapTypeNames(MetaDataIterator itr) {
        if (itr == null)
            return Collections.emptyMap();

        Map<Object, String []> map = new HashMap<>();
        Object source = null;
        List<String> names = new ArrayList<>();
        try {
            while (itr.hasNext()) {
                source = itr.next();
                appendTypeNames(source, itr.getInputStream(), names);
                if (!names.isEmpty()) {
                    map.put(source, names.toArray(new String[names.size()]));
                }
                names.clear();
            }
        } catch (Exception e) {
            throw new RuntimeException(
                _loc.get("class-arg", source).getMessage(), e);
        }
        return map;
    }

    /**
     * Returns the class named in the given .class file.
     */
    private String getFromClassFile(File file) throws IOException {
        FileInputStream fin = null;
        try {
            fin = AccessController.doPrivileged(
                J2DoPrivHelper.newFileInputStreamAction(file));
            return getFromClass(fin);
        } catch (PrivilegedActionException pae) {
            throw (FileNotFoundException) pae.getException();
        } finally {
            if (fin != null)
                try {
                    fin.close();
                } catch (IOException ioe) {
                }
        }
    }

    /**
     * Returns the class name in the given .class bytecode.
     */
    private String getFromClass(InputStream in) throws IOException {
        ConstantPoolTable table = new ConstantPoolTable(in);
        int idx = table.getEndIndex();
        idx += 2; // access flags
        int clsEntry = table.readUnsignedShort(idx);
        int utfEntry = table.readUnsignedShort(table.get(clsEntry));
        return table.readString(table.get(utfEntry)).replace('/', '.');
    }

    /**
     * Returns the class named in the given .java file.
     */
    private String getFromJavaFile(File file) throws IOException {
        BufferedReader in = null;
        try {
            // find the line with the package declaration
            in = new BufferedReader(new FileReader(file));
            String line;
            StringBuilder pack = null;
            while ((line = in.readLine()) != null) {
                line = line.trim();
                if (line.startsWith("package ")) {
                    line = line.substring(8).trim();

                    // strip off anything beyond the package declaration
                    pack = new StringBuilder();
                    for (int i = 0; i < line.length(); i++) {
                        if (Character.isJavaIdentifierPart(line.charAt(i))
                            || line.charAt(i) == '.')
                            pack.append(line.charAt(i));
                        else
                            break;
                    }
                    break;
                }
            }

            // strip '.java'
            String clsName = file.getName();
            clsName = clsName.substring(0, clsName.length() - 5);

            // prefix with package
            if (pack != null && pack.length() > 0)
                clsName = pack + "." + clsName;

            return clsName;
        } finally {
            if (in != null)
                try { in.close(); } catch (IOException ioe) {}
        }
    }

    /**
     * Returns the classes named in the given common format metadata file.
     */
    private Collection<String> getFromMetaDataFile(File file)
        throws IOException {
        FileReader in = null;
        try {
            in = new FileReader(file);
            return getFromMetaData(in);
        } finally {
            if (in != null)
                try {
                    in.close();
                } catch (IOException ioe) {
                }
        }
    }

    /**
     * Returns the classes named in the given common format metadata stream.
     */
    private Collection<String> getFromMetaData(Reader xml) throws IOException {
        Collection<String> names = new ArrayList<>();
        BufferedReader in = new BufferedReader(xml);

        boolean comment = false;
        int token = TOKEN_NONE;
        String pkg = "";
        String name;
        read:
        for (int ch = 0, last = 0, last2 = 0;
            ch == '<' || (ch = in.read()) != -1; last2 = last, last = ch) {
            // handle comments
            if (comment && last2 == '-' && last == '-' && ch == '>') {
                comment = false;
                continue;
            }
            if (comment) {
                if (ch == '<') {
                    ch = in.read();
                    if (ch == -1)
                        break read;
                }
                continue;
            }
            if (last2 == '<' && last == '!' && ch == '-') {
                comment = true;
                continue;
            }

            // if not an element start, skip it
            if (ch != '<')
                continue;
            token = TOKEN_NONE; // reset token
            last = ch; // update needed for comment detection
            ch = readThroughWhitespace(in);
            if (ch == '/' || ch == '!' || ch == '?')
                continue;

            // read element name; look for packages and classes
            token = readElementToken(ch, in);
            switch (token) {
                case TOKEN_EOF:
                    break read;
                case TOKEN_PACKAGE:
                    pkg = readAttribute(in, _packageAttr);
                    if (pkg == null)
                        break read;
                    break;
                case TOKEN_PACKAGE_NOATTR:
                    pkg = readElementText(in);
                    if (pkg == null)
                        break read;
                    ch = '<'; // reading element text reads to next '<'
                    break;
                case TOKEN_CLASS:
                    name = readAttribute(in, _classAttr);
                    if (name == null)
                        break read;
                    if (pkg.length() > 0 && name.indexOf('.') == -1)
                        names.add(pkg + "." + name);
                    else
                        names.add(name);
                    break;
                case TOKEN_CLASS_NOATTR:
                    name = readElementText(in);
                    if (name == null)
                        break read;
                    ch = '<'; // reading element text reads to next '<'
                    if (pkg.length() > 0 && name.indexOf('.') == -1)
                        names.add(pkg + "." + name);
                    else
                        names.add(name);
                    break;
            }
        }
        return names;
    }

    /**
     * Read the name of the current XML element and return the matching token.
     */
    private int readElementToken(int ch, Reader in) throws IOException {
        // look through the beginning element names to find what element this
        // might be(if any)
        int matchIdx = -1;
        int matched = 0;
        int dq = 0;
        for (int beginIdx = 0; beginIdx < _beginElements[0].length; beginIdx++)
        {
            if (beginIdx != 0)
                ch = in.read();
            if (ch == -1)
                return TOKEN_EOF;

            matched = 0;
            for (int i = 0; i < _beginElements.length; i++) {
                if ((dq & (2 << i)) != 0)
                    continue;

                if (ch == _beginElements[i][beginIdx]) {
                    matchIdx = i;
                    matched++;
                } else
                    dq |= 2 << i;
            }

            if (matched == 0)
                break;
        }
        if (matched != 1)
            return TOKEN_NONE;

        // make sure the rest of the element name matches
        char[] match = _endElements[matchIdx];
        for (int i = 0; i < match.length; i++) {
            ch = in.read();
            if (ch == -1)
                return TOKEN_EOF;
            if (ch != match[i])
                return TOKEN_NONE;
        }

        // read the next char to make sure we finished the element name
        ch = in.read();
        if (ch == -1)
            return TOKEN_EOF;
        if (ch == '>') {
            if (matchIdx == 0 && _packageAttr == null)
                return TOKEN_PACKAGE_NOATTR;
            if (matchIdx != 0 && _classAttr == null)
                return TOKEN_CLASS_NOATTR;
        } else if (Character.isWhitespace((char) ch)) {
            if (matchIdx == 0 && _packageAttr != null)
                return TOKEN_PACKAGE;
            if (matchIdx != 0 && _classAttr != null)
                return TOKEN_CLASS;
        }
        return TOKEN_NONE;
    }

    /**
     * Read the attribute with the given name in chars of the current XML
     * element.
     */
    private String readAttribute(Reader in, char[] name) throws IOException {
        int expected = 0;
        for (int ch, last = 0; true; last = ch) {
            ch = in.read();
            if (ch == -1)
                return null;
            if (ch == '>')
                return "";

            // if not expected char or still looking for 'n' and previous
            // char is not whitespace, keep looking
            if (ch != name[expected] || (expected == 0 && last != 0
                && !Character.isWhitespace((char) last))) {
                expected = 0;
                continue;
            }

            // found expected char; have we found the whole "name"?
            expected++;
            if (expected == name.length) {
                // make sure the next char is '='
                ch = readThroughWhitespace(in);
                if (ch == -1)
                    return null;
                if (ch != '=') {
                    expected = 0;
                    continue;
                }

                // toss out any subsequent whitespace and the next char, which
                // is the opening quote for the attr value, then read until the
                // closing quote
                readThroughWhitespace(in);
                return readAttributeValue(in);
            }
        }
    }

    /**
     * Read the current text value until the next element.
     */
    private String readElementText(Reader in) throws IOException {
        StringBuilder buf = null;
        int ch;
        while (true) {
            ch = in.read();
            if (ch == -1)
                return null;
            if (ch == '<')
                break;
            if (Character.isWhitespace((char) ch))
                continue;
            if (buf == null)
                buf = new StringBuilder();
            buf.append((char) ch);
        }
        return (buf == null) ? "" : buf.toString();
    }

    /**
     * Read until the next non-whitespace character.
     */
    private int readThroughWhitespace(Reader in) throws IOException {
        int ch;
        while (true) {
            ch = in.read();
            if (ch == -1 || !Character.isWhitespace((char) ch))
                return ch;
        }
    }

    /**
     * Return the current attribute value.
     */
    private String readAttributeValue(Reader in) throws IOException {
        StringBuilder buf = new StringBuilder();
        int ch;
        while (true) {
            ch = in.read();
            if (ch == -1)
                return null;
            if (ch == '\'' || ch == '"')
                return buf.toString();
            buf.append((char) ch);
        }
    }
}
