package org.dbsp.sqlCompiler.compiler.frontend.parser;

import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCreate;
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.util.ImmutableNullableList;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.dbsp.util.Utilities;

import java.util.List;
import java.util.Objects;

/** Parse tree for {@code DECLARE RECURSIVE VIEW} statement. */
public class SqlDeclareView extends SqlCreate {
    public final SqlIdentifier name;
    public final SqlNodeList columns;

    private static final SqlOperator OPERATOR =
            new SqlSpecialOperator("DECLARE RECURSIVE VIEW", SqlKind.OTHER) {
                @Override
                public SqlCall createCall(
                        @Nullable SqlLiteral functionQualifier, SqlParserPos pos, @Nullable SqlNode... operands) {
                    Utilities.enforce(operands.length == 2);
                    return new SqlDeclareView(pos,
                            (SqlIdentifier) Objects.requireNonNull(operands[0]),
                            (SqlNodeList) Objects.requireNonNull(operands[1]));
                }
            };

    public SqlDeclareView(SqlParserPos pos, SqlIdentifier name, SqlNodeList columns) {
        super(OPERATOR, pos, false, false);
        this.name = Objects.requireNonNull(name, "name");
        this.columns = columns;
    }

    @SuppressWarnings("nullness")
    @Override public List<SqlNode> getOperandList() {
        return ImmutableNullableList.of(this.name, this.columns);
    }

    @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
        writer.keyword("DECLARE");
        writer.keyword("RECURSIVE");
        writer.keyword("VIEW");
        name.unparse(writer, leftPrec, rightPrec);
        {
            SqlWriter.Frame frame = writer.startList("(", ")");
            for (SqlNode c : columns) {
                writer.sep(",");
                c.unparse(writer, 0, 0);
            }
            writer.endList(frame);
        }
    }
}
