/*
 * 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.felix.gogo.runtime;

import java.util.*;
import java.util.regex.Pattern;


public class Parser
{

    public static abstract class Executable extends Token
    {
        public Executable(Token cs)
        {
            super(cs);
        }
    }

    public static class Operator extends Executable
    {
        public Operator(Token cs) {
            super(cs);
        }
    }

    public static class Statement extends Executable
    {
        private final List<Token> tokens;
        private final List<Token> redirections;

        public Statement(Token cs, List<Token> tokens, List<Token> redirections)
        {
            super(cs);
            this.tokens = tokens;
            this.redirections = redirections;
        }

        public List<Token> tokens()
        {
            return tokens;
        }

        public List<Token> redirections() {
            return redirections;
        }
    }

    /**
     * pipe1 ; pipe2 ; ...
     */
    public static class Program extends Token
    {
        private final List<Executable> tokens;

        public Program(Token cs, List<Executable> tokens)
        {
            super(cs);
            this.tokens = tokens;
        }

        public List<Executable> tokens()
        {
            return tokens;
        }
    }

    /**
     * token1 | token2 | ...
     */
    public static class Pipeline extends Executable
    {
        private final List<Executable> tokens;

        public Pipeline(Token cs, List<Executable> tokens)
        {
            super(cs);
            this.tokens = tokens;
        }

        public List<Executable> tokens()
        {
            return tokens;
        }

    }

    /**
     * ( program )
     */
    public static class Sequence extends Executable
    {
        private final Program program;

        public Sequence(Token cs, Program program)
        {
            super(cs);
            this.program = program;
        }

        public Program program()
        {
            return program;
        }
    }

    /**
     * { program }
     */
    public static class Closure extends Token
    {
        private final Program program;

        public Closure(Token cs, Program program)
        {
            super(cs);
            this.program = program;
        }

        public Program program()
        {
            return program;
        }
    }

    /**
     * [ a b ...]
     * [ k1=v1 k2=v2 ...]
     */
    public static class Array extends Token
    {
        private final List<Token> list;
        private final Map<Token, Token> map;

        public Array(Token cs, List<Token> list, Map<Token, Token> map)
        {
            super(cs);
            assert list != null ^ map != null;
            this.list = list;
            this.map = map;
        }

        public List<Token> list()
        {
            return list;
        }

        public Map<Token, Token> map()
        {
            return map;
        }
    }

    protected final Tokenizer tz;
    protected final LinkedList<String> stack = new LinkedList<>();
    protected final List<Token> tokens = new ArrayList<>();
    protected final List<Statement> statements = new ArrayList<>();

    public Parser(CharSequence line)
    {
        this.tz = new Tokenizer(line);
    }

    public List<Token> tokens() {
        return Collections.unmodifiableList(tokens);
    }

    public List<Statement> statements() {
        Collections.sort(statements, new Comparator<Statement>() {
                    @Override
                    public int compare(Statement o1, Statement o2) {
                        return Integer.compare(o1.start, o2.start);
                    }
                });
        return Collections.unmodifiableList(statements);
    }

    public Program program()
    {
        List<Executable> tokens = new ArrayList<>();
        List<Executable> pipes = null;
        int start = tz.index - 1;
        while (true)
        {
            Statement ex;
            Token t = next();
            if (t == null)
            {
                if (pipes != null)
                {
                    throw new EOFError(tz.line, tz.column, "unexpected EOT while looking for a statement after |", getMissing("pipe"), "0");
                }
                else
                {
                    return new Program(whole(tokens, start), tokens);
                }
            }
            if (Token.eq("}", t) || Token.eq(")", t))
            {
                if (pipes != null)
                {
                    throw new EOFError(t.line, t.column, "unexpected token '" + t + "' while looking for a statement after |", getMissing("pipe"), "0");
                }
                else
                {
                    push(t);
                    return new Program(whole(tokens, start), tokens);
                }
            }
            else
            {
                push(t);
                ex = statement();
            }
            t = next();
            if (t == null || Token.eq(";", t) || Token.eq("\n", t) || Token.eq("&", t) || Token.eq("&&", t) || Token.eq("||", t))
            {
                if (pipes != null)
                {
                    pipes.add(ex);
                    tokens.add(new Pipeline(whole(pipes, start), pipes));
                    pipes = null;
                }
                else
                {
                    tokens.add(ex);
                }
                if (t == null)
                {
                    return new Program(whole(tokens, start), tokens);
                }
                else {
                    tokens.add(new Operator(t));
                }
            }
            else if (Token.eq("|", t) || Token.eq("|&", t))
            {
                if (pipes == null)
                {
                    pipes = new ArrayList<>();
                }
                pipes.add(ex);
                pipes.add(new Operator(t));
            }
            else
            {
                if (pipes != null)
                {
                    pipes.add(ex);
                    tokens.add(new Pipeline(whole(pipes, start), pipes));
                    pipes = null;
                }
                else
                {
                    tokens.add(ex);
                }
                push(t);
            }
        }
    }

    protected void push(Token t) {
        tz.push(t);
    }

    protected Token next() {
        boolean pushed = tz.pushed != null;
        Token token = tz.next();
        if (!pushed && token != null) {
            tokens.add(token);
        }
        return token;
    }

    public Sequence sequence()
    {
        Token start = start("(", "sequence");
        expectNotNull();
        Program program = program();
        Token end = end(")");
        return new Sequence(whole(start, end), program);
    }

    public Closure closure()
    {
        Token start = start("{", "closure");
        expectNotNull();
        Program program = program();
        Token end = end("}");
        return new Closure(whole(start, end), program);
    }

    private static final Pattern redirNoArg = Pattern.compile("[0-9]?>&[0-9-]|[0-9-]?<&[0-9-]");
    private static final Pattern redirArg = Pattern.compile("[0-9&]?>|[0-9]?>>|[0-9]?<|[0-9]?<>|<<<");
    private static final Pattern redirHereDoc = Pattern.compile("<<-?");

    public Statement statement()
    {
        List<Token> tokens = new ArrayList<>();
        List<Token> redirs = new ArrayList<>();
        boolean needRedirArg = false;
        int start = tz.index;
        while (true)
        {
            Token t = next();
            if (t == null
                    || Token.eq("\n", t)
                    || Token.eq(";", t)
                    || Token.eq("&", t)
                    || Token.eq("&&", t)
                    || Token.eq("||", t)
                    || Token.eq("|", t)
                    || Token.eq("|&", t)
                    || Token.eq("}", t)
                    || Token.eq(")", t)
                    || Token.eq("]", t))
            {
                if (needRedirArg)
                {
                    throw new EOFError(tz.line, tz.column, "Expected file name for redirection", "redir", "foo");
                }
                push(t);
                break;
            }
            if (Token.eq("{", t))
            {
                push(t);
                tokens.add(closure());
            }
            else if (Token.eq("[", t))
            {
                push(t);
                tokens.add(array());
            }
            else if (Token.eq("(", t))
            {
                push(t);
                tokens.add(sequence());
            }
            else if (needRedirArg)
            {
                redirs.add(t);
                needRedirArg = false;
            }
            else if (redirNoArg.matcher(t).matches())
            {
                redirs.add(t);
            }
            else if (redirArg.matcher(t).matches())
            {
                redirs.add(t);
                needRedirArg = true;
            }
            else if (redirHereDoc.matcher(t).matches())
            {
                redirs.add(t);
                redirs.add(tz.readHereDoc(t.charAt(t.length() - 1) == '-'));
            }
            else
            {
                tokens.add(t);
            }
        }
        Statement statement = new Statement(whole(tokens, start), tokens, redirs);
        statements.add(statement);
        return statement;
    }

    public Array array()
    {
        Token start = start("[", "array");
        Boolean isMap = null;
        List<Token> list = new ArrayList<>();
        Map<Token, Token> map = new LinkedHashMap<>();
        while (true)
        {
            Token key = next();
            if (key == null)
            {
                throw new EOFError(tz.line, tz.column, "unexpected EOT", getMissing(), "]");
            }
            if (Token.eq("]", key))
            {
                push(key);
                break;
            }
            if (Token.eq("\n", key))
            {
                continue;
            }
            if (Token.eq("{", key) || Token.eq(";", key) || Token.eq("&", key) || Token.eq("&&", key) || Token.eq("||", key)
                    || Token.eq("|", key) || Token.eq("|&", key) || Token.eq(")", key) || Token.eq("}", key) || Token.eq("=", key))
            {
                throw new SyntaxError(key.line(), key.column(), "unexpected token '" + key + "' while looking for array key");
            }
            if (Token.eq("(", key))
            {
                push(key);
                key = sequence();
            }
            if (Token.eq("[", key))
            {
                push(key);
                key = array();
            }
            if (isMap == null)
            {
                Token n = next();
                if (n == null)
                {
                    throw new EOFError(tz.line, tz.column, "unexpected EOF while looking for array token", getMissing(), "]");
                }
                isMap = Token.eq("=", n);
                push(n);
            }
            if (isMap)
            {
                expect("=");
                Token val = next();
                if (val == null)
                {
                    throw new EOFError(tz.line, tz.column, "unexpected EOF while looking for array value", getMissing(), "0");
                }
                else if (Token.eq(";", val) || Token.eq("&", val) || Token.eq("&&", val) || Token.eq("||", val) || Token.eq("|", val) || Token.eq("|&", val)
                        || Token.eq(")", key) || Token.eq("}", key) || Token.eq("=", key))
                {
                    throw new SyntaxError(key.line(), key.column(), "unexpected token '" + key + "' while looking for array value");
                }
                else if (Token.eq("[", val))
                {
                    push(val);
                    val = array();
                }
                else if (Token.eq("(", val))
                {
                    push(val);
                    val = sequence();
                }
                else if (Token.eq("{", val))
                {
                    push(val);
                    val = closure();
                }
                map.put(key, val);
            }
            else
            {
                list.add(key);
            }
        }
        Token end = end("]");
        if (isMap == null || !isMap)
        {
            return new Array(whole(start, end), list, null);
        }
        else
        {
            return new Array(whole(start, end), null, map);
        }
    }

    protected void expectNotNull()
    {
        Token t = next();
        if (t == null)
        {
            throw new EOFError(tz.line, tz.column,
                    "unexpected EOT",
                    getMissing(), "0");
        }
        push(t);
    }

    private String getMissing() {
        return getMissing(null);
    }

    private String getMissing(String additional) {
        StringBuilder sb = new StringBuilder();
        LinkedList<String> stack = this.stack;
        if (additional != null) {
            stack = new LinkedList<>(stack);
            stack.addLast(additional);
        }
        String last = null;
        int nb = 0;
        for (String cur : stack) {
            if (last == null) {
                last = cur;
                nb = 1;
            } else if (last.equals(cur)) {
                nb++;
            } else {
                if (sb.length() > 0) {
                    sb.append(" ");
                }
                sb.append(last);
                if (nb > 1) {
                    sb.append("(").append(nb).append(")");
                }
                last = cur;
                nb = 1;
            }
        }
        if (sb.length() > 0) {
            sb.append(" ");
        }
        sb.append(last);
        if (nb > 1) {
            sb.append("(").append(nb).append(")");
        }
        return sb.toString();
    }

    protected Token start(String str, String missing) {
        stack.addLast(missing);
        return expect(str);
    }

    protected Token end(String str) {
        Token t = expect(str);
        stack.removeLast();
        return t;
    }

    protected Token expect(String str)
    {
        Token start = next();
        if (start == null)
        {
            throw new EOFError(tz.line, tz.column,
                    "unexpected EOT looking for '" + str + "",
                    getMissing(), str);
        }
        if (!Token.eq(str, start))
        {
            throw new SyntaxError(start.line, start.column, "expected '" + str + "' but got '" + start.toString() + "'");
        }
        return start;
    }

    protected Token whole(List<? extends Token> tokens, int index)
    {
        if (tokens.isEmpty())
        {
            index = Math.min(index, tz.text().length());
            return tz.text().subSequence(index, index);
        }
        Token b = tokens.get(0);
        Token e = tokens.get(tokens.size() - 1);
        return whole(b, e);
    }

    protected Token whole(Token b, Token e)
    {
        return tz.text.subSequence(b.start - tz.text.start, e.start + e.length() - tz.text.start);
    }

}
