// $Id: Paragraph.java,v 1.6 2004/02/27 16:30:00 m31 Exp $
//
// This file is part of the program suite "Principia Mathematica II"
// which is a working prototype for the main project:
// "Hilbert II" - http://www.qedeq.org
//
// Copyright 2001-2004  Michael Meyling <mime@qedeq.org>.
//
// "Principia Mathematica II" is free software; you can redistribute
// it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

package com.meyling.principia.logic.paragraph;


import com.meyling.principia.argument.AbstractDynamicArgumentList;
import com.meyling.principia.argument.Argument;
import com.meyling.principia.argument.ArgumentException;
import com.meyling.principia.argument.Text;
import com.meyling.principia.module.Module;
import com.meyling.principia.module.ModuleCreator;


/**
 * A paragraph contains an axiom, an abbreviation or a proposition of a
 * mathematical theory.
 *
 * @version $Revision: 1.6 $
 * @author  Michael Meyling
 */
public class Paragraph extends AbstractDynamicArgumentList
        implements Argument {

    /** the paragraph could be referenced by this label */
    private final String label;

    /** this text preceeds the paragraph */
    private String preceedingText = null;

    /** this text follows the paragraph */
    private String followingText = null;

    /** Abbreviation, Axiom, Proposition, or whatever */
    private final ParagraphCheck paragraphCheck;



    /**
     * Constructs a paragraph.
     *
     * @param   arguments    list of arguments
     * @throws  ArgumentException    if argument list is not
     *           like {@link LinkLabel}
     *           {@link Text}?
     *           ({@link Abbreviation} | {@link Axiom}
     *            | {@link Proposition})
     *           {@link Text}?
     *           <p>
     *           the question mark is for an optional argument
     *           the pipe symbol is an exclusive &quot;or&quot;
     */
    public Paragraph(final Argument[] arguments)
            throws ArgumentException {
        super(arguments);
        final String convention
            = ParagraphConstants.CONVENTION
            + ModuleCreator.getName(LinkLabel.class)        + " "
            + ParagraphConstants.QUOTED_STRING              + "? ("
            + ModuleCreator.getName(Abbreviation.class)     + " | "
            + ModuleCreator.getName(Axiom.class)            + " | "
            + ModuleCreator.getName(RuleDeclaration.class)  + " | "
            + ModuleCreator.getName(Proposition.class)      + ") "
            + ParagraphConstants.QUOTED_STRING              + "?";
        final int len = arguments.length;
        if (len < 2 || len > 4) {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_NUMBER,
                ModuleCreator.getName(this.getClass())
                + ParagraphConstants.OPERATOR_WITH_TWO_TO_FOUR_ARGUMENTS);
        }
        if (!(arguments[0] instanceof LinkLabel)) {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                ModuleCreator.getName(this.getClass())
                + ParagraphConstants.FIRST_ARGUMENT_TYPE
                + ModuleCreator.getName(LinkLabel.class),
                arguments[0]);
        }
        label = ((Text) arguments[0].getArgument(0)).getText();
        int position = 1;     // here is the main thing
        switch (len) {
            case 2:
                position = 1;
            break;
            case 3:
                if (arguments[1] instanceof Text) {
                    position = 2;
                    preceedingText = ((Text) arguments[1]).getText();
                } else {
                    position = 1;
                    if (!(arguments[2] instanceof Text)) {
                        throw new ArgumentException(
                            ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                            ModuleCreator.getName(this.getClass())
                            + convention,
                            arguments[2]);
                    }
                    followingText = ((Text) arguments[2]).getText();
                }
            break;
            case 4:
                position = 2;
                if (!(arguments[1] instanceof Text)) {
                    throw new ArgumentException(
                        ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                        ModuleCreator.getName(this.getClass())
                        + convention,
                        arguments[1]);
                }
                preceedingText = ((Text) arguments[1]).getText();
                if (!(arguments[3] instanceof Text)) {
                    throw new ArgumentException(
                        ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                        ModuleCreator.getName(this.getClass())
                        + convention,
                        arguments[3]);
                }
                followingText = ((Text) arguments[3]).getText();
           break;
        }

        if (arguments[position] instanceof ParagraphCheck) {
            paragraphCheck = (ParagraphCheck) arguments[position];
        } else {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                ModuleCreator.getName(this.getClass())
                + convention,
                arguments[position]);
        }

    }


    /**
     * Set the label of this paragraph.
     *
     * @param   label     the name of this paragraph
     * @throws  IllegalArgumentException if <code>label == null</code>
     */
// TODO change "construction" arguments too
/*
    public final void setLabel(final String label) {
        if (label == null) {
            throw new IllegalArgumentException(
                ParagraphConstants.NULLPOINTER_PARAMETER);
        }
        this.label = label;
    }
*/


    /**
     * Get the label of this paragraph.
     *
     * @return  the label of this paragraph
     */
    public final String getLabel() {
        return label;
    }


    /**
     * Set the preceeding text of this paragraph.
     *
     * @param   text     the preceeding text of this paragraph
     * @throws  IllegalArgumentException if <code>text == null</code>
     */
// TODO change "construction" arguments too
/*
    public final void setPreceedingtext(final String text) {
        if (text == null) {
            throw new IllegalArgumentException(
                ParagraphConstants.NULLPOINTER_PARAMETER);
        }
        if (this.preceedingText == null) {
            insert(0, new Text(text));
        }
        this.preceedingText = text;
    }
*/


    /**
     * Get the preceeding text of this paragraph.
     *
     * @return  the preceedingText of this paragraph
     */
    public final String getPreceedingText() {
        return preceedingText;
    }


    /**
     * Set the following text of this paragraph.
     *
     * @param   text     the following text of this paragraph
     * @throws  IllegalArgumentException if <code>text == null</code>
     */
// TODO change "construction" arguments too
/*
    public final void setFollowingtext(final String text) {
        if (text == null) {
            throw new IllegalArgumentException(
                ParagraphConstants.NULLPOINTER_PARAMETER);
        }
        if (this.followingText == null) {
            insert(2, new Text(text));
        }
        this.followingText = text;
    }
*/


    /**
     * Get the following text of this paragraph.
     *
     * @return  the followingText of this paragraph
     */
    public final String getFollowingText() {
        return followingText;
    }


    /**
     * Get the meat of this paragraph.
     *
     * @return  the {@link Axiom}, {@link Abbreviation},
     *          {@link Proposition}, etc.
     */
    public final ParagraphCheck getParagraphCheck() {
        return paragraphCheck;
    }


    /**
     * Check if this paragraph could be added.
     *
     * @param   module   module
     * @throws  ArgumentException    if addition is impossible
     */
    public final void check(final Module module)
            throws ArgumentException {
        try {
            module.checkLabel(getLabel());
        } catch (IllegalArgumentException e) {
            throw new ArgumentException(
                ParagraphConstants.CODE_METHOD_ARGUMENT_CHECK_FAILED,
                e.getMessage(),
                getArgument(0));
        }
        paragraphCheck.check(module, label);
    }


    /** @inherited */
    public final Argument create(final Argument[] arguments)
            throws ArgumentException {
        return new Paragraph(arguments);
    }



    /** @inherited */
    public final String toString() {
        StringBuffer buffer = new StringBuffer("Paragraph ");
        for (int i = 0; i < getArgumentSize(); i++) {
            if (i != 0) {
                buffer.append(", ");
            };
            buffer.append(getArgument(i));
        }
        return buffer.toString();
    };

}
