//
// 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.
//

import org.apache.asterix.graphix.common.metadata.GraphElementIdentifier;
import org.apache.asterix.graphix.lang.expression.GraphConstructor;
import org.apache.asterix.graphix.lang.statement.CreateGraphStatement;
import org.apache.asterix.graphix.lang.statement.GraphDropStatement;
import org.apache.asterix.graphix.lang.statement.GraphElementDecl;
import org.apache.asterix.lang.sqlpp.parser.ParseException;
import org.apache.asterix.lang.sqlpp.parser.SqlppParseException;
import org.apache.asterix.lang.sqlpp.parser.Token;

@new_at_the_class_def
public GraphElementDecl parseGraphElementBody(GraphElementIdentifier identifier) throws CompilationException {
    return parseImpl(new ParseFunction<GraphElementDecl>() {
        @Override
        public GraphElementDecl parse() throws ParseException {
            DataverseName dataverse = defaultDataverse;
            defaultDataverse = identifier.getGraphIdentifier().getDataverseName();

            // We borrow the ViewBody production, where we have a SelectExpression or a VariableRef.
            createNewScope();
            Expression elementBodyExpr = GraphixParser.this.ViewBody();
            removeCurrentScope();

            defaultDataverse = dataverse;
            return new GraphElementDecl(identifier, elementBodyExpr);
        }
    });
}

@merge
Statement CreateStatement() throws ParseException:
{
  // merge area 1
  before:
  after:
}
{
  (
    // merge area 2
    before:
    after:    | stmt = CreateGraphStatement(startToken, false)
  )
  {
    // merge area 3
  }
}

@merge
Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException:
{
  // merge area 1
  before:
  after:
}
{
  (
    // merge area 2
    before:
    after:    | stmt = CreateGraphStatement(startStmtToken, true)
  )
  {
    // merge area 3
  }
}

@merge
Statement DropStatement() throws ParseException:
{
  // merge area 1
  before:
  after:
}
{
  (
    // merge area 2
    before:
    after:    | stmt = DropGraphStatement(startToken)
  )
  {
    // merge area 3
  }
}

@new
CreateGraphStatement CreateGraphStatement(Token startStmtToken, boolean orReplace) throws ParseException:
{
  CreateGraphStatement stmt = null;
}
{
  <GRAPH> stmt = CreateGraphSpecification(startStmtToken, orReplace)
  {
    return stmt;
  }
}

@new
CreateGraphStatement CreateGraphSpecification(Token startStmtToken, boolean orReplace) throws ParseException:
{
  Pair<DataverseName, Identifier> nameComponents = null;
  GraphConstructor graphConstructor = null;
  boolean ifNotExists = false;
}
{
  nameComponents = QualifiedName()
  ifNotExists = IfNotExists()
  {
    if (orReplace && ifNotExists) {
      throw new SqlppParseException(getSourceLocation(startStmtToken), "Unexpected IF NOT EXISTS");
    }
  }
  <AS> graphConstructor = GraphConstructor(token)
  {
    CreateGraphStatement stmt = new CreateGraphStatement(nameComponents.first, nameComponents.second.getValue(),
        orReplace, ifNotExists, graphConstructor);
    return addSourceLocation(stmt, startStmtToken);
  }
}

@new
GraphDropStatement DropGraphStatement(Token startStmtToken) throws ParseException:
{
   GraphDropStatement stmt = null;
}
{
  <GRAPH> stmt = DropGraphSpecification(startStmtToken)
  {
    return stmt;
  }
}

@new
GraphDropStatement DropGraphSpecification(Token startStmtToken) throws ParseException:
{
  Pair<DataverseName, Identifier> pairId = null;
  boolean ifExists = false;
}
{
  pairId = QualifiedName() ifExists = IfExists()
  {
    GraphDropStatement stmt = new GraphDropStatement(pairId.first, pairId.second.getValue(), ifExists);
    return addSourceLocation(stmt, startStmtToken);
  }
}

@new
Pair<List<Integer>, List<List<String>>> KeyFields() throws ParseException:
{
  Pair<List<Integer>, List<List<String>>> keyFields = null;
}
{
  // This is essentially an alias for the production PrimaryKeyFields.
  keyFields = PrimaryKeyFields()
  {
    return keyFields;
  }
}

@new
GraphConstructor GraphConstructor(Token startStmtToken) throws ParseException:
{
  List<GraphConstructor.VertexElement> vertexElements = new ArrayList<GraphConstructor.VertexElement>();
  List<GraphConstructor.EdgeElement> edgeElements = new ArrayList<GraphConstructor.EdgeElement>();
  GraphConstructor.VertexElement vertexElement = null;
  GraphConstructor.EdgeElement edgeElement = null;
}
{
  vertexElement = GraphVertexSpecification(startStmtToken) { vertexElements.add(vertexElement); }
  ( <COMMA>
    (
      ( vertexElement = GraphVertexSpecification(token) { vertexElements.add(vertexElement); } )
      | ( edgeElement = GraphEdgeSpecification(token) { edgeElements.add(edgeElement); } )
    )
  )*
  {
    GraphConstructor graphConstructor = new GraphConstructor(vertexElements, edgeElements);
    return addSourceLocation(graphConstructor, startStmtToken);
  }
}

@new
GraphConstructor.VertexElement GraphVertexSpecification(Token startStmtToken) throws ParseException:
{
  Pair<List<Integer>, List<List<String>>> primaryKeyFields;
  Token beginPos = null, endPos = null;
  Expression vertexDefinitionExpr;
  String vertexName;
}
{
  <VERTEX>
  vertexName = GraphVertexDefinitionPattern()
  <PRIMARY> <KEY> <LEFTPAREN> primaryKeyFields = KeyFields() <RIGHTPAREN>
  <AS>
  {
    beginPos = token;
    createNewScope();
  }
  (
    vertexDefinitionExpr = ViewBody()
    | <LEFTPAREN> vertexDefinitionExpr = ViewBody() <RIGHTPAREN>
  )
  {
    endPos = token;
    String vDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
    removeCurrentScope();
    GraphConstructor.VertexElement vertexElement = new GraphConstructor.VertexElement(vertexName,
      primaryKeyFields.second, primaryKeyFields.first, vertexDefinitionExpr, vDef);
    return addSourceLocation(vertexElement, startStmtToken);
  }
}

@new
String GraphVertexDefinitionPattern() throws ParseException:
{
  String vertexName;
}
{
  <LEFTPAREN> <COLON> vertexName = Identifier() <RIGHTPAREN>
  {
    return vertexName;
  }
}

@new
GraphConstructor.EdgeElement GraphEdgeSpecification(Token startStmtToken) throws ParseException:
{
  Pair<Triple<String, String, String>, Boolean> edgeDefinitionPattern;
  Pair<List<Integer>, List<List<String>>> keyFields;
  Token beginPos = null, endPos = null;
  Expression edgeDefinitionExpr = null;

  List<Integer> destinationKeySourceIndicators = null;
  List<Integer> sourceKeySourceIndicators = null;
  List<Integer> primaryKeySourceIndicators = null;
  List<List<String>> destinationKeyFields = null;
  List<List<String>> sourceKeyFields = null;
  List<List<String>> primaryKeyFields = null;
}
{
  <EDGE>
  edgeDefinitionPattern = GraphEdgeDefinitionPattern()
  (
    (
      <PRIMARY> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
      {
        primaryKeyFields = keyFields.second;
        primaryKeySourceIndicators = keyFields.first;
      }
      <SOURCE> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
      {
        sourceKeyFields = keyFields.second;
        sourceKeySourceIndicators = keyFields.first;
      }
      <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
      {
        destinationKeyFields = keyFields.second;
        destinationKeySourceIndicators = keyFields.first;
      }
      <AS>
      {
        beginPos = token;
        createNewScope();
      }
      (
        edgeDefinitionExpr = ViewBody()
        | <LEFTPAREN> edgeDefinitionExpr = ViewBody() <RIGHTPAREN>
      )
    )
    |
    (
      <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
      {
        destinationKeyFields = keyFields.second;
        destinationKeySourceIndicators = keyFields.first;
      }
    )
  )
  {
    String destinationLabel, edgeLabel, sourceLabel;
    if (edgeDefinitionPattern.second) { // isDirectedLeft
      sourceLabel = edgeDefinitionPattern.first.third;
      edgeLabel = edgeDefinitionPattern.first.second;
      destinationLabel = edgeDefinitionPattern.first.first;
    } else {
      sourceLabel = edgeDefinitionPattern.first.first;
      edgeLabel = edgeDefinitionPattern.first.second;
      destinationLabel = edgeDefinitionPattern.first.third;
    }

    String eDef = null;
    if (edgeDefinitionExpr != null) {
      endPos = token;
      eDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
      removeCurrentScope();
    }

    GraphConstructor.EdgeElement edgeElement = new GraphConstructor.EdgeElement(edgeLabel, destinationLabel,
        sourceLabel, primaryKeyFields, primaryKeySourceIndicators, destinationKeyFields, destinationKeySourceIndicators,
        sourceKeyFields, sourceKeySourceIndicators, edgeDefinitionExpr, eDef);
    return addSourceLocation(edgeElement, startStmtToken);
  }
}

@new
Pair<Triple<String, String, String>, Boolean> GraphEdgeDefinitionPattern() throws ParseException:
{
  String leftVertexName, edgeName, rightVertexName;
  boolean isDirectedLeft;
}
{
  leftVertexName = GraphVertexDefinitionPattern()
  ( <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> <GT> { isDirectedLeft = false; }
  | <LT> <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> { isDirectedLeft = true; } )
  rightVertexName = GraphVertexDefinitionPattern()
  {
    Triple<String, String, String> t = new Triple<String, String, String>(leftVertexName, edgeName, rightVertexName);
    return new Pair<Triple<String, String, String>, Boolean>(t, isDirectedLeft);
  }
}

@new
<DEFAULT,IN_DBL_BRACE>
TOKEN [IGNORE_CASE]:
{
  <DESTINATION: "destination">
  | <EDGE: "edge">
  | <GRAPH: "graph">
  | <SOURCE: "source">
  | <VERTEX: "vertex">
}

@new_at_the_end
<DEFAULT,IN_DBL_BRACE>
TOKEN :
{
  <BAR: "|">
}