/*
 * 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 java.util.Collection;
import java.util.Map;

import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.uri.UriInfoKind;
import org.apache.olingo.server.api.uri.UriResourceNavigation;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
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.UriResourceComplexPropertyImpl;
import org.apache.olingo.server.core.uri.UriResourceCountImpl;
import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
import org.apache.olingo.server.core.uri.UriResourceRefImpl;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl;
import org.apache.olingo.server.core.uri.validator.UriValidationException;

public class ExpandParser {

  private final Edm edm;
  private final OData odata;
  private final Map<String, AliasQueryOption> aliases;
  private final Collection<String> crossjoinEntitySetNames;

  public ExpandParser(final Edm edm, final OData odata, final Map<String, AliasQueryOption> aliases,
      final Collection<String> crossjoinEntitySetNames) {
    this.edm = edm;
    this.odata = odata;
    this.aliases = aliases;
    this.crossjoinEntitySetNames = crossjoinEntitySetNames;
  }

  public ExpandOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType)
      throws UriParserException, UriValidationException {
    ExpandOptionImpl expandOption = new ExpandOptionImpl();
    do {
      // In the crossjoin case the start has to be an EntitySet name which will dictate the reference type
      if (crossjoinEntitySetNames != null && !crossjoinEntitySetNames.isEmpty()) {
        final ExpandItem item = parseCrossJoinItem(tokenizer);
        expandOption.addExpandItem(item);
      } else {
        final ExpandItem item = parseItem(tokenizer, referencedType);
        expandOption.addExpandItem(item);
      }
    } while (tokenizer.next(TokenKind.COMMA));

    return expandOption;
  }

  private ExpandItem parseCrossJoinItem(UriTokenizer tokenizer) throws UriParserSemanticException {
    ExpandItemImpl item = new ExpandItemImpl();
    if (tokenizer.next(TokenKind.STAR)) {
      item.setIsStar(true);
    } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
      String entitySetName = tokenizer.getText();
      if (crossjoinEntitySetNames.contains(entitySetName)) {
        UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
        final UriResourceEntitySetImpl entitySetResourceSegment =
            new UriResourceEntitySetImpl(edm.getEntityContainer().getEntitySet(entitySetName));
        resource.addResourcePart(entitySetResourceSegment);

        item.setResourcePath(resource);
      } else {
        throw new UriParserSemanticException("Unknown crossjoin entity set.",
            UriParserSemanticException.MessageKeys.UNKNOWN_PART, entitySetName);
      }
    } else {
      throw new UriParserSemanticException("If the target resource is a crossjoin an entity set is "
          + "needed as the starting point.",
          UriParserSemanticException.MessageKeys.UNKNOWN_PART);
    }
    return item;
  }

  private ExpandItem parseItem(UriTokenizer tokenizer, final EdmStructuredType referencedType)
      throws UriParserException, UriValidationException {
    ExpandItemImpl item = new ExpandItemImpl();
    if (tokenizer.next(TokenKind.STAR)) {
      item.setIsStar(true);
      if (tokenizer.next(TokenKind.SLASH)) {
        ParserHelper.requireNext(tokenizer, TokenKind.REF);
        item.setIsRef(true);
      } else if (tokenizer.next(TokenKind.OPEN)) {
        ParserHelper.requireNext(tokenizer, TokenKind.LEVELS);
        ParserHelper.requireNext(tokenizer, TokenKind.EQ);
        item.setSystemQueryOption((SystemQueryOption) parseLevels(tokenizer));
        ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
      }

    } else {
      final EdmStructuredType typeCast = ParserHelper.parseTypeCast(tokenizer, edm, referencedType);
      if (typeCast != null) {
        item.setTypeFilter(typeCast);
        ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
      }

      UriInfoImpl resource = parseExpandPath(tokenizer, edm, referencedType, item);

      UriResourcePartTyped lastPart = (UriResourcePartTyped) resource.getLastResourcePart();

      boolean hasSlash = false;
      EdmStructuredType typeCastSuffix = null;
      if (tokenizer.next(TokenKind.SLASH)) {
        hasSlash = true;
        if (lastPart instanceof UriResourceNavigation) {
          UriResourceNavigationPropertyImpl navigationResource = (UriResourceNavigationPropertyImpl) lastPart;
          final EdmNavigationProperty navigationProperty = navigationResource.getProperty();
          typeCastSuffix = ParserHelper.parseTypeCast(tokenizer, edm, navigationProperty.getType());
          if (typeCastSuffix != null) {
            if (navigationProperty.isCollection()) {
              navigationResource.setCollectionTypeFilter(typeCastSuffix);
            } else {
              navigationResource.setEntryTypeFilter(typeCastSuffix);
            }
            hasSlash = false;
          }
        }
      }

      final EdmStructuredType newReferencedType = typeCastSuffix != null ? typeCastSuffix 
        : (EdmStructuredType) lastPart.getType();
      final boolean newReferencedIsCollection = lastPart.isCollection();
      if (hasSlash || tokenizer.next(TokenKind.SLASH)) {
        if (tokenizer.next(TokenKind.REF)) {
          resource.addResourcePart(new UriResourceRefImpl());
          item.setIsRef(true);
          parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, true, false);
        } else {
          ParserHelper.requireNext(tokenizer, TokenKind.COUNT);
          resource.addResourcePart(new UriResourceCountImpl());
          item.setCountPath(true);
          parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, true);
        }
      } else {
        parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, false);
      }

      item.setResourcePath(resource);
    }

    return item;
  }

  protected static UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final Edm edm,
      final EdmStructuredType referencedType, ExpandItemImpl item) throws UriParserException {
    UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);

    EdmStructuredType type = referencedType;
    String name = null;
    while (tokenizer.next(TokenKind.ODataIdentifier)) {
      name = tokenizer.getText();
      final EdmProperty property = referencedType.getStructuralProperty(name);
      if (property != null && property.getType().getKind() == EdmTypeKind.COMPLEX) {
        type = (EdmStructuredType) property.getType();
        UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl(property);
        ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
        final EdmStructuredType typeCast = ParserHelper.parseTypeCast(tokenizer, edm, type);
        if (typeCast != null) {
          complexResource.setTypeFilter(typeCast);
          ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
          type = typeCast;
        }
        resource.addResourcePart(complexResource);
      }
    }

    final EdmNavigationProperty navigationProperty = type.getNavigationProperty(name);
    if (navigationProperty == null) {
      if (tokenizer.next(TokenKind.STAR)) {
        item.setIsStar(true);
      } else {
        throw new UriParserSemanticException(
            "Navigation Property '" + name + "' not found in type '" + type.getFullQualifiedName() + "'.",
            UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, type.getName(), name);
      }
    } else {
      resource.addResourcePart(new UriResourceNavigationPropertyImpl(navigationProperty));
    }

    return resource;
  }

  private void parseOptions(UriTokenizer tokenizer,
      final EdmStructuredType referencedType, final boolean referencedIsCollection,
      ExpandItemImpl item,
      final boolean forRef, final boolean forCount) throws UriParserException, UriValidationException {
    if (tokenizer.next(TokenKind.OPEN)) {
      do {
        SystemQueryOption systemQueryOption;
        if (!forCount && tokenizer.next(TokenKind.COUNT)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          ParserHelper.requireNext(tokenizer, TokenKind.BooleanValue);
          CountOptionImpl countOption = new CountOptionImpl();
          countOption.setText(tokenizer.getText());
          countOption.setValue(Boolean.parseBoolean(tokenizer.getText()));
          systemQueryOption = countOption;

        } else if (!forRef && !forCount && tokenizer.next(TokenKind.EXPAND)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          systemQueryOption = new ExpandParser(edm, odata, aliases, null).parse(tokenizer, referencedType);

        } else if (tokenizer.next(TokenKind.FILTER)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          systemQueryOption = new FilterParser(edm, odata).parse(tokenizer, referencedType, null, aliases);

        } else if (!forRef && !forCount && tokenizer.next(TokenKind.LEVELS)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          systemQueryOption = (SystemQueryOption) parseLevels(tokenizer);

        } else if (!forCount && tokenizer.next(TokenKind.ORDERBY)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          systemQueryOption = new OrderByParser(edm, odata).parse(tokenizer, referencedType, null, aliases);

        } else if (tokenizer.next(TokenKind.SEARCH)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          systemQueryOption = new SearchParser().parse(tokenizer);

        } else if (!forRef && !forCount && tokenizer.next(TokenKind.SELECT)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          systemQueryOption = new SelectParser(edm).parse(tokenizer, referencedType, referencedIsCollection);

        } else if (!forCount && tokenizer.next(TokenKind.SKIP)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
          final int value = ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.SKIP.toString(),
              tokenizer.getText(), true);
          SkipOptionImpl skipOption = new SkipOptionImpl();
          skipOption.setText(tokenizer.getText());
          skipOption.setValue(value);
          systemQueryOption = skipOption;

        } else if (!forCount && tokenizer.next(TokenKind.TOP)) {
          ParserHelper.requireNext(tokenizer, TokenKind.EQ);
          ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
          final int value = ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.TOP.toString(),
              tokenizer.getText(), true);
          TopOptionImpl topOption = new TopOptionImpl();
          topOption.setText(tokenizer.getText());
          topOption.setValue(value);
          systemQueryOption = topOption;

        } else {
          throw new UriParserSyntaxException("Allowed query option expected.",
              UriParserSyntaxException.MessageKeys.SYNTAX);
        }
        try {
          item.setSystemQueryOption(systemQueryOption);
        } catch (final ODataRuntimeException e) {
          throw new UriParserSyntaxException("Double system query option '" + systemQueryOption.getName() + "'.", e,
              UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION, systemQueryOption.getName());
        }
      } while (tokenizer.next(TokenKind.SEMI));
      ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
    }
  }

  private LevelsExpandOption parseLevels(UriTokenizer tokenizer) throws UriParserException {
    final LevelsOptionImpl option = new LevelsOptionImpl();
    if (tokenizer.next(TokenKind.MAX)) {
      option.setText(tokenizer.getText());
      option.setMax();
    } else {
      ParserHelper.requireNext(tokenizer, TokenKind.IntegerValue);
      option.setText(tokenizer.getText());
      option.setValue(
          ParserHelper.parseNonNegativeInteger(SystemQueryOptionKind.LEVELS.toString(), tokenizer.getText(), false));
    }
    return option;
  }
}
