package DialML;

import alice.tuprolog.*;

import java.util.*;

public class VectTheory extends Vector {
  public VectTheory() {
  }

  public void addImplic(Struct prem, Struct concl) {
    Struct[] implic=new Struct[2];
    implic[0]=(Struct)prem.copy();
    implic[1]=(Struct)concl.copy();
    if (!contains(implic)) addElement(implic);
  }

  public void addFact(Struct fact) {
    Struct[] implic=new Struct[2];
    implic[0]=new Struct("");
    implic[1]=(Struct)fact.copy();
    if (!contains(implic)) addElement(implic);
  }

  public void delFact(Struct fact) {
    Struct[] implic=new Struct[2];
    implic[0]=new Struct("");
    implic[1]=new Struct(fact.getName(),fact.copy());
    if (contains(implic)) removeElement(implic);
  }

  public void delImplic(Struct prem,Struct concl){
    Struct[] implic=new Struct[2];
    Enumeration e=elements();
    while (e.hasMoreElements()) {
      implic=(Struct[])e.nextElement();
      if (implic[0].equals(prem) && implic[1].equals(concl)) {
        removeElement(implic);
        break;
      }
    }
  }

  public String toProlog() {
    String result=new String();
    Struct prem,concl;
    Struct[] implic=new Struct[2];
    Enumeration e=elements();
    while (e.hasMoreElements()) {
      implic=(Struct[])e.nextElement();
      prem=implic[0];
      concl=implic[1];
      if (prem.getName().length()==0)
        result+=getPrologFact(concl)+"\n";
      else result+=getPrologImplic(prem,concl)+"\n";
    }
    return result;
  }

  public String toLPPO() {
    String result=new String();
    Struct prem,concl;
    Struct[] implic=new Struct[2];
    Enumeration e=elements();
    while (e.hasMoreElements()) {
      implic=(Struct[])e.nextElement();
      prem=implic[0];
      concl=implic[1];
      if (prem.getName().length()==0)
        result+=">>>>> "+getLogicFact(concl)+"\n";
      else result+=">>>>> "+getLogicImplic(prem,concl)+"\n";
    }
    return result;
  }


  // Transformations de termes en prolog
  public static String getPrologVectData(Vector v) {
    String res=new String("[");
    Enumeration e=v.elements();
    while (e.hasMoreElements()) {
      res+="("+getLogicData((Struct[])e.nextElement())+")";
    }
    return res+"]";
  }
  public static String getLogicData(Struct[] implic) {
    if (implic[0].getName().equals("")) return (implic[1].toString());
    else return (implic[0].toString()+" -> "+implic[1].toString());
  }
  public static String getLogicKnowledge(Struct prem,Struct concl) {
    if (prem.getName().equals("")) return (concl.toString());
    else return (prem.toString()+" -> "+concl.toString());
  }
  public static String getLogicImplic(Struct prem,Struct concl) {
   return (prem.toString()+" -> "+concl.toString());
  }
  public static String getLogicFact(Struct fact) {
   return (fact.toString());
  }
  public static String getPrologImplic(Struct prem,Struct concl) {
   return (concl.toString()+" :- "+prem.toString()+".");
  }
  public static String getPrologFact(Struct fact) {
    return (fact.toString()+".");
  }
  public static String getPrologFact(Struct fact1,Struct fact2) {
   return (fact1.toString()+", "+fact2.toString()+".");
  }

  /** l'ensemble des données contient-il le prédicat fourni ?
   *
   */
  public boolean contient(Struct pred) {
    Struct[] implic;
    Struct prem,concl;
    Enumeration e=elements();
    while (e.hasMoreElements()) {
      implic = (Struct[]) e.nextElement();
      prem = implic[0];
      concl = implic[1];
      if (prem.equals(prem) || concl.equals(prem)) return true;
    }
    return false;
  }

  /** Retourne l'ensemble des prédicats qui sont validés par la même constante que celle du fait fourni
   *
   */
  public Vector getPredsCst(Struct fact) {
    Struct arg,fact1,arg1;
    Vector res=new Vector();

    if (fact.getArity()!=1) return res; // arité supérieure non gérée actuellement
    arg=getFirstArg(fact);
    Struct[] implic1;
    Enumeration e=elements();
    while (e.hasMoreElements()) {
      implic1 = (Struct[]) e.nextElement();
      if (isFact(implic1)) {
        fact1=implic1[1];
        if (fact1.getArity()==1) {
          arg1=getFirstArg(fact1);
          if (arg1.equals(arg)) {
            if (!res.contains(fact1)) res.addElement(fact1);
          }
        }
      }
    }
    return res;
  }

  public static boolean isFact(Struct[] implic) {
    return (implic[0].getName().equals(""));
  }

  /** Retourne le prédicat généralisé
   *
   */
  public static Struct getGenPred(Struct pred) {
    try {
      if (pred.getName().equals("not"))
        return new Struct("not",
                          new Struct( ( (Struct) pred.getArg(0)).getName(),
                                     new Var("X")));
      else
        return new Struct(pred.getName(), new Var("X"));
    }
    catch(Exception e) {
    }
    return new Struct();
  }

  /** Retourne le premier argument
   *
   */
  public static Struct getFirstArg(Struct pred) {
    try {
      if (pred.getName().equals("not"))
        return ((Struct)((Struct)pred.getArg(0)).getArg(0));
      else
        return ((Struct)pred.getArg(0));
    }
    catch(Exception e) {
    }
    return new Struct();
  }
}