// $Id: PredicateVariable.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.basic;


import com.meyling.principia.argument.Argument;
import com.meyling.principia.argument.ArgumentException;
import com.meyling.principia.argument.CounterMarker;


/**
 * Predicate variable with argument list.
 *
 * @version $Revision: 1.6 $
 * @author  Michael Meyling
 */
public class PredicateVariable extends AbstractFormula
        implements Argument, Formula {

    /** predicate variable identity number */
    private final CounterMarker number;

    /** arguments of predicate */
    private final SubjectVariableMarker[] variables;


    /**
     * Constructs a predicate variable with an argument list.
     *
     * @param   arguments identity number of predicate variable
     *          and  a list of arguments that are all an instance
     *          of {@link SubjectVariableMarker}
     * @throws  ArgumentException if there are not
     *          exactly two arguments or the first argument is no
     *          instance of {@link CounterMarker} or
     *          the second argument is no instance of
     *          {@link RegularArgumentList} or
     *          the entries of the second argument are
     *          no instances of {@link SubjectVariableMarker}
     */
    public PredicateVariable(final Argument[] arguments)
            throws ArgumentException {
        super(arguments);
        if (arguments.length != 2) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_NUMBER,
                BasicCreator.getName(PredicateVariable.class)
                + BasicConstants.OPERATOR_WITH_TWO_ARGUMENTS);
        }
        if (!(arguments[0] instanceof CounterMarker)) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                BasicCreator.getName(PredicateVariable.class)
                + BasicConstants.FIRST_ARGUMENT_TYPE
                + BasicConstants.COUNTER,
                arguments[0]);
        }
        if (!(arguments[1] instanceof RegularArgumentList)) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                BasicCreator.getName(PredicateVariable.class)
                + BasicConstants.SECOND_ARGUMENT_TYPE
                + BasicConstants.ARGUMENT_LIST,
                arguments[1]);
        }
        this.number = (CounterMarker) arguments[0];
        final RegularArgumentList list = (RegularArgumentList) arguments[1];
        this.variables
            = new SubjectVariableMarker[arguments[1].getArgumentSize()];
        int i = 0;
        try {
            for (i = 0; i < this.variables.length; i++) {
                this.variables[i]
                    = (SubjectVariableMarker) arguments[1].getArgument(i);
            }
        } catch (ClassCastException e) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                BasicConstants
                .SUBJECT_VARIABLE_EXPECTED_IN_SECOND_ARGUMENT
                + i,
                arguments[i].getArgument(i));
        }
// TODO better use something like
//        System.arraycopy(argument, 1, this.argument, 0,
//                            argument.length - 1);
    }


    /**
     * Get the identity number of predicate variable.
     * @return  identity number
     */
    public int getNumber() {
        return number.getNumber();
    }


    /**
     * Get the argument.
     * @return  argument
     */
    public final SubjectVariableMarker[] getArgument() {
        return variables;
    }


    /**
     * @inherited
     * @return  always 0
     */
    public final int getPartFormulaSize() {
        return 0;
    }


    /**
     * @inherited
     * @return  will never occur
     * @throws  IllegalArgumentException always
     */
    public final Formula getPartFormula(final int i) {
        throw new IllegalArgumentException(
            BasicConstants.WRONG_FORMULA_NUMBER);
    }


    /** @inherited */
    public final SubjectVariables getFreeSubjectVariables() {
        return new SubjectVariables(this.variables);
    }


    /** @inherited */
    public final SubjectVariables getBoundSubjectVariables() {
        return new SubjectVariables();
    }


    /** @inherited */
    public final SubjectVariables getSubjectVariables() {
        return new SubjectVariables(this.variables);
    }


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


    /** @inherited */
    public final String toString() {
        final StringBuffer buffer = new StringBuffer();
        buffer.append("R").append(number.toString());
        if (variables.length > 0) {
            buffer.append("(");
            for (int i = 0; i < variables.length; i++) {
                if (i > 0) {
                    buffer.append(", ");
                }
                buffer.append(variables[i].toString());
            }
            buffer.append(")");
        }
        return buffer.toString();
    }


}
