/*
 * 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.drill.exec.planner.sql.parser;

import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCharStringLiteral;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlSpecialOperator;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.util.SqlBasicVisitor;
import org.apache.drill.common.util.DrillStringUtils;
import org.apache.drill.exec.planner.sql.SchemaUtilities;
import org.apache.drill.exec.planner.sql.handlers.AbstractSqlHandler;
import org.apache.drill.exec.planner.sql.handlers.SqlHandlerConfig;
import org.apache.drill.exec.planner.sql.handlers.SchemaHandler;
import org.apache.drill.exec.planner.sql.handlers.SqlHandlerUtil;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Parent class for CREATE, DROP, DESCRIBE, ALTER SCHEMA commands.
 * Holds logic common command property: table, path.
 */
public abstract class SqlSchema extends DrillSqlCall {

  protected final SqlIdentifier table;
  protected final SqlNode path;

  protected SqlSchema(SqlParserPos pos, SqlIdentifier table, SqlNode path) {
    super(pos);
    this.table = table;
    this.path = path;
  }

  @Override
  public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
    if (table != null) {
      writer.keyword("FOR TABLE");
      table.unparse(writer, leftPrec, rightPrec);
    }

    if (path != null) {
      writer.keyword("PATH");
      path.unparse(writer, leftPrec, rightPrec);
    }
  }

  public boolean hasTable() {
    return table != null;
  }

  public SqlIdentifier getTable() {
    return table;
  }

  public List<String> getSchemaPath() {
    return hasTable() ? SchemaUtilities.getSchemaPath(table) : null;
  }

  public String getTableName() {
    if (hasTable()) {
      String tableName = table.isSimple() ? table.getSimple() : table.names.get(table.names.size() - 1);
      return DrillStringUtils.removeLeadingSlash(tableName);
    }
    return null;
  }

  public String getPath() {
    return path == null ? null : path.accept(LiteralVisitor.INSTANCE);
  }

  protected Map<String, String> getProperties(SqlNodeList properties) {
    if (properties == null) {
      return null;
    }

    // preserve properties order
    Map<String, String> map = new LinkedHashMap<>();
    for (int i = 1; i < properties.size(); i += 2) {
      map.put(properties.get(i - 1).accept(LiteralVisitor.INSTANCE),
        properties.get(i).accept(LiteralVisitor.INSTANCE));
    }
    return map;
  }

  /**
   * Visits literal and returns bare value (i.e. single quotes).
   */
  private static class LiteralVisitor extends SqlBasicVisitor<String> {

    static final LiteralVisitor INSTANCE = new LiteralVisitor();

    @Override
    public String visit(SqlLiteral literal) {
      return literal.toValue();
    }

  }

  /**
   * CREATE SCHEMA sql call.
   */
  public static class Create extends SqlSchema {

    private final SqlCharStringLiteral schema;
    private final SqlNode load;
    private final SqlNodeList properties;
    private final SqlLiteral createType;

    public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("CREATE_SCHEMA", SqlKind.OTHER_DDL) {
      @Override
      public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode... operands) {
        return new Create(pos, (SqlCharStringLiteral) operands[0], operands[1],
          (SqlIdentifier) operands[2], operands[3], (SqlNodeList) operands[4], (SqlLiteral) operands[5]);
      }
    };

    public Create(SqlParserPos pos,
                  SqlCharStringLiteral schema,
                  SqlNode load,
                  SqlIdentifier table,
                  SqlNode path,
                  SqlNodeList properties,
                  SqlLiteral createType) {
      super(pos, table, path);
      this.schema = schema;
      this.load = load;
      this.properties = properties;
      this.createType = createType;
    }

    @Override
    public SqlOperator getOperator() {
      return OPERATOR;
    }

    @Override
    public List<SqlNode> getOperandList() {
      return Arrays.asList(schema, load, table, path, properties, createType);
    }

    @Override
    public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
      writer.keyword("CREATE");

      if (SqlCreateType.OR_REPLACE == getSqlCreateType()) {
        writer.keyword("OR");
        writer.keyword("REPLACE");
      }

      if (schema != null) {
        writer.keyword("SCHEMA");
        writer.literal(getSchema());
      }

      if (load != null) {
        writer.keyword("LOAD");
        load.unparse(writer, leftPrec, rightPrec);
      }

      super.unparse(writer, leftPrec, rightPrec);

      if (properties != null) {
        writer.keyword("PROPERTIES");
        SqlHandlerUtil.unparseKeyValuePairs(writer, leftPrec, rightPrec, properties);
      }
    }

    @Override
    public AbstractSqlHandler getSqlHandler(SqlHandlerConfig config) {
      return new SchemaHandler.Create(config);
    }

    public boolean hasSchema() {
      return schema != null;
    }

    public String getSchema() {
      return hasSchema() ? schema.toValue() : null;
    }

    public String getLoad() {
      return load == null ? null : load.accept(LiteralVisitor.INSTANCE);
    }

    public Map<String, String> getProperties() {
      return getProperties(properties);
    }

    public SqlCreateType getSqlCreateType() {
      return SqlCreateType.valueOf(createType.toValue());
    }
  }

  /**
   * DROP SCHEMA sql call.
   */
  public static class Drop extends SqlSchema {

    private final SqlLiteral existenceCheck;

    public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("DROP_SCHEMA", SqlKind.OTHER_DDL) {
      @Override
      public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode... operands) {
        return new Drop(pos, (SqlIdentifier) operands[0], (SqlLiteral) operands[1]);
      }
    };

    public Drop(SqlParserPos pos, SqlIdentifier table, SqlLiteral existenceCheck) {
      super(pos, table, null);
      this.existenceCheck = existenceCheck;
    }

    @Override
    public SqlOperator getOperator() {
      return OPERATOR;
    }

    @Override
    public List<SqlNode> getOperandList() {
      return Arrays.asList(table, existenceCheck);
    }

    @Override
    public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
      writer.keyword("DROP");
      writer.keyword("SCHEMA");

      if (ifExists()) {
        writer.keyword("IF");
        writer.keyword("EXISTS");
      }

      super.unparse(writer, leftPrec, rightPrec);
    }

    @Override
    public AbstractSqlHandler getSqlHandler(SqlHandlerConfig config) {
      return new SchemaHandler.Drop(config);
    }

    public boolean ifExists() {
      return existenceCheck.booleanValue();
    }
  }

  /**
   * DESCRIBE SCHEMA FOR TABLE sql call.
   */
  public static class Describe extends SqlSchema {

    private final SqlLiteral format;

    public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator(SqlKind.DESCRIBE_SCHEMA.name(), SqlKind.DESCRIBE_SCHEMA) {
      @Override
      public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode... operands) {
        return new Describe(pos, (SqlIdentifier) operands[0], (SqlLiteral) operands[1]);
      }
    };

    public Describe(SqlParserPos pos, SqlIdentifier table, SqlLiteral format) {
      super(pos, table, null);
      this.format = format;
    }

    @Override
    public SqlOperator getOperator() {
      return OPERATOR;
    }

    @Override
    public List<SqlNode> getOperandList() {
      return Arrays.asList(table, format);
    }

    @Override
    public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
      writer.keyword("DESCRIBE");
      writer.keyword("SCHEMA");

      super.unparse(writer, leftPrec, rightPrec);

      writer.keyword("AS");
      writer.keyword(getFormat().name());
    }

    public Describe.Format getFormat() {
      return Format.valueOf(format.toValue());
    }

    /**
     * Enum which specifies format of DESCRIBE SCHEMA FOR table output.
     */
    public enum Format {

      /**
       * Schema will be output in JSON format used to store schema
       * in {@link org.apache.drill.exec.record.metadata.schema.SchemaProvider#DEFAULT_SCHEMA_NAME} file.
       */
      JSON,

      /**
       * Schema will be output in CREATE SCHEMA command syntax.
       */
      STATEMENT
    }
  }

  public static class Add extends SqlSchema {

    private final SqlLiteral replace;
    private final SqlCharStringLiteral schema;
    private final SqlNodeList properties;

    public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("ALTER_SCHEMA_ADD", SqlKind.OTHER_DDL) {
      @Override
      public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode... operands) {
        return new Add(pos, (SqlIdentifier) operands[0], operands[1], (SqlLiteral) operands[2],
          (SqlCharStringLiteral) operands[3], (SqlNodeList) operands[4]);
      }
    };

    public Add(SqlParserPos pos,
               SqlIdentifier table,
               SqlNode path,
               SqlLiteral replace,
               SqlCharStringLiteral schema,
               SqlNodeList properties) {
      super(pos, table, path);
      this.replace = replace;
      this.schema = schema;
      this.properties = properties;
    }

    @Override
    public SqlOperator getOperator() {
      return OPERATOR;
    }

    @Override
    public List<SqlNode> getOperandList() {
      return Arrays.asList(table, path, replace, schema, properties);
    }

    @Override
    public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
      writer.keyword("ALTER");
      writer.keyword("SCHEMA");
      writer.keyword("ADD");

      if (replace.booleanValue()) {
        writer.keyword("OR");
        writer.keyword("REPLACE");
      }

      super.unparse(writer, leftPrec, rightPrec);

      if (schema != null) {
        writer.keyword("COLUMNS");
        writer.literal(getSchema());
      }

      if (properties != null) {
        writer.keyword("PROPERTIES");
        SqlHandlerUtil.unparseKeyValuePairs(writer, leftPrec, rightPrec, properties);
      }
    }

    @Override
    public AbstractSqlHandler getSqlHandler(SqlHandlerConfig config) {
      return new SchemaHandler.Add(config);
    }

    public boolean isReplace() {
      return replace.booleanValue();
    }

    public boolean hasSchema() {
      return schema != null;
    }

    public String getSchema() {
      return hasSchema() ? schema.toValue() : null;
    }

    public boolean hasProperties() {
      return properties != null;
    }

    public Map<String, String> getProperties() {
      return getProperties(properties);
    }
  }

  public static class Remove extends SqlSchema {

    private final SqlNodeList columns;
    private final SqlNodeList properties;

    public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("ALTER_SCHEMA_REMOVE", SqlKind.OTHER_DDL) {
      @Override
      public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode... operands) {
        return new Remove(pos, (SqlIdentifier) operands[0], operands[1],
          (SqlNodeList) operands[2], (SqlNodeList) operands[3]);
      }
    };

    public Remove(SqlParserPos pos,
                  SqlIdentifier table,
                  SqlNode path,
                  SqlNodeList columns,
                  SqlNodeList properties) {
      super(pos, table, path);
      this.columns = columns;
      this.properties = properties;
    }

    @Override
    public SqlOperator getOperator() {
      return OPERATOR;
    }

    @Override
    public List<SqlNode> getOperandList() {
      return Arrays.asList(table, path, columns, properties);
    }

    @Override
    public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
      writer.keyword("ALTER");
      writer.keyword("SCHEMA");
      writer.keyword("REMOVE");

      super.unparse(writer, leftPrec, rightPrec);

      if (columns != null) {
        writer.keyword("COLUMNS");
        SqlHandlerUtil.unparseSqlNodeList(writer, leftPrec, rightPrec, columns);
      }

      if (properties != null) {
        writer.keyword("PROPERTIES");
        SqlHandlerUtil.unparseSqlNodeList(writer, leftPrec, rightPrec, properties);
      }
    }

    @Override
    public AbstractSqlHandler getSqlHandler(SqlHandlerConfig config) {
      return new SchemaHandler.Remove(config);
    }

    public List<String> getColumns() {
      if (columns == null) {
        return null;
      }
      return columns.getList().stream()
        .map(SqlNode::toString)
        .collect(Collectors.toList());
    }

    public boolean hasProperties() {
      return properties != null;
    }

    public List<String> getProperties() {
      if (properties == null) {
        return null;
      }
      return properties.getList().stream()
        .map(property -> property.accept(LiteralVisitor.INSTANCE))
        .collect(Collectors.toList());
    }
  }
}
