/*-
 * #%L
 * JSQLParser library
 * %%
 * Copyright (C) 2004 - 2021 JSQLParser
 * %%
 * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
 * #L%
 */

package net.sf.jsqlparser.statement.alter;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;

/**
 * @author are
 * @see <a href=
 *      "https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_9019.htm">Rename</a>
 */
public class RenameTableStatement implements Statement {
    private final LinkedHashMap<Table, Table> tableNames = new LinkedHashMap<>();

    private boolean usingTableKeyword = false;
    private boolean usingIfExistsKeyword = false;

    private String waitDirective = "";

    public RenameTableStatement(Table oldName, Table newName) {
        tableNames.put(
                Objects.requireNonNull(oldName,
                        "The OLD NAME of the Rename Statement must not be null."),
                Objects.requireNonNull(newName,
                        "The NEW NAME of the Rename Statement must not be null."));
    }

    public RenameTableStatement(Table oldName, Table newName, boolean usingTableKeyword,
            boolean usingIfExistsKeyword, String waitDirective) {
        tableNames.put(
                Objects.requireNonNull(oldName,
                        "The OLD NAME of the Rename Statement must not be null."),
                Objects.requireNonNull(newName,
                        "The NEW NAME of the Rename Statement must not be null."));

        this.usingTableKeyword = usingTableKeyword;
        this.usingIfExistsKeyword = usingIfExistsKeyword;
        this.waitDirective = waitDirective;
    }

    public void addTableNames(Table oldName, Table newName) {
        tableNames.put(
                Objects.requireNonNull(oldName,
                        "The OLD NAME of the Rename Statement must not be null."),
                Objects.requireNonNull(newName,
                        "The NEW NAME of the Rename Statement must not be null."));
    }


    public boolean isUsingTableKeyword() {
        return usingTableKeyword;
    }

    public void setUsingTableKeyword(boolean usingTableKeyword) {
        this.usingTableKeyword = usingTableKeyword;
    }

    public RenameTableStatement withUsingTableKeyword(boolean usingTableKeyword) {
        this.usingTableKeyword = usingTableKeyword;
        return this;
    }

    public boolean isUsingIfExistsKeyword() {
        return usingIfExistsKeyword;
    }

    public void setUsingIfExistsKeyword(boolean usingIfExistsKeyword) {
        this.usingIfExistsKeyword = usingIfExistsKeyword;
    }

    public RenameTableStatement withUsingIfExistsKeyword(boolean usingIfExistsKeyword) {
        this.usingIfExistsKeyword = usingIfExistsKeyword;
        return this;
    }

    public String getWaitDirective() {
        return waitDirective;
    }

    public void setWaitDirective(String waitDirective) {
        this.waitDirective = waitDirective;
    }

    public RenameTableStatement withWaitDirective(String waitDirective) {
        this.waitDirective = waitDirective;
        return this;
    }

    public int getTableNamesSize() {
        return tableNames.size();
    }

    public boolean isTableNamesEmpty() {
        return tableNames.isEmpty();
    }

    public Set<Map.Entry<Table, Table>> getTableNames() {
        return tableNames.entrySet();
    }

    @Override
    public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
        return statementVisitor.visit(this, context);
    }

    public StringBuilder appendTo(StringBuilder builder) {
        int i = 0;
        for (Entry<Table, Table> e : tableNames.entrySet()) {
            if (i == 0) {
                builder
                        .append("RENAME")
                        .append(usingTableKeyword ? " TABLE " : " ")
                        .append(usingIfExistsKeyword ? " IF EXISTS " : " ")
                        .append(e.getKey())
                        .append(waitDirective != null && waitDirective.length() > 0
                                ? " " + waitDirective
                                : "")
                        .append(" TO ")
                        .append(e.getValue());
            } else {
                builder
                        .append(", ")
                        .append(e.getKey())
                        .append(" TO ")
                        .append(e.getValue());
            }

            i++;
        }
        return builder;
    }

    @Override
    public String toString() {
        return appendTo(new StringBuilder()).toString();
    }
}
