/*
 * 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.carbondata.core.scan.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.carbondata.common.logging.LogServiceFactory;
import org.apache.carbondata.core.index.IndexFilter;
import org.apache.carbondata.core.metadata.datatype.DataTypes;
import org.apache.carbondata.core.metadata.schema.table.CarbonTable;
import org.apache.carbondata.core.metadata.schema.table.column.CarbonDimension;
import org.apache.carbondata.core.metadata.schema.table.column.CarbonMeasure;
import org.apache.carbondata.core.util.DataTypeConverter;

import org.apache.log4j.Logger;

public class QueryModelBuilder {

  private CarbonTable table;
  private QueryProjection projection;
  private IndexFilter indexFilter;
  private DataTypeConverter dataTypeConverter;
  private boolean forcedDetailRawQuery;
  private boolean readPageByPage;
  private boolean convertToRangeFilter = true;
  /**
   * log information
   */
  private static final Logger LOGGER =
      LogServiceFactory.getLogService(QueryModelBuilder.class.getName());

  public QueryModelBuilder(CarbonTable table) {
    this.table = table;
  }

  public QueryModelBuilder projectColumns(String[] projectionColumns) {
    Objects.requireNonNull(projectionColumns);
    String factTableName = table.getTableName();
    QueryProjection projection = new QueryProjection();

    int i = 0;
    for (String projectionColumnName : projectionColumns) {
      CarbonDimension dimension = table.getDimensionByName(projectionColumnName);
      if (dimension != null) {
        CarbonDimension complexParentDimension = dimension.getComplexParentDimension();
        if (null != complexParentDimension && dimension.getDataType() == DataTypes.DATE) {
          if (!isAlreadyExists(complexParentDimension, projection.getDimensions())) {
            projection.addDimension(complexParentDimension, i);
            i++;
          }
        } else {
          projection.addDimension(dimension, i);
          i++;
        }
      } else {
        CarbonMeasure measure = table.getMeasureByName(projectionColumnName);
        if (measure == null) {
          throw new RuntimeException(
              projectionColumnName + " column not found in the table " + factTableName);
        }
        projection.addMeasure(measure, i);
        i++;
      }
    }
    projection = optimizeProjectionForComplexColumns(projection, projectionColumns, factTableName);
    List<String> projectionDimensionAndMeasures = new ArrayList<>();
    this.projection = projection;
    for (ProjectionDimension projectionDimension : projection.getDimensions()) {
      projectionDimensionAndMeasures.add(projectionDimension.getColumnName());
    }
    for (ProjectionMeasure projectionMeasure : projection.getMeasures()) {
      projectionDimensionAndMeasures.add(projectionMeasure.getColumnName());
    }
    LOGGER.info("Projection Columns: " + projectionDimensionAndMeasures);
    return this;
  }

  /**
   * For complex dimensions, check if the dimension already exists in the projection list or not
   *
   * @param dimension
   * @param projectionDimensions
   * @return
   */
  private boolean isAlreadyExists(CarbonDimension dimension,
      List<ProjectionDimension> projectionDimensions) {
    boolean exists = false;
    for (ProjectionDimension projectionDimension : projectionDimensions) {
      if (dimension.getColName().equals(projectionDimension.getColumnName())) {
        exists = true;
        break;
      }
    }
    return exists;
  }

  private QueryProjection optimizeProjectionForComplexColumns(QueryProjection projection,
      String[] projectionColumns, String factTableName) {
    // Get the List of Complex Column Projection.
    // The optimization techniques which can be applied are
    // A. Merging in Driver Side
    // B. Merging in the result Collector side.
    // Merging is driver side cases are
    // Driver merging will eliminate one of the CarbonDimension.
    // Executor merging will merge the column output in Result Collector.
    // In this routine we are going to do driver merging and leave executor merging.
    Map<Integer, List<Integer>> complexColumnMap = new HashMap<>();
    List<ProjectionDimension> carbonDimensions = projection.getDimensions();
    // Traverse and find out if the top most parent of projection column is already there
    List<CarbonDimension> projectionDimensionToBeMerged = new ArrayList<>();
    for (ProjectionDimension projectionDimension : carbonDimensions) {
      CarbonDimension complexParentDimension =
          projectionDimension.getDimension().getComplexParentDimension();
      if (null != complexParentDimension && isAlreadyExists(complexParentDimension,
          carbonDimensions)) {
        projectionDimensionToBeMerged.add(projectionDimension.getDimension());
      }
    }

    if (projectionDimensionToBeMerged.size() != 0) {
      projection =
          removeMergedDimensions(projectionDimensionToBeMerged, projectionColumns, factTableName);
      carbonDimensions = projection.getDimensions();
    }

    for (ProjectionDimension cols : carbonDimensions) {
      // get all the Projections with Parent Ordinal Set.
      if (null != cols.getDimension().getComplexParentDimension()) {
        if (complexColumnMap.get(cols.getDimension().getComplexParentDimension().getOrdinal())
            != null) {
          List<Integer> childColumns =
              complexColumnMap.get(cols.getDimension().getComplexParentDimension().getOrdinal());
          childColumns.add(cols.getDimension().getOrdinal());
          complexColumnMap
              .put(cols.getDimension().getComplexParentDimension().getOrdinal(), childColumns);
        } else {
          List<Integer> childColumns = new ArrayList<>();
          childColumns.add(cols.getDimension().getOrdinal());
          complexColumnMap
              .put(cols.getDimension().getComplexParentDimension().getOrdinal(), childColumns);
        }
      }
    }

    // Traverse the Map to Find any columns are parent.
    for (Map.Entry<Integer, List<Integer>> entry : complexColumnMap.entrySet()) {
      List<Integer> childOrdinals = entry.getValue();
      if (childOrdinals.size() > 1) {
        // In case of more that one child, have to check if the child columns are in the same path
        // and have a common parent.
        Collections.sort(childOrdinals);
        List<CarbonDimension> mergedDimensions = mergeChildColumns(childOrdinals);
        if (mergedDimensions.size() > 0) {
          projection = removeMergedDimensions(mergedDimensions, projectionColumns, factTableName);
        }
      }
    }
    return projection;
  }

  /**
   * Remove the dimensions from the projection list which are merged
   *
   * @param mergedDimensions
   * @param projectionColumns
   * @param factTableName
   * @return
   */
  private QueryProjection removeMergedDimensions(List<CarbonDimension> mergedDimensions,
      String[] projectionColumns, String factTableName) {
    QueryProjection queryProjection = new QueryProjection();
    int i = 0;
    for (String projectionColumnName : projectionColumns) {
      CarbonDimension dimension = table.getDimensionByName(projectionColumnName);
      if (dimension != null) {
        if (!mergedDimensions.contains(dimension)) {
          if (!isAlreadyExists(dimension, queryProjection.getDimensions())) {
            queryProjection.addDimension(dimension, i);
            i++;
          }
        }
      } else {
        CarbonMeasure measure = table.getMeasureByName(projectionColumnName);
        if (measure == null) {
          throw new RuntimeException(
              projectionColumnName + " column not found in the table " + factTableName);
        }
        queryProjection.addMeasure(measure, i);
        i++;
      }
    }
    return queryProjection;
  }

  private List<CarbonDimension> mergeChildColumns(List<Integer> childOrdinals) {
    // Check If children if they are in the path of not.
    List<CarbonDimension> mergedChild = new ArrayList<>();
    List<CarbonDimension> dimList = table.getVisibleDimensions();
    for (int i = 0; i < childOrdinals.size(); i++) {
      for (int j = i; j < childOrdinals.size(); j++) {
        CarbonDimension parentDimension = getDimensionBasedOnOrdinal(dimList, childOrdinals.get(i));
        CarbonDimension childDimension = getDimensionBasedOnOrdinal(dimList, childOrdinals.get(j));
        if (!mergedChild.contains(childOrdinals.get(j)) && checkChildrenInSamePath(parentDimension,
            childDimension)) {
          mergedChild.add(childDimension);
        }
      }
    }
    return mergedChild;
  }

  private boolean checkChildrenInSamePath(CarbonDimension parentDimension,
      CarbonDimension childDimension) {
    if (parentDimension.getColName().equals(childDimension.getColName())) {
      return false;
    } else if (checkForChildColumns(parentDimension, childDimension)) {
      return true;
    } else {
      return false;
    }
  }

  private boolean checkForChildColumns(CarbonDimension parentDimension,
      CarbonDimension childDimension) {
    boolean output = false;
    if (parentDimension.getOrdinal() == childDimension.getOrdinal()) {
      output = true;
    } else if (parentDimension.getNumberOfChild() > 0) {
      for (int i = 0; i < parentDimension.getNumberOfChild() && !output; i++) {
        output =
            checkForChildColumns(parentDimension.getListOfChildDimensions().get(i), childDimension);
      }
    } else {
      output = false;
    }
    return output;
  }

  private CarbonDimension getDimensionBasedOnOrdinal(List<CarbonDimension> dimList,
      Integer ordinal) {
    for (CarbonDimension dims : dimList) {
      if (dims.getOrdinal() == ordinal) {
        return dims;
      } else if (dims.getNumberOfChild() > 0) {
        CarbonDimension dimensionBasedOnOrdinal =
            getDimensionBasedOnOrdinal(dims.getListOfChildDimensions(), ordinal);
        if (null != dimensionBasedOnOrdinal) {
          return dimensionBasedOnOrdinal;
        }
      }
    }
    return null;
  }

  public QueryModelBuilder projectAllColumns() {
    QueryProjection projection = new QueryProjection();
    List<CarbonDimension> dimensions = table.getVisibleDimensions();
    for (int i = 0; i < dimensions.size(); i++) {
      projection.addDimension(dimensions.get(i), i);
    }
    List<CarbonMeasure> measures = table.getVisibleMeasures();
    for (int i = 0; i < measures.size(); i++) {
      projection.addMeasure(measures.get(i), i);
    }
    this.projection = projection;
    return this;
  }

  public QueryModelBuilder filterExpression(IndexFilter filterExpression) {
    this.indexFilter = filterExpression;
    return this;
  }

  public QueryModelBuilder dataConverter(DataTypeConverter dataTypeConverter) {
    this.dataTypeConverter = dataTypeConverter;
    return this;
  }

  public QueryModelBuilder enableForcedDetailRawQuery() {
    this.forcedDetailRawQuery = true;
    return this;
  }

  public QueryModelBuilder convertToRangeFilter(boolean convertToRangeFilter) {
    this.convertToRangeFilter = convertToRangeFilter;
    return this;
  }

  public boolean isConvertToRangeFilter() {
    return this.convertToRangeFilter;
  }

  public void enableReadPageByPage() {
    this.readPageByPage = true;
  }

  public QueryModel build() {
    QueryModel queryModel = QueryModel.newInstance(table);
    queryModel.setConverter(dataTypeConverter);
    queryModel.setForcedDetailRawQuery(forcedDetailRawQuery);
    queryModel.setReadPageByPage(readPageByPage);
    queryModel.setProjection(projection);

    if (table.isTransactionalTable() && !table.hasColumnDrift()) {
      // set the filter to the query model in order to filter blocklet before scan
      boolean[] isFilterDimensions = new boolean[table.getDimensionOrdinalMax()];
      boolean[] isFilterMeasures = new boolean[table.getAllMeasures().size()];
      queryModel.setIsFilterDimensions(isFilterDimensions);
      queryModel.setIsFilterMeasures(isFilterMeasures);
      // In case of Dictionary Include Range Column we do not optimize the range expression
      if (indexFilter != null) {
        if (isConvertToRangeFilter()) {
          indexFilter.processFilterExpression(isFilterDimensions, isFilterMeasures);
        } else {
          indexFilter.processFilterExpressionWithoutRange(isFilterDimensions, isFilterMeasures);
        }
      }
    }
    queryModel.setIndexFilter(indexFilter);
    return queryModel;
  }
}
