/**
 * 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 com.taobao.weex.el.parse;

import com.taobao.weex.WXEnvironment;
import com.taobao.weex.utils.WXLogUtils;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by furture on 2017/8/28.
 * simple expression parse, less ast node and save memory
 */
public class Parser {

    private String code;
    private int position;
    private ArrayStack<Token> stacks;
    private ArrayStack<Symbol> operators;

    public Parser(String code){
        this.code = code;
        this.position = 0;
        this.stacks = new ArrayStack<>();
        this.operators = new ArrayStack<>();
    }


    public final Token parse(){
        while (hasNextToken()){
            scanNextToken();
        }
        while (!operators.isEmpty()){
            Symbol op = operators.pop();
            doOperator(op);
        }
        if(stacks.size() == 1){
            return  stacks.pop();
        }
        Block block = new Block(stacks.getList(), Token.TYPE_BLOCK);
        return block;
    }


    /**
     * parse code to ast block.
     * */
    public static Token parse(String code){
        try{
            Parser parser = new Parser(code);
            return parser.parse();
        }catch (Exception e){
            if(WXEnvironment.isApkDebugable()){
                WXLogUtils.e("code " + code, e);
            }
            return new Block(null, Token.TYPE_BLOCK);
        }
    }


    final char scanNextToken(){
        char ch = nextToken();
        if(ch == Operators.DOLLAR){
            position++;
            return ch;
        }else if(Character.isJavaIdentifierStart(ch)){
            scanIdentifier();
        }else if (ch == Operators.BRACKET_START || ch == Operators.BLOCK_START) {
            scanBracket();
        }else if (ch == Operators.ARRAY_START) {
            scanArray();
        }else if (ch ==  Operators.QUOTE || ch == Operators.SINGLE_QUOTE) {
            scanString();
        }else if((ch == Operators.DOT && Character.isDigit(code.charAt(position + 1)))
                || Character.isDigit(ch)){ //number .00 .00e6
            scanNumber();
        }else if(ch ==  Operators.CONDITION_IF){
            scanIf();
        }else if(ch ==  Operators.CONDITION_IF_MIDDLE
                || ch ==  Operators.BRACKET_END
                || ch == Operators.BLOCK_END
                || ch == Operators.SPACE
                || ch == Operators.ARRAY_END){
            position++;
            return ch;
        }else{
            scanOperator();
        }
        return ch;
    }


    final void  scanArray(){
        int stackSize = stacks.size();
        int opSize = operators.size();
        int type = Token.TYPE_IDENTIFIER;
        if(position - 1 < 0 || !Character.isJavaIdentifierPart(code.charAt(position - 1))){
            type = Token.TYPE_ARRAY;
        }
        operators.push(new Symbol(Operators.ARRAY_START_STR, stacks.size()));
        position++;
        while (hasNextToken()){
            char token = scanNextToken();
            if(token == Operators.ARRAY_END){
                break;
            }
        }

        if(stacks.size() <= stackSize){ // empty bracket, none need, save memory
            while (operators.size() > opSize){
                operators.pop();
            }
            return;
        }

        while (operators.size() > opSize){
            Symbol op = operators.pop();
            if(stacks.size() > stackSize){
                doOperator(op);
            }
        }
        List<Token> tokens = new ArrayList<>(4);
        for(int i=stackSize; i<stacks.size(); i++){
            tokens.add(stacks.get(i));
        }
        while (stacks.size() > stackSize){
            stacks.pop();
        }
        if(type == Token.TYPE_ARRAY || stacks.size() == 0){
            Block block = new Block(tokens, Token.TYPE_ARRAY);
            stacks.push(block);
            return;
        }

        Token identifer = stacks.pop();
        Token second = null;
        if(tokens.size() == 1){
            second = tokens.get(0);
        }else{
            second = new Block(tokens, Token.TYPE_BLOCK);
        }
        Operator operator = new Operator(Operators.DOT_STR, type);
        operator.first = identifer;
        operator.second = second;
        stacks.push(operator);
    }

    void  scanBracket(){
        int stackSize = stacks.size();
        int opSize = operators.size();
        if(code.charAt(position) == Operators.BLOCK_START){
            operators.push(new Symbol(Operators.BLOCK_START_STR, stacks.size()));
            position++;
            while (hasNextToken()){
                if(scanNextToken() == Operators.BLOCK_END){
                    break;
                }
            }
        }else{
            operators.push(new Symbol(Operators.BRACKET_START_STR, stacks.size()));
            position++;
            while (hasNextToken()){
                if(scanNextToken() == Operators.BRACKET_END){
                    break;
                }
            }
        }
        if(stacks.size() <= stackSize){ // empty bracket, none need, save memory
            while (operators.size() > opSize){
                operators.pop();
            }
            return;
        }
        while (operators.size() > opSize){
            Symbol op = operators.pop();
            if(stacks.size() > stackSize){
                doOperator(op);
            }
        }
        List<Token> tokens = new ArrayList<>(4);
        for(int i=stackSize; i<stacks.size(); i++){
            tokens.add(stacks.get(i));
        }
        while (stacks.size() > stackSize){
            stacks.pop();
        }
        if(tokens.size() == 1){
            stacks.push(tokens.get(0));
        }else{
            Block block = new Block(tokens, Token.TYPE_BLOCK);
            stacks.push(block);
        }
    }

    /**
     * 1  === (1 + 3) &&  1
     * scan operator
     * */
    void scanOperator(){
        int start = position;
        int length = Math.min(position + 3, code.length());
        String operator = code.substring(position, length);
        if(operator.length() >= 3){
            if(!Operators.OPERATORS_PRIORITY.containsKey(operator)){
                operator = operator.substring(0, 2);
            }
        }
        if(operator.length() >= 2){
            if(!Operators.OPERATORS_PRIORITY.containsKey(operator)){
                operator = operator.substring(0, 1);
            }
        }
        if(!Operators.OPERATORS_PRIORITY.containsKey(operator)){
            //just skip illegal character
            int illegalChar = Math.min(start + 1, code.length());
            WXLogUtils.e("weex", new IllegalArgumentException(code.substring(0, illegalChar) + " illegal code operator" + operator));
            position += operator.length();
            return;
        }
        if((!operators.isEmpty() && operators.peek() != null)){
            String preOp = operators.peek().op;
            if(Operators.OPERATORS_PRIORITY.get(preOp) >= Operators.OPERATORS_PRIORITY.get(operator)){
                Symbol op = operators.pop();
                doOperator(op);
            }
        }
        if(!Operators.isOpEnd(operator)){
            operators.push(new Symbol(operator, stacks.size()));
        }
        position += operator.length();
    }



    void doOperator(Symbol symbol){
        String op = symbol.op;
        if(Operators.BRACKET_START_STR.equals(symbol.op)
                || Operators.BLOCK_START_STR.equals(symbol.op)
                || Operators.ARRAY_START_STR.equals(symbol.op)
                || Operators.DOLLAR_STR.equals(symbol.op)){
            return;
        }
        if(Operators.BLOCK_START_STR.equals(symbol.op)){
            return;
        }
        int second = symbol.pos;
        int first  = Math.max(symbol.pos - 1, 0);
        if(!operators.isEmpty()){
            first = Math.max(first, operators.peek().pos);
        }

        Operator operator = new Operator(op, Token.TYPE_OPERATOR);
        if(Operators.AND_NOT.equals(op)){
            if(stacks.size() > second) {
                Token token = stacks.remove(second);
                operator.self = token;
                stacks.add(second, operator);
                return;
            }
            return; //invalid
        }
        if(stacks.size() > second) {
            operator.second = stacks.remove(second);
        }else{
            return;
        }
        if(stacks.size() > first) {
            operator.first = stacks.remove(first);
        }else{
            if(operator.second == null){
                return;
            }
        }
        stacks.add(first, operator);
    }

    /**
     * condition if
     * */
    void scanIf(){
        Operator operator = new Operator(Operators.CONDITION_IF_STRING, Token.TYPE_OPERATOR);
        int selfIndex = 0;
        doStackOperators(0);
        if(operators.size() > 0){
            selfIndex = Math.max(operators.peek().pos, selfIndex);
        }
        if(stacks.size() > selfIndex){
            operator.self = stacks.pop();
        }

        int stackSize = stacks.size();
        int leftOperatorSize = operators.size();
        position++;
        while (hasNextToken()){
            if(scanNextToken() == Operators.CONDITION_IF_MIDDLE){
                break;
            }
        }
        while (operators.size() > leftOperatorSize){
            Symbol symbol = operators.pop();
            doOperator(symbol);
        }

        while (stacks.size() > stackSize){
            operator.first = stacks.pop();
        }
        int rightOperatorsSize = operators.size();
        while (hasNextToken()){
            scanNextToken();
            if(hasNextToken()){
                scanNextToken();
            }
            if(operators.size() <= rightOperatorsSize){
                break;
            }
        }
        doStackOperators(rightOperatorsSize);
        while (stacks.size() > stackSize){
            operator.second = stacks.pop();
        }
        stacks.push(operator);
    }

    private final void doStackOperators(int operatorSize){
        while (operators.size() > operatorSize){
            Symbol symbol = operators.pop();
            doOperator(symbol);
        }
    }

    /**
     * 1+e6
     * .00
     * .00e6
     * 100
     * 199e5
     * */
    final void scanNumber(){
        boolean isInt = true;
        int start = position;
        if(code.charAt(position) == 'e' || code.charAt(position) == '.'){
            isInt = false;
        }
        position++;
        while (hasNext()){
            char ch = code.charAt(position);
            if(Character.isDigit(ch)
                    || ch == '.'
                    || ch =='e'){
                if(ch == 'e'
                        || ch == '.'){
                    isInt = false;
                }
                position++;
            }else{
                break;
            }
        }
        String number = code.substring(start, position);
        if(".".equals(number)){
            return;
        }
        Token stack = null;
        if(isInt){
            stack = new Token(number, Token.TYPE_INT);
        }else{
            stack = new Token(number, Token.TYPE_DOUBLE);
        }
        stacks.push(stack);
    }


    final void  scanString(){
        int start = position;
        ArrayStack operator = new ArrayStack();
        char quote = code.charAt(start);
        operator.push(quote);
        StringBuilder builder = new StringBuilder();
        for(position= start + 1; position<code.length(); position++){
            char ch = code.charAt(position);
            if(ch == quote){
                if(code.charAt(position -1) != '\\'){
                    operator.pop();
                    if(operator.size() == 0){
                       position++;
                       break;
                    }
                }else{
                    builder.deleteCharAt(builder.length()-1);
                    builder.append(ch);
                }
            }else{
                builder.append(ch);
            }
        }
        String string =  builder.toString();
        Token token = new Token(string, Token.TYPE_STRING);
        stacks.push(token);
    }



    /**
     * scan el expression.
     * item.ddd
     * ${item.dd}
     * $item.dd
     * */
    final void scanIdentifier(){
        int start = position;
        position++;
        while (hasNext()){
            char ch = code.charAt(position);
            if(Character.isJavaIdentifierPart(ch)){
               position++;
            }else{
                break;
            }
            //2.true
        }
        String el = code.substring(start, position);
        if(el.startsWith(Operators.DOLLAR_STR)){
            if(el.length() == Operators.DOLLAR_STR.length()){
                return;
            }
            el = el.substring(Operators.DOLLAR_STR.length());
        }
        int type = Token.TYPE_IDENTIFIER;
        if(Operators.KEYWORDS.containsKey(el)){
            if(!(!operators.isEmpty() && Operators.isDot(operators.peek().op))){
                type = Token.TYPE_KEYWORD;
            }
        }
        Token token = new Token(el, type);
        stacks.push(token);
    }


    final boolean hasNext(){
        return position < code.length();
    }



    final boolean hasNextToken(){
        while (hasNext()){
            char ch = code.charAt(position);
            if(ch == ' '){
                position++;
                continue;
            }
            return  true;
        }
        return false;
    }

    final char nextToken(){
        char ch = code.charAt(position);
        while (ch == ' '){
            position ++;
            if(code.length() >= position){
                break;
            }
            code.charAt(position);
        }
        return ch;
    }
}
