/*
 * 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.axis2.corba.idl;

import org.apache.axis2.corba.exceptions.PreProcessorException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class PreProcessorInputStream extends InputStream {

    public static int MAX_DEPTH = 99;

    protected String[] userIncludePaths;
    protected String[] systemIncludePaths;
    protected String currentFile;
    protected String parentPath;
    protected StringBuffer idlContent;
    protected int contentLength;
    protected int lastRead = 0;

    public PreProcessorInputStream(String parentPath, String idlFilename)
            throws PreProcessorException {
        this(parentPath, idlFilename, new String[] {}, new String[] {});
    }

    public PreProcessorInputStream(String parentPath, String idlFilename,
            String[] userIncludePaths, String[] systemIncludePaths)
            throws PreProcessorException {
        this.userIncludePaths = userIncludePaths;
        this.systemIncludePaths = systemIncludePaths;
        this.parentPath = parentPath;
        this.currentFile = parentPath + File.separator + idlFilename;
        InputStream idlStream = getInputStream(parentPath, idlFilename);
        if (idlFilename == null)
            throw new PreProcessorException("Cannot find the file "
                    + parentPath + File.separator + idlFilename);

        idlContent = readIdl(idlStream, 0);
        contentLength = idlContent.length();
    }

    protected StringBuffer readIdl(InputStream idlStream, int depth)
            throws PreProcessorException {
        StringBuffer buffer = new StringBuffer();
        LineNumberReader lineNumberReader = new LineNumberReader(
                new InputStreamReader(idlStream));
        lineNumberReader.setLineNumber(1);
        String line;
        Map defs = new HashMap();
        Stack ifdefValue = new Stack();
        boolean validLine = true;
        boolean elseNotValid = false;
        String lastLine = null;
        while (true) {
            try {
                line = lineNumberReader.readLine();
            } catch (IOException e) {
                throw new PreProcessorException("Error while reading next line"
                        + getLineNoString(lineNumberReader), e);
            }
            if (line == null) {
                break;
            } else if (line.startsWith("#")) {
                line = line.trim();
            }

            if (lastLine != null) {
                line = lastLine + " " + line;
                lastLine = null;
            }

            if (!ifdefValue.empty()
                    && !((Boolean) ifdefValue.peek()).booleanValue()
                    && !line.startsWith("#")) {
                continue;
            } else if (line.startsWith("#") && line.endsWith("\\")) {
                lastLine = line.substring(0, line.lastIndexOf("\\"));
                continue;
            } else if (line.startsWith("#include") && validLine) {
                if (depth < MAX_DEPTH) {
                    String inc = line.replaceAll("#include", "").trim();
                    addComment(buffer, line);
                    InputStream incis = resolveInclude(inc,
                            getLineNoString(lineNumberReader));
                    buffer.append(readIdl(incis, depth + 1));
                    addComment(buffer, "end of " + line);
                } else {
                    throw new PreProcessorException("More than " + MAX_DEPTH
                            + " nested #includes are not allowed"
                            + getLineNoString(lineNumberReader));
                }
            } else if (line.startsWith("#define")) {
                String def = line.replaceAll("#define", "").trim();
                def = def.replaceAll("\"", "");
                StringTokenizer tok = new StringTokenizer(def, " ");
                if (tok.countTokens() == 1) {
                    def = tok.nextToken();
                    if (defs.containsKey(def))
                        throw new PreProcessorException("Variable " + def
                                + " is already defined"
                                + getLineNoString(lineNumberReader));
                    defs.put(def, null);
                } else if (tok.countTokens() == 2) {
                    defs.put(tok.nextToken(), tok.nextToken());
                }
                addComment(buffer, line);
            } else if (line.startsWith("#undef")) {
                String def = line.replaceAll("#undef", "").trim();
                def = def.replaceAll("\"", "");
                if (defs.containsKey(def)) {
                    defs.remove(def);
                } else {
                    throw new PreProcessorException("Undifined variable " + def
                            + getLineNoString(lineNumberReader));
                }
                addComment(buffer, line);
            } else if (line.startsWith("#ifdef")) {
                String def = line.replaceAll("#ifdef", "").trim();
                def = def.replaceAll("\"", "");
                if (defs.containsKey(def)) {
                    ifdefValue.push(Boolean.TRUE);
                } else {
                    validLine = false;
                    ifdefValue.push(Boolean.FALSE);
                }
                elseNotValid = false;
                addComment(buffer, line);
            } else if (line.startsWith("#ifndef")) {
                String def = line.replaceAll("#ifndef", "").trim();
                def = def.replaceAll("\"", "");
                if (defs.containsKey(def)) {
                    validLine = false;
                    ifdefValue.push(Boolean.FALSE);
                } else {
                    ifdefValue.push(Boolean.TRUE);
                }
                elseNotValid = false;
                addComment(buffer, line);
            } else if (line.startsWith("#else")) {
                if (elseNotValid)
                    throw new PreProcessorException("Invalid #else preprocessor directive" + getLineNoString(lineNumberReader));
                    
                // invert last element
                boolean lastval = ((Boolean) ifdefValue.peek()).booleanValue();
                ifdefValue.setElementAt(new Boolean(!lastval), ifdefValue.size() - 1);
                validLine = isAllTrue(ifdefValue);
                elseNotValid = true;
                addComment(buffer, line);
            } else if (line.startsWith("#endif")) {
                if (ifdefValue.empty())
                    throw new PreProcessorException("Invalid #endif preprocessor directive" + getLineNoString(lineNumberReader));
                ifdefValue.pop();
                validLine = isAllTrue(ifdefValue);
                elseNotValid = false;
                addComment(buffer, line);
            } else if (line.startsWith("#")) {
                // TODO: log
                System.out
                        .println("Ignoring unsupported preprocessor directive "
                                + line + getLineNoString(lineNumberReader));
            } else if (validLine) {
                buffer.append(line);
                buffer.append('\n');
                // System.out.println(line);
            }
        }

        if (!ifdefValue.empty()) {
            throw new PreProcessorException(
                    "One or more #ifdef/#ifndef preprocessor directives are not properly closed" + getLineNoString(lineNumberReader));
        }

        try {
            lineNumberReader.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return buffer;
    }

    protected InputStream resolveInclude(String include, String lineNoString)
            throws PreProcessorException {
        try {
            File incFile;
            if (include.startsWith("\"") && include.startsWith("\"")) {
                include = include.replaceAll("\"", "");
                incFile = new File(include);
                if (incFile.exists()) {
                    currentFile = incFile.getAbsolutePath();
                    return new FileInputStream(incFile);
                }

                InputStream stream = getInputStream(parentPath, include);
                if (stream != null)
                    return stream;

                for (int i = 0; i < userIncludePaths.length; i++) {
                    if (userIncludePaths[i].endsWith(File.separator)) {
                        incFile = new File(userIncludePaths[i] + include);
                    } else {
                        incFile = new File(userIncludePaths[i] + File.separator
                                + include);
                    }
                    if (incFile.exists()) {
                        currentFile = incFile.getAbsolutePath();
                        return new FileInputStream(incFile);
                    }
                }

                throw new PreProcessorException("Unable to resolve include "
                        + include + lineNoString);

            } else if (include.startsWith("<") && include.startsWith(">")) {
                include = include.replaceAll("<", "");
                include = include.replaceAll(">", "");

                for (int i = 0; i < systemIncludePaths.length; i++) {
                    if (systemIncludePaths[i].endsWith(File.separator)) {
                        incFile = new File(systemIncludePaths[i] + include);
                    } else {
                        incFile = new File(systemIncludePaths[i]
                                + File.separator + include);
                    }
                    if (incFile.exists()) {
                        currentFile = incFile.getAbsolutePath();
                        return new FileInputStream(incFile);
                    }
                }
                throw new PreProcessorException("Unable to resolve include "
                        + include + lineNoString);
            } else {
                throw new PreProcessorException(
                        "Include name must be enclosed in '< >' or '\" \"'"
                                + lineNoString);
            }
        } catch (FileNotFoundException e) {
            throw new PreProcessorException("Unable to resolve include "
                    + include + lineNoString, e);
        }
    }

    protected InputStream getInputStream(String parent, String filename)
            throws PreProcessorException {
        File parentFile = new File(parent);
        try {
            if (parentFile.isDirectory()) {
                return new FileInputStream(parent + File.separator + filename);
            } else {
                ZipInputStream zin = new ZipInputStream(new FileInputStream(
                        parentFile));
                ZipEntry entry;
                while ((entry = zin.getNextEntry()) != null) {
                    if (entry.getName().equalsIgnoreCase(filename)) {
                        return zin;
                    }
                }
                return null;
            }
        } catch (IOException e) {
            throw new PreProcessorException("Unable to pre-process file " + parent
                    + File.separator + filename, e);
        }
    }

    private boolean isAllTrue(Stack stack) {
        if (stack.empty()) {
            return true;
        } else {
            for (Iterator iterator = stack.iterator(); iterator.hasNext();) {
                Boolean value = (Boolean) iterator.next();
                if (!value.booleanValue()) {
                    return false;
                }
            }
            return true;
        }
    }

    private void addComment(StringBuffer buffer, String line) {
        buffer.append("/* ");
        buffer.append(line);
        buffer.append(" */\n");
    }

    private String getLineNoString(LineNumberReader lineNumberReader) {
        if (lineNumberReader != null) {
            int lineNo = lineNumberReader.getLineNumber();
            if (lineNo > 0) {
                return " (file:" + currentFile + ", line:" + (lineNo - 1) + ")";
            }
        }
        return "";
    }

    public int read() throws IOException {
        return (contentLength > lastRead) ? idlContent.charAt(lastRead++) : -1;
    }
}
