/*
 * 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.olingo.server.core.uri.parser;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.olingo.commons.api.ODataRuntimeException;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
import org.apache.olingo.server.core.uri.UriInfoImpl;
import org.apache.olingo.server.core.uri.antlr.UriLexer;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.BatchEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.CrossjoinEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CustomQueryOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FormatOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.IdOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;

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

public class Parser {
  int logLevel = 0;

  private enum ParserEntryRules {
    All, Batch, CrossJoin, Entity, ExpandItems, FilterExpression, Metadata, PathSegment, Orderby, Select
  };

  public Parser setLogLevel(final int logLevel) {
    this.logLevel = logLevel;
    return this;
  }

  public UriInfo parseUri(final String path, final String query, final String fragment, final Edm edm)
      throws UriParserException {

    UriContext context = new UriContext();
    UriParseTreeVisitor uriParseTreeVisitor = new UriParseTreeVisitor(edm, context);

    try {
      final RawUri uri = UriDecoder.decodeUri(path, query, fragment, 0); // -> 0 segments are before the service url

      // first, read the decoded path segments
      final String firstSegment = uri.pathSegmentListDecoded.isEmpty() ? "" : uri.pathSegmentListDecoded.get(0);

      if (firstSegment.isEmpty()) {
        ensureLastSegment(firstSegment, 0, uri.pathSegmentListDecoded.size());
        context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
      } else if (firstSegment.startsWith("$batch")) {
        ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
        BatchEOFContext ctxBatchEOF =
            (BatchEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.Batch);

        uriParseTreeVisitor.visitBatchEOF(ctxBatchEOF);
      } else if (firstSegment.startsWith("$metadata")) {
        ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
        MetadataEOFContext ctxMetadataEOF =
            (MetadataEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.Metadata);

        uriParseTreeVisitor.visitMetadataEOF(ctxMetadataEOF);

        context.contextUriInfo.setFragment(uri.fragment);
      } else if (firstSegment.startsWith("$entity")) {

        context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
        if (uri.pathSegmentListDecoded.size() > 1) {
          final String typeCastSegment = uri.pathSegmentListDecoded.get(1);
          ensureLastSegment(typeCastSegment, 2, uri.pathSegmentListDecoded.size());
          EntityEOFContext ctxEntityEOF =
              (EntityEOFContext) parseRule(typeCastSegment, ParserEntryRules.Entity);
          uriParseTreeVisitor.visitEntityEOF(ctxEntityEOF);
        }

      } else if (firstSegment.startsWith("$all")) {
        ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
        AllEOFContext ctxResourcePathEOF =
            (AllEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.All);

        uriParseTreeVisitor.visitAllEOF(ctxResourcePathEOF);
      } else if (firstSegment.startsWith("$crossjoin")) {
        ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
        CrossjoinEOFContext ctxResourcePathEOF =
            (CrossjoinEOFContext) parseRule(uri.pathSegmentListDecoded.get(0), ParserEntryRules.CrossJoin);

        uriParseTreeVisitor.visitCrossjoinEOF(ctxResourcePathEOF);
      } else {
        List<PathSegmentEOFContext> ctxPathSegments = new ArrayList<PathSegmentEOFContext>();
        for (String pathSegment : uri.pathSegmentListDecoded) {
          PathSegmentEOFContext ctxPathSegment =
              (PathSegmentEOFContext) parseRule(pathSegment, ParserEntryRules.PathSegment);
          ctxPathSegments.add(ctxPathSegment);
        }

        context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource);

        for (PathSegmentEOFContext ctxPathSegment : ctxPathSegments) {
          // add checks for batch, entity, metadata, all, crossjoin
          uriParseTreeVisitor.visitPathSegmentEOF(ctxPathSegment);
        }

        UriResource lastSegment = context.contextUriInfo.getLastResourcePart();
        if (lastSegment instanceof UriResourcePartTyped) {
          UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;

          UriParseTreeVisitor.TypeInformation myType = uriParseTreeVisitor.getTypeInformation(typed);
          UriParseTreeVisitor.TypeInformation typeInfo =
              uriParseTreeVisitor.new TypeInformation(myType.type, typed.isCollection());
          context.contextTypes.push(typeInfo);
        }
      }

      // second, read the system query options and the custom query options
      for (RawUri.QueryOption option : uri.queryOptionListDecoded) {
        if (option.name.startsWith("$")) {
          SystemQueryOption systemOption = null;
          if (option.name.equals(SystemQueryOptionKind.FILTER.toString())) {
            FilterExpressionEOFContext ctxFilterExpression =
                (FilterExpressionEOFContext) parseRule(option.value, ParserEntryRules.FilterExpression);

            FilterOptionImpl filterOption =
                (FilterOptionImpl) uriParseTreeVisitor.visitFilterExpressionEOF(ctxFilterExpression);

            systemOption = filterOption;

          } else if (option.name.equals(SystemQueryOptionKind.FORMAT.toString())) {
            FormatOptionImpl formatOption = new FormatOptionImpl();
            formatOption.setName(option.name);
            formatOption.setText(option.value);
            if (option.value.equalsIgnoreCase(ODataFormat.JSON.name())
                || option.value.equalsIgnoreCase(ODataFormat.XML.name())
                || option.value.equalsIgnoreCase(ODataFormat.ATOM.name())
                || isFormatSyntaxValid(option.value)) {
              formatOption.setFormat(option.value);
            } else {
              throw new UriParserSyntaxException("Illegal value of $format option!",
                  UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION_FORMAT, option.value);
            }
            systemOption = formatOption;

          } else if (option.name.equals(SystemQueryOptionKind.EXPAND.toString())) {
            ExpandItemsEOFContext ctxExpandItems =
                (ExpandItemsEOFContext) parseRule(option.value, ParserEntryRules.ExpandItems);

            ExpandOptionImpl expandOption =
                (ExpandOptionImpl) uriParseTreeVisitor.visitExpandItemsEOF(ctxExpandItems);

            systemOption = expandOption;

          } else if (option.name.equals(SystemQueryOptionKind.ID.toString())) {
            IdOptionImpl idOption = new IdOptionImpl();
            idOption.setName(option.name);
            idOption.setText(option.value);
            idOption.setValue(option.value);
            systemOption = idOption;
          } else if (option.name.equals(SystemQueryOptionKind.LEVELS.toString())) {
            throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
                UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
          } else if (option.name.equals(SystemQueryOptionKind.ORDERBY.toString())) {
            OrderByEOFContext ctxOrderByExpression =
                (OrderByEOFContext) parseRule(option.value, ParserEntryRules.Orderby);

            OrderByOptionImpl orderByOption =
                (OrderByOptionImpl) uriParseTreeVisitor.visitOrderByEOF(ctxOrderByExpression);

            systemOption = orderByOption;
          } else if (option.name.equals(SystemQueryOptionKind.SEARCH.toString())) {
            throw new RuntimeException("System query option '$search' not implemented!");
          } else if (option.name.equals(SystemQueryOptionKind.SELECT.toString())) {
            SelectEOFContext ctxSelectEOF =
                (SelectEOFContext) parseRule(option.value, ParserEntryRules.Select);

            SelectOptionImpl selectOption =
                (SelectOptionImpl) uriParseTreeVisitor.visitSelectEOF(ctxSelectEOF);

            systemOption = selectOption;
          } else if (option.name.equals(SystemQueryOptionKind.SKIP.toString())) {
            SkipOptionImpl skipOption = new SkipOptionImpl();
            skipOption.setName(option.name);
            skipOption.setText(option.value);
            try {
              skipOption.setValue(Integer.parseInt(option.value));
            } catch (final NumberFormatException e) {
              throw new UriParserSyntaxException("Illegal value of $skip option!", e,
                  UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
                  option.name, option.value);
            }
            systemOption = skipOption;
          } else if (option.name.equals(SystemQueryOptionKind.SKIPTOKEN.toString())) {
            SkipTokenOptionImpl skipTokenOption = new SkipTokenOptionImpl();
            skipTokenOption.setName(option.name);
            skipTokenOption.setText(option.value);
            skipTokenOption.setValue(option.value);
            systemOption = skipTokenOption;
          } else if (option.name.equals(SystemQueryOptionKind.TOP.toString())) {
            TopOptionImpl topOption = new TopOptionImpl();
            topOption.setName(option.name);
            topOption.setText(option.value);
            try {
              topOption.setValue(Integer.parseInt(option.value));
            } catch (final NumberFormatException e) {
              throw new UriParserSyntaxException("Illegal value of $top option!", e,
                  UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
                  option.name, option.value);
            }
            systemOption = topOption;
          } else if (option.name.equals(SystemQueryOptionKind.COUNT.toString())) {
            CountOptionImpl inlineCountOption = new CountOptionImpl();
            inlineCountOption.setName(option.name);
            inlineCountOption.setText(option.value);
            if (option.value.equals("true") || option.value.equals("false")) {
              inlineCountOption.setValue(Boolean.parseBoolean(option.value));
            } else {
              throw new UriParserSyntaxException("Illegal value of $count option!",
                  UriParserSyntaxException.MessageKeys.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
                  option.name, option.value);
            }
            systemOption = inlineCountOption;
          } else {
            throw new UriParserSyntaxException("Unknown system query option!",
                UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, option.name);
          }
          try {
            context.contextUriInfo.setSystemQueryOption(systemOption);
          } catch (final ODataRuntimeException e) {
            throw new UriParserSyntaxException("Double system query option!", e,
                UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, option.name);
          }
        } else {
          CustomQueryOptionImpl customOption = new CustomQueryOptionImpl();
          customOption.setName(option.name);
          customOption.setText(option.value);
          context.contextUriInfo.addCustomQueryOption(customOption);
        }
      }

      return context.contextUriInfo;
    } catch (ParseCancellationException e) {
      throw e.getCause() instanceof UriParserException ?
          (UriParserException) e.getCause() :
          new UriParserSyntaxException("Syntax error", e, UriParserSyntaxException.MessageKeys.SYNTAX);
    }
  }

  private void ensureLastSegment(final String segment, final int pos, final int size)
      throws UriParserSyntaxException {
    if (pos < size) {
      throw new UriParserSyntaxException(segment + " must be the last segment.",
          UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT, segment);
    }
  }

  private boolean isFormatSyntaxValid(final String value) {
    final int index = value.indexOf('/');
    return index > 0 && index < value.length() - 1 && index == value.lastIndexOf('/');
  }

  private ParserRuleContext parseRule(final String input, final ParserEntryRules entryPoint)
      throws UriParserSyntaxException {
    UriParserParser parser = null;
    UriLexer lexer = null;
    ParserRuleContext ret = null;

    // Use 2 stage approach to improve performance
    // see https://github.com/antlr/antlr4/issues/192

    // stage = 1
    try {

      // create parser
      if (logLevel > 0) {
        lexer = new UriLexer(new ANTLRInputStream(input));
        showTokens(input, lexer.getAllTokens());
      }

      lexer = new UriLexer(new ANTLRInputStream(input));
      parser = new UriParserParser(new CommonTokenStream(lexer));

      // Set error strategy
      addStage1ErrorStategy(parser);

      // Set error collector
      addStage1ErrorListener(parser);

      // user the faster LL parsing
      parser.getInterpreter().setPredictionMode(PredictionMode.SLL);

      // parse
      switch (entryPoint) {
      case All:
        ret = parser.allEOF();
        break;
      case Batch:
        ret = parser.batchEOF();
        break;
      case CrossJoin:
        ret = parser.crossjoinEOF();
        break;
      case Metadata:
        ret = parser.metadataEOF();
        break;
      case PathSegment:
        ret = parser.pathSegmentEOF();
        break;
      case FilterExpression:
        lexer.mode(Lexer.DEFAULT_MODE);
        ret = parser.filterExpressionEOF();
        break;
      case Orderby:
        lexer.mode(Lexer.DEFAULT_MODE);
        ret = parser.orderByEOF();
        break;
      case ExpandItems:
        lexer.mode(Lexer.DEFAULT_MODE);
        ret = parser.expandItemsEOF();
        break;
      case Entity:
        ret = parser.entityEOF();
        break;
      case Select:
        ret = parser.selectEOF();
        break;
      default:
        break;

      }

    } catch (ParseCancellationException hardException) {
      // stage = 2
      try {

        // create parser
        lexer = new UriLexer(new ANTLRInputStream(input));
        parser = new UriParserParser(new CommonTokenStream(lexer));

        // Set error strategy
        addStage2ErrorStategy(parser);

        // Set error collector
        addStage2ErrorListener(parser);

        // Use the slower SLL parsing
        parser.getInterpreter().setPredictionMode(PredictionMode.LL);

        // parse
        switch (entryPoint) {
        case All:
          ret = parser.allEOF();
          break;
        case Batch:
          ret = parser.batchEOF();
          break;
        case CrossJoin:
          ret = parser.crossjoinEOF();
          break;
        case Metadata:
          ret = parser.metadataEOF();
          break;
        case PathSegment:
          ret = parser.pathSegmentEOF();
          break;
        case FilterExpression:
          lexer.mode(Lexer.DEFAULT_MODE);
          ret = parser.filterExpressionEOF();
          break;
        case Orderby:
          lexer.mode(Lexer.DEFAULT_MODE);
          ret = parser.orderByEOF();
          break;
        case ExpandItems:
          lexer.mode(Lexer.DEFAULT_MODE);
          ret = parser.expandItemsEOF();
          break;
        case Entity:
          ret = parser.entityEOF();
          break;
        case Select:
          ret = parser.selectEOF();
          break;
        default:
          break;
        }

      } catch (final RecognitionException weakException) {
        throw new UriParserSyntaxException("Error in syntax", weakException,
            UriParserSyntaxException.MessageKeys.SYNTAX);

        // exceptionOnStage = 2;
      }
    } catch (final RecognitionException hardException) {
      throw new UriParserSyntaxException("Error in syntax", hardException,
          UriParserSyntaxException.MessageKeys.SYNTAX);
    }

    return ret;
  }

  protected void addStage1ErrorStategy(final UriParserParser parser) {
    // Throw exception at first syntax error
    parser.setErrorHandler(new BailErrorStrategy());

  }

  protected void addStage2ErrorStategy(final UriParserParser parser) {
    // Throw exception at first syntax error
    parser.setErrorHandler(new BailErrorStrategy());
  }

  protected void addStage1ErrorListener(final UriParserParser parser) {
    // No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
    parser.removeErrorListeners();
    parser.addErrorListener(new CheckFullContextListener());

  }

  protected void addStage2ErrorListener(final UriParserParser parser) {
    // No error logging to System.out or System.err, only exceptions used (depending on ErrorStrategy)
    parser.removeErrorListeners();
  }

  public void showTokens(final String input, final List<? extends Token> list) {
    boolean first = true;
    System.out.println("input: " + input);
    String nL = "\n";
    String out = "[" + nL;
    for (Token token : list) {
      if (!first) {
        out += ",";
        first = false;
      }
      int index = token.getType();
      if (index != -1) {
        out += "\"" + token.getText() + "\"" + "     " + UriLexer.tokenNames[index] + nL;
      } else {
        out += "\"" + token.getText() + "\"" + "     " + index + nL;
      }
    }
    out += ']';
    System.out.println("tokens: " + out);
    return;
  }

}
