package CH.ifa.draw.standard;

import java.util.Objects;
import java.util.Optional;
import java.util.Vector;

import de.renew.draw.storables.ontology.Drawing;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.ui.api.ErrorApi;
import de.renew.draw.ui.ontology.ErrorState;

/**
 * Class describing an erroneous state, described by a message and title, and possible concerning figures.
 * @deprecated This class is not to be used externally. Please use the {@link ErrorApi} instead.
 */
@Deprecated(since = "5.0", forRemoval = true)
public class FigureException implements ErrorState {
    private static final String DEFAULT_TITLE = "Renew: Syntax Error";
    private final int _line;
    private final int _column;
    private final String _title;
    private final String _message;
    private final Drawing _errorDrawing;
    private final Vector<Figure> _errorFigures;
    private final Figure _typedErrorFigure;
    private final Object _problemSpecificInformation;

    /**
     * Creates a new FigureException, describing an erroneous state, with the given parameters.
     * <p>
     * By giving a specific error figure, it can later be accessed to e.g. edit its text if it's a text figure.
     *
     * @param message the message describing the erroneous state
     * @param line line index that can be used to determine in which line the text is erroneous if a text figure is given as the specific erroneous figure
     * @param column column index that can be used to determine at which column the text is erroneous if a text figure is given as the specific erroneous figure
     * @param drawing the drawing that contains the erroneous state
     * @param specificErrorFigure a specific figure that is erroneous, e.g. a text figure.
     *
     * @deprecated This method is only for internal usage and will later be made private.
     */
    @Deprecated
    public FigureException(
        String message, int line, int column, Drawing drawing, Figure specificErrorFigure)
    {
        this(
            message, DEFAULT_TITLE, line, column, drawing, createVector(specificErrorFigure),
            specificErrorFigure, null);

    }

    /**
     * Creates a new FigureException, describing an erroneous state, with the given parameters.
     * <p>
     * This constructor is to be used if there is only one offending figure whose type is not important.
     *
     * @param title the title for the erroneous state
     * @param message the message describing the erroneous state
     * @param drawing the drawing that contains the erroneous state
     * @param offendingFigure an erroneous figure
     *
     * @deprecated This method is not to be used externally. Please use the method
     * {@link ErrorApi#createErrorState(String, String, Drawing, Figure)} instead.
     */
    @Deprecated
    public FigureException(String title, String message, Drawing drawing, Figure offendingFigure) {
        this(message, title, 0, 0, drawing, createVector(offendingFigure), null, null);
    }

    /**
     * Creates a new FigureException, describing an erroneous state, with the given parameters.
     *
     * @param title the title for the erroneous state
     * @param message the message describing the erroneous state
     * @param drawing the drawing that contains the erroneous state
     * @param offendingFigures the erroneous figures
     *
     * @deprecated This method is not to be used externally. Please use the method 
     * {@link ErrorApi#createErrorState(String, String, Drawing, Vector)} instead.
     */
    @Deprecated
    public FigureException(
        String title, String message, Drawing drawing, Vector<? extends Figure> offendingFigures)
    {
        this(message, title, 0, 0, drawing, createVector(offendingFigures), null, null);
    }

    /**
     * Creates a new FigureException, describing an erroneous state, with the given parameters.
     * <p>
     * By giving a specific error figure, it can later be accessed to e.g. edit its text if its a text figure.
     *
     * @param message the message describing the erroneous state
     * @param line line index that can be used to determine in which line the text is erroneous if a text figure is given as the specific erroneous figure
     * @param column column index that can be used to determine at which column the text is erroneous if a text figure is given as the specific erroneous figure
     * @param drawing the drawing that contains the erroneous state
     * @param specificErrorFigure a specific figure that is erroneous, e.g. a text figure.
     * @param errorFigures additional erroneous figures
     * @param problemSpecificInformation an object giving specific information for the error
     *
     * @deprecated This method is not to be used externally. Please use the method 
     * {@link ErrorApi#createErrorState(String, int, int, Drawing, Figure, Vector, Object)} instead.
     */
    @Deprecated
    public FigureException(
        String message, int line, int column, Drawing drawing, Figure specificErrorFigure,
        Vector<Figure> errorFigures, Object problemSpecificInformation)
    {
        this(
            message, DEFAULT_TITLE, line, column, drawing, createVector(errorFigures),
            specificErrorFigure, problemSpecificInformation);
    }

    /**
     * Creates a new FigureException, describing an erroneous state, with the given parameters.
     * <p>
     * By giving a specific error figure, it can later be accessed to e.g. edit its text if its a text figure.
     *
     * @param message the message describing the erroneous state
     * @param line line index that can be used to determine in which line the text is erroneous if a text figure is given as the specific erroneous figure
     * @param column column index that can be used to determine at which column the text is erroneous if a text figure is given as the specific erroneous figure
     * @param drawing the drawing that contains the erroneous state
     * @param specificErrorFigure a specific figure that is erroneous, e.g. a text figure.
     * @param problemSpecificInformation an object giving specific information for the error
     *
     * @deprecated This method is not to be used externally. Please use the method 
     * {@link ErrorApi#createErrorState(String, int, int, Drawing, Figure, Object)} instead.
     */
    @Deprecated
    public FigureException(
        String message, int line, int column, Drawing drawing, Figure specificErrorFigure,
        Object problemSpecificInformation)
    {
        this(
            message, DEFAULT_TITLE, line, column, drawing, createVector(specificErrorFigure),
            specificErrorFigure, problemSpecificInformation);
    }



    private FigureException(
        String message, String title, int line, int column, Drawing drawing,
        Vector<Figure> errorFigures, Figure typedErrorFigure, Object o)
    {
        Objects.requireNonNull(message, "A message must be given for the FigureException.");
        this._message = message;
        this._title = title;
        this._errorDrawing = drawing;
        this._errorFigures = errorFigures;
        this._line = line;
        this._column = column;
        this._typedErrorFigure = typedErrorFigure;
        this._problemSpecificInformation = o;

    }

    public String getMessage() {
        return _message;
    }

    public Optional<Object> getProblemSpecificInformation() {
        return Optional.ofNullable(_problemSpecificInformation);
    }

    @Override
    public Optional<Drawing> getErroneousDrawing() {
        return Optional.ofNullable(_errorDrawing);
    }

    @Override
    public Vector<Figure> getErroneousFigures() {
        return _errorFigures;
    }

    @Override
    public <F extends Figure> Optional<F> getErroneousFigure(Class<F> figureClass) {
        if (figureClass.isInstance(_typedErrorFigure)) {
            return Optional.of((F) _typedErrorFigure);
        }
        return Optional.empty();
    }

    @Override
    public int getLine() {
        return _line;
    }

    @Override
    public int getColumn() {
        return _column;
    }

    @Override
    public String getTitle() {
        return _title;
    }

    private static Vector<Figure> createVector(Figure figure) {
        Vector<Figure> figures = new Vector<>();
        figures.add(figure);
        return figures;
    }

    private static Vector<Figure> createVector(Vector<? extends Figure> errorFigures) {
        Vector<Figure> figures = new Vector<>();
        figures.addAll(errorFigures);
        return figures;
    }
}