package de.renew.expression;

import java.io.IOException;
import java.io.Serializable;

/**
 * A {@code LocalVariable} represents a variable that is local to an {@code Expression}.
 */
public class LocalVariable implements Serializable {
    /**
     * The name of the {@code LocalVariable}.
     * @deprecated this field is deprecated, use {@link #getName()} instead
     */
    @Deprecated
    public String name;

    /**
     * Whether the {@code LocalVariable} should be shown to the user, for example when bindings are listed using
     * {@link de.renew.expression.VariableMapper#appendBindingsTo}.
     */
    private final boolean _isVisible;

    // Refactoring
    /**
     * The line at which the variable begins.
     * @deprecated this field is deprecated, use {@link #getVariableBeginLine()} instead
     */
    @Deprecated
    public int variableBeginLine;
    /**
     * The column at which the variable begins.
     * @deprecated this field is deprecated, use {@link #getVariableBeginColumn()} instead
     */
    @Deprecated
    public int variableBeginColumn;
    /**
     * The line at which the variable ends.
     * @deprecated this field is deprecated, use {@link #getVariableEndLine()} instead
     */
    @Deprecated
    public int variableEndLine;
    /**
     * The column at which the variable ends.
     * @deprecated this field is deprecated, use {@link #getVariableEndColumn()} instead
     */
    @Deprecated
    public int variableEndColumn;

    /**
     * Constructs a new {@code LocalVariable} with the given name and visibility.
     *
     * @param name the name of the {@code LocalVariable}
     * @param isVisible whether the {@code LocalVariable} is visible
     */
    public LocalVariable(String name, boolean isVisible) {
        this.name = name.intern();
        _isVisible = isVisible;
    }

    /**
     * Constructs a new, visible {@code LocalVariable} with the given name.
     *
     * @param name the name of the {@code LocalVariable}
     */
    public LocalVariable(String name) {
        this(name, true);
    }

    /**
     * Returns the name of the local variable.
     * @return name of the {@link LocalVariable}
     */
    public String getName() {
        return name;
    }

    /**
     * Returns the visibility setting.
     * @return {@code true}, if this local variable is visible, {@code false} otherwise
     */
    public boolean getIsVisible() {
        return _isVisible;
    }

    /**
     * Returns the beginning of the local variable's line.
     * @return the beginning of the local variable's line
     */
    public int getVariableBeginLine() {
        return variableBeginLine;
    }

    /**
     * Returns the beginning of the local variable's column.
     * @return the beginning of the local variable's column
     */
    public int getVariableBeginColumn() {
        return variableBeginColumn;
    }

    /**
     * Returns the end of the local variable's line.
     * @return the end of the local variable's line
     */
    public int getVariableEndLine() {
        return variableEndLine;
    }

    /**
     * Returns the end of the local variable's column.
     * @return the end of the local variable's column
     */
    public int getVariableEndColumn() {
        return variableEndColumn;
    }

    /**
     * Sets the beginning of the local variable's line to a new given value.
     * @param variableBeginLine the new integer value for the beginning of the local variable's line
     */
    public void setVariableBeginLine(int variableBeginLine) {
        this.variableBeginLine = variableBeginLine;
    }

    /**
     * Sets the beginning of the local variable's column to a new given value.
     * @param variableBeginColumn the new integer value for the beginning of the local variable's column
     */
    public void setVariableBeginColumn(int variableBeginColumn) {
        this.variableBeginColumn = variableBeginColumn;
    }

    /**
     * Sets the end of the local variable's line to a new given value.
     * @param variableEndLine the new integer value for the end of the local variable's line
     */
    public void setVariableEndLine(int variableEndLine) {
        this.variableEndLine = variableEndLine;
    }

    /**
     * Sets the end of the local variable's column to a new given value.
     * @param variableEndColumn the new integer value for the end of the local variable's column
     */
    public void setVariableEndColumn(int variableEndColumn) {
        this.variableEndColumn = variableEndColumn;
    }

    @Override
    public String toString() {
        return "local variable \"" + name + "\"";
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof LocalVariable) {
            return (name.equals(((LocalVariable) obj).name));
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }

    /**
     * Deserializes a {@code LocalVariable} from an object input stream.
     *
     * @param in the stream to read from
     * @throws IOException if an error occurs while reading from the stream
     * @throws ClassNotFoundException if an object is read whose class is not known
     */
    private void readObject(java.io.ObjectInputStream in)
        throws IOException, ClassNotFoundException
    {
        in.defaultReadObject();
        name = name.intern();
    }
}