/*******************************************************************************
 * Copyright (c) 2013, 2018 Red Hat, Inc.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Neil Guzman - python implementation (B#350065)
 *******************************************************************************/
package org.eclipse.linuxtools.internal.rpmstubby.parser;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.linuxtools.internal.rpmstubby.StubbyLog;

/**
 * Class to parse a Python setup.py to grab specfile properties
 *
 */
public class PythonEggParser {

    private Map<String, String> variables;
    private Map<String, String> setupOptions;
    private IFile file;

    /**
     * Initialize and then parse the file
     *
     * @param file The Python setup.py file
     * @throws CoreException Throws CoreException
     * @throws IOException  Throws IOException
     */
    public PythonEggParser(IFile file) throws IOException, CoreException {
        setupOptions = new HashMap<>();
        variables = new HashMap<>();
        // end if file is empty or cannot get its contents
        if (file.getContents().available() <= 0) {
            return;
        }
        this.file = file;
        parse();
    }

    /**
     * Parse the contents of the Python setup.py file and grab
     * variables and meta-data from the setup(...) function
     *
     */
    public void parse() {
        String line = "";
        String setupLine = "";
        List<String> vars = new ArrayList<>();
        int offset = 0;
        try (RandomAccessFile raf = new RandomAccessFile(file.getRawLocation().makeAbsolute().toFile(), "r")){
            // end if cannot find setup(
            long bytesToSkip = findStartSetup(raf);
            if (bytesToSkip == -1) {
                return;
            }

            // end if the end of setup cannot be found
            long stop = findEndSetup(raf, bytesToSkip);
            if (stop == -1) {
                return;
            }

            raf.seek(0);
            while ((line = raf.readLine()) != null) {
                if (!line.trim().startsWith("#")) {
                    if (isLineSimpleDefinition(line)) {
                        vars.add(line);
                    } else if (!vars.isEmpty() && vars.get(vars.size()-1).trim().endsWith("\\") && isLineContinuation(line)){
                        offset = vars.get(vars.size()-1).lastIndexOf('\\');
                        vars.set(vars.size() -1, vars.get(vars.size() - 1).substring(0, offset));
                        vars.set(vars.size() - 1, vars.get(vars.size() - 1)
                                .concat(line.trim()));
                    }
                }
            }

            raf.seek(bytesToSkip);
            while ((line = raf.readLine()) != null && raf.getFilePointer() <= stop) {
                line = line.trim();
                if (!line.startsWith("#")) {
                    if (setupLine.equals("")) {
                        setupLine = line.trim();
                    } else {
                        setupLine = setupLine.concat(line.trim());
                    }
                }
            }

            List<String> list = prepareSetupOptions(setupLine);

            for (String str : vars) {
                variables.putAll(parseLine(str));
            }

            for (String str : list) {
                setupOptions.putAll(parseLine(str));
            }

            resolveVariables(variables, setupOptions);
        } catch (IOException e) {
            StubbyLog.logError(e);
        }
    }

    /**
     * Check to see if the string passed in is a function
     *
     * @param str The string to check
     * @return True if the string matches the function regex
     */
    public boolean checkFunction(String str) {
        boolean rc = false;
        Pattern pattern = Pattern.compile("\\s*\\w*\\s*?\\(.*\\)\\s*");
        Matcher variableMatcher = pattern.matcher(str);

        if (variableMatcher.matches()) {
            rc = true;
        }

        return rc;
    }

    /**
     * Get the value of the variable
     *
     * @param key The variable to get the value of
     * @return The value of the variable
     */
    public String getValue(String key) {
        String rc = "";
        Pattern pattern = Pattern.compile("\\s*\\((.+)\\)\\s*");
        Matcher variableMatcher = null;

        if (setupOptions.containsKey(key)) {
            rc = setupOptions.get(key).replaceAll("('|\")", "").trim();
            variableMatcher = pattern.matcher(rc);
            if (variableMatcher.matches()) {
                rc = variableMatcher.group(1);
            }
        }

        return rc;
    }

    /**
     * Get the list of strings for a key.
     * Use with classifiers, platforms, install_requires, etc.
     *
     * @param key The variable to get the value of
     * @return The value of the variable
     */
    public List<String> getValueList(String key) {
        List<String> rc = new ArrayList<>();
        Pattern pattern = Pattern.compile("^\\[(.*)\\]");

        if (setupOptions.containsKey(key)) {
            Matcher variableMatcher = pattern.matcher(setupOptions.get(key).trim());
            if (variableMatcher.find()) {
                String[] temp = variableMatcher.group(1).replaceAll("('|\")", "").split(",");
                for (String str : temp) {
                    if (!str.isEmpty() && !str.trim().startsWith("#")) {
                        rc.add(str.trim());
                    }
                }
            }
        }

        return rc;
    }

    /**
     * Prepare the setup options by returning each comma delimited option
     *
     * @param setupLine The single string containing all the setup options
     * @return A list of setup options
     */
    private static List<String> prepareSetupOptions(String setupLine) {
        List<String> rc = new ArrayList<>();
        // match the setup(...) pattern
        Pattern pattern = Pattern.compile("\\bsetup\\b(\\s+)?\\((.*)\\)");
        Matcher variableMatcher = pattern.matcher(setupLine);

        if (variableMatcher.find()) {
            setupLine = variableMatcher.group(2);
        }

        String[] tempList = setupLine.split("(?=,)");

        for (String str : tempList) {
            if (isOptionLineKeyValuePair(str) && !str.trim().startsWith("#")) {
                if (str.startsWith(",")) {
                    str = str.substring(1, str.length()).trim();
                }
                rc.add(str);
            } else if (!str.trim().startsWith("#") && !rc.isEmpty()) {
                rc.set(rc.size() - 1, rc.get(rc.size() - 1).concat(str.trim()));
            }
        }

        return rc;
    }

    /**
     * Resolves the setup option variables if they are referencing a
     * define from outside the setup() function.
     *
     * @param variables The variables outside the setup() function
     * @param options The options to be resolved within the setup() function
     */
    private static void resolveVariables(Map<String, String> variables, Map<String, String> options) {
        for (Entry<String, String> entry : options.entrySet()) {
            if (variables.containsKey(entry.getValue())) {
                options.put(entry.getKey(), variables.get(entry.getValue()));
            }
        }
    }

    /**
     * Check to see if the line in setup option is a new key->value pair
     *
     * @param line Line to check
     * @return True if the line contains a key->value
     */
    private static boolean isOptionLineKeyValuePair(String line) {
        boolean rc = false;
        Pattern pattern = Pattern.compile("(\\w+)(\\s+)?=[^=].*");
        Matcher variableMatcher = pattern.matcher(line.toLowerCase());

        if (variableMatcher.find()) {
            rc = true;
        }

        return rc;
    }

    /**
     * Check to see if the line is a simple variable declaration (var=value)
     *
     * @param line Line to check
     * @return True if it is a simple variable declaration
     */
    private static boolean isLineSimpleDefinition(String line) {
        boolean rc = false;
        Pattern pattern = Pattern.compile("^(\\w+)(\\s+)?=(\\s+)?");
        Matcher variableMatcher = pattern.matcher(line.toLowerCase());

        if (variableMatcher.find()) {
            rc = true;
        }

        return rc;
    }

    /**
     * Check to see if the line is a continuation from the previous.
     * It is a continuation from the previous if it starts
     * with a ' or "
     *
     * @param line Line to check
     * @return True if the line is a continuation
     */
    private static boolean isLineContinuation(String line) {
        boolean rc = false;
        Pattern pattern = Pattern.compile(".*[\'\"](/s+)?$");
        Matcher variableMatcher = pattern.matcher(line.toLowerCase());

        if (variableMatcher.find()) {
            rc = true;
        }

        return rc;
    }

    /**
     * Parse the line and split it into a key->value pair
     *
     * @param line The line to be parsed
     * @return The map containing the key->value pair
     */
    private static Map<String, String> parseLine(String line) {
        Map<String, String> rc = new HashMap<>();
        Pattern pattern = Pattern.compile("(\\s+)?(\\w+)(\\s+)?=(\\s+)?(.*)");
        Matcher variableMatcher = pattern.matcher(line);

        if (variableMatcher.find()) {
            String value = variableMatcher.group(5);
            if (value.charAt(value.length()-1) == ',') {
                value = value.substring(0, value.length()-1);
            }
            rc.put(variableMatcher.group(2), value);
        }

        return rc;
    }

    /**
     * Find the offset of when setup(...) starts
     *
     * @param reader The file reader
     * @return The position of the start of setup(...
     * @throws IOException
     */
    private static long findStartSetup(RandomAccessFile reader) throws IOException {
        long rc = -1;
        long previous = 0;
        Pattern pattern = Pattern.compile("^\\bsetup\\b(\\s+)?(\\()?");
        Matcher variableMatcher = null;
        String line = "";

        reader.seek(0);
        while ((line = reader.readLine()) != null && rc == -1) {
            variableMatcher = pattern.matcher(line.toLowerCase());
            if (variableMatcher.find()) {
                // get the previous line's file pointer location
                rc = previous;
            }
            previous = reader.getFilePointer();
        }

        return rc;
    }

    /**
     * Find the offset of when setup(...) ends based on the
     * position AFTER the closing bracket of setup()
     *
     * @param reader The file reader
     * @param startPosition The position of the start of setup(...
     * @return The position of the end of setup ...)
     * @throws IOException
     */
    private static long findEndSetup(RandomAccessFile reader, long startPosition) throws IOException {
        int bracketCounter = 0;
        boolean flag = false;
        boolean stop = false;
        String line = "";

        reader.seek(startPosition);
        while ((line = reader.readLine()) != null && !stop) {
            for (char x : line.toCharArray()) {
                if (x == '(') {
                    bracketCounter++;
                } else if (x == ')') {
                    bracketCounter--;
                }
                if (flag && bracketCounter == 0) {
                    stop = true;
                }
                // prevent ending prematurely
                if (bracketCounter != 0) {
                    flag = true;
                }
            }
        }

        return reader.getFilePointer();
    }
}
