package edu.stanford.smi.protegex.owl.model.impl;

import edu.stanford.smi.protege.model.FrameID;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protegex.owl.model.*;

import java.util.*;

/**
 * The base class of DefaultOWLIntersectionClass and DefaultOWLUnionClass.
 *
 * @author Holger Knublauch  <holger@knublauch.com>
 */
public abstract class AbstractOWLNAryLogicalClass extends AbstractOWLLogicalClass
        implements OWLNAryLogicalClass {


    protected AbstractOWLNAryLogicalClass(KnowledgeBase kb, FrameID id) {
        super(kb, id);
    }


    protected AbstractOWLNAryLogicalClass() {
    }


    public void addOperand(RDFSClass operand) {
        RDFList list = (RDFList) getPropertyValue(getOperandsProperty());
        if (list == null || getOWLModel().getRDFNil().equals(list)) {
            list = getOWLModel().createRDFList();
            setOwnSlotValue(getOperandsProperty(), list);
        }
        list.append(operand);
    }


    public boolean equalsStructurally(RDFObject object) {
        if (object instanceof AbstractOWLNAryLogicalClass) {
            AbstractOWLNAryLogicalClass compCls = (AbstractOWLNAryLogicalClass) object;
            if (getOperatorSymbol() == compCls.getOperatorSymbol()) {
                return OWLUtil.equalsStructurally(getOperands(), compCls.getOperands());
            }
        }
        return false;
    }

    /*public String getBrowserText() {
       final Collection operands = getOperands();
       char operator = getOperatorSymbol();
       if (operands.size() == 0) {
           return "<empty " + getClass().getName() + ">";
       }
       String text = "";
       for (Iterator it = operands.iterator(); it.hasNext();) {
           Cls cls = (Cls) it.next();
           String clsText = cls instanceof RDFSClass ?
                   ((RDFSClass) cls).getNestedBrowserText() :
                   cls.getBrowserText();
           text += clsText;
           if (it.hasNext()) {
               text += " " + operator + " ";
           }
       }
       return text;
   } */


    public Collection getNamedOperands() {
        Collection result = new HashSet();
        for (Iterator it = getOperands().iterator(); it.hasNext();) {
            RDFSClass operand = (RDFSClass) it.next();
            if (operand instanceof RDFSNamedClass) {
                result.add(operand);
            }
        }
        return result;
    }


    public String getNestedBrowserText() {
        return "(" + getBrowserText() + ")";
    }


    public Collection getOperands() {
        RDFList list = (RDFList) getPropertyValue(getOperandsProperty());
        if (list == null) {
            return Collections.EMPTY_LIST;
        }
        else {
            return list.getValues();
        }
    }


    public boolean hasOperandWithBrowserText(String browserText) {
        for (Iterator it = getOperands().iterator(); it.hasNext();) {
            RDFSClass operand = (RDFSClass) it.next();
            if (browserText.equals(operand.getBrowserText())) {
                return true;
            }
        }
        return false;
    }


    public boolean hasSameOperands(OWLNAryLogicalClass other) {
        Set setA = new HashSet();
        for (Iterator it = getOperands().iterator(); it.hasNext();) {
            RDFSClass operand = (RDFSClass) it.next();
            setA.add(operand.getBrowserText());
        }
        Set setB = new HashSet();
        for (Iterator it = other.getOperands().iterator(); it.hasNext();) {
            RDFSClass operand = (RDFSClass) it.next();
            setB.add(operand.getBrowserText());
        }
        if (setA.size() == setB.size()) {
            setA.removeAll(setB);
            return setA.isEmpty();
        }
        else {
            return false;
        }
    }


    public Iterator listOperands() {
        return getOperands().iterator();
    }


    public void removeOperand(RDFSClass operand) {
        DefaultRDFList.removeListValue(this, getOperandsProperty(), operand);
    }
}
