/*
 * Equivalence.java
 *
 * Copyright (C) 2008  Pei Wang
 *
 * This file is part of Open-NARS.
 *
 * Open-NARS 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.
 *
 * Open-NARS 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with Open-NARS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nars.language;

import java.util.Arrays;
import nars.inference.TemporalRules;
import nars.io.Symbols.NativeOperator;

/**
 * A Statement about an Equivalence relation.
 */
public class Equivalence extends Statement {

    private int temporalOrder = TemporalRules.ORDER_NONE;

    /**
     * Constructor with partial values, called by make
     *
     * @param components The component list of the term
     */
    private Equivalence(Term[] components, int order) {
        super(components);
        
        temporalOrder = order;
        
        init(components);
    }

    /**
     * Clone an object
     *
     * @return A new object
     */
    @Override
    public Equivalence clone() {
        return new Equivalence(term, temporalOrder);
    }
    
    @Override public Equivalence clone(final Term[] t) {        
        if (t.length!=2)
            throw new RuntimeException("Equivalence requires 2 components: " + Arrays.toString(t));
        
        return make(t[0], t[1], temporalOrder);
    }
    
    /** alternate version of Inheritance.make that allows equivalent subject and predicate
     * to be reduced to the common term.      */
    public static Term makeTerm(final Term subject, final Term predicate, int temporalOrder) {
        if (subject.equals(predicate))
            return subject;                
        return make(subject, predicate, temporalOrder);        
    }    


    /**
     * Try to make a new compound from two term. Called by the inference
     * rules.
     *
     * @param subject The first component
     * @param predicate The second component
     * @param memory Reference to the memory
     * @return A compound generated or null
     */
    public static Equivalence make(Term subject, Term predicate) {  // to be extended to check if subject is Conjunction
        return make(subject, predicate, TemporalRules.ORDER_NONE);
    }

    public static Equivalence make(Term subject, Term predicate, int temporalOrder) {  // to be extended to check if subject is Conjunction
        if (invalidStatement(subject, predicate)) {
            return null;
        }
        
        if ((subject instanceof Implication) || (subject instanceof Equivalence)
                || (predicate instanceof Implication) || (predicate instanceof Equivalence) ||
                (subject instanceof Interval) || (predicate instanceof Interval)) {
            return null;
        }
                
        if ((temporalOrder == TemporalRules.ORDER_BACKWARD)
                || ((subject.compareTo(predicate) > 0) && (temporalOrder != TemporalRules.ORDER_FORWARD))) {
            Term interm = subject;
            subject = predicate;
            predicate = interm;
        }
        
        NativeOperator copula;
        switch (temporalOrder) {
            case TemporalRules.ORDER_BACKWARD:
                temporalOrder = TemporalRules.ORDER_FORWARD;
                //TODO determine if this missing break is intended
            case TemporalRules.ORDER_FORWARD:
                copula = NativeOperator.EQUIVALENCE_AFTER;
                break;
            case TemporalRules.ORDER_CONCURRENT:
                copula = NativeOperator.EQUIVALENCE_WHEN;
                break;
            default:
                copula = NativeOperator.EQUIVALENCE;
        }
        
        Term[] t = Term.toSortedSetArray(subject, predicate);
        if (t.length != 2)
            return null;        
        return new Equivalence(t, temporalOrder);
    }

    /**
     * Get the operator of the term.
     *
     * @return the operator of the term
     */
    @Override
    public NativeOperator operator() {
        switch (temporalOrder) {
            case TemporalRules.ORDER_FORWARD:
                return NativeOperator.EQUIVALENCE_AFTER;
            case TemporalRules.ORDER_CONCURRENT:
                return NativeOperator.EQUIVALENCE_WHEN;
        }
        return NativeOperator.EQUIVALENCE;
    }

    /**
     * Check if the compound is commutative.
     *
     * @return true for commutative
     */
    @Override
    public boolean isCommutative() {
        return (temporalOrder != TemporalRules.ORDER_FORWARD);
    }

    @Override
    public int getTemporalOrder() {
        return temporalOrder;
    }
}

@@ -4064,23 +4064,149 @@
     
-%0A        Term%5B%5D
+Term%5B%5D t;%0A        if (temporalOrder==TemporalRules.ORDER_FORWARD)%0A            t = new Term%5B%5D %7B subject, predicate %7D;%0A        else%0A           
  t =
@@ -4249,16 +4249,24 @@
 icate);%0A
+       %0A
         

fix equivalence order problem, for example <b </> a>. shouldnt be parsed as <a </> b>. while it would be fine if it would be <|> or <=>