package uk.ac.man.cs.lethe.abductionTests

import uk.ac.man.cs.lethe.internal.dl.owlapi.OWLApiInterface

import java.io.File
import java.net.URL
import java.util.{Date, HashSet, Set}
import scala.collection.JavaConversions._
import scala.collection.JavaConverters._
import scala.collection.mutable.HashMap
import scala.util.Random
import org.semanticweb.owlapi.apibinding.OWLManager
import org.semanticweb.owlapi.model.parameters.Imports
import org.semanticweb.owlapi.model.{IRI, OWLAxiom, OWLClass, OWLEntity, OWLLogicalAxiom, OWLOntology}
import uk.ac.man.cs.lethe.interpolation.AlchTBoxInterpolatorC
import uk.ac.man.cs.lethe.abduction.{OWLAbducerGeneral, OWLAbducerSignatureBased}
import uk.ac.man.cs.lethe.internal.tools.formatting.SimpleOWLFormatter



object ParticularAbductionTest{ 
  def main(args: Array[String]) = { 
    println("Loading ontology...")
    println(new Date())
    val ontology = OWLApiInterface.getOWLOntology(new File(args(0)))
    println(new Date())
    println("Loaded")

    println("Ontology: ")
    println(SimpleOWLFormatter.format(ontology))
    println()

    val interpolator = new AlchTBoxInterpolatorC()
    val abducerSignature = new OWLAbducerSignatureBased(interpolator,		   
							ontology)
    val abducerGeneral = new OWLAbducerGeneral(interpolator, ontology)


    val factory = OWLManager.createOWLOntologyManager().getOWLDataFactory

    //val  fruit = factory.getOWLClass(IRI.create("http://klappo.com/kb/taxonomy/ingredientModifiers#Langual-%28en%29Fruit"))
    // //val vegetable = factory.getOWLClass(IRI.create("http://klappo.com/kb/taxonomy/ingredientModifiers#Langual-%28en%29VegetableOrVegetableProduct%28usCfr%29"))

    // val vegetable = factory.getOWLClass(IRI.create("http://klappo.com/kb/taxonomy/ingredients#EurofirPT-%28en%29Oil%2CVegetable"))

    // val berries = factory.getOWLClass(IRI.create("http://klappo.com/kb/taxonomy/ingredients#EurofirAT-%28en%29Berries")



    val margheritaPizza = factory.getOWLClass(IRI.create("http://www.semanticweb.org/koopmanp/ontologies/2015/4/simple-pizza-example#MargheritaPizza"))
                                                          
    val vegetarianPizza = factory.getOWLClass(IRI.create("http://www.semanticweb.org/koopmanp/ontologies/2015/4/simple-pizza-example#VegetarianPizza"))
    
    val vegetarianTopping = factory.getOWLClass(IRI.create("http://www.semanticweb.org/koopmanp/ontologies/2015/4/simple-pizza-example#VegetarianTopping"))
    val cheeseTopping = factory.getOWLClass(IRI.create("http://www.semanticweb.org/koopmanp/ontologies/2015/4/simple-pizza-example#CheeseTopping"))
    val mushroomTopping = factory.getOWLClass(IRI.create("http://www.semanticweb.org/koopmanp/ontologies/2015/4/simple-pizza-example#MushroomTopping"))
    val peperoniTopping = factory.getOWLClass(IRI.create("http://www.semanticweb.org/koopmanp/ontologies/2015/4/simple-pizza-example#Peperoni"))


    val axiom = factory.getOWLSubClassOfAxiom(margheritaPizza, vegetarianPizza)
    
    println()
    println("Explain: "+SimpleOWLFormatter.format(axiom))
    println()
    val eliminate = new HashSet[OWLEntity]()
    eliminate.add(vegetarianPizza)
    eliminate.add(vegetarianTopping)
    eliminate.add(cheeseTopping)
    eliminate.add(mushroomTopping)
    eliminate.add(peperoniTopping)

    abducerSignature.removeAbducibles(eliminate)

    println("Using only: "+abducerSignature.getAbducibles.map(_.getIRI.getFragment).mkString(", "))
    println()
    val explanations = abducerSignature.abduce(axiom)

    // val explanations = abducerGeneral.abduceAll(new HashSet[OWLAxiom]()+axiom)
    explanations.foreach{ explanation =>
      println("Explanation: ")
      println(explanation.getAxioms.map(SimpleOWLFormatter.format).mkString("\n"))
      println()
    }
    
  }
}

/**
 * Test performance of abduction runs
 */

object AbductionTester { 

  var axiomPoolToUseFrom = new HashSet[OWLLogicalAxiom]()

  var abducer: OWLAbducerGeneral = _  

  def main(args: Array[String]) = { 

    println("Loading ontology...")
    println(new Date())
    val ontology = OWLApiInterface.getOWLOntology(new File(args(0)))
    println(new Date())
    println("Loaded")


    val axiomsInOnt = ontology.getTBoxAxioms(Imports.EXCLUDED).iterator.asScala
    axiomPoolToUseFrom ++= axiomsInOnt.toSeq.take(100).map(_.asInstanceOf[OWLLogicalAxiom])

    val manager = OWLManager.createOWLOntologyManager
    manager.removeAxioms(ontology, axiomPoolToUseFrom)
    

    val interpolator = new AlchTBoxInterpolatorC()
    abducer = new OWLAbducerGeneral(interpolator,		   
				    ontology)



    while(true){ 
      computeRandomAbductions(1, 2)
    }
  }

  def computeRandomAbductions(minAxioms: Int, maxAxioms: Int) = { 
    val number = Random.nextInt(maxAxioms+1-minAxioms) + minAxioms
    val observation = new HashSet(Random.shuffle(axiomPoolToUseFrom.toSeq).take(number))
    println("Observation: ")
    println(observation.map(SimpleOWLFormatter.format).mkString("\n"))
    println()

    val startTime = new Date().getTime
    println("Explaining ("+new Date()+")")

    /*
    val explanations = abducer.abduce(observation)

    println("Done. (" + new Date()+")")
    if(explanations.isEmpty)
      println("No explanation!")
    explanations.foreach{ explanation => { 
      println("Explanation: ")
      println(explanation.getAxioms.map(SimpleOWLFormatter.format).mkString("\n"))
      println()
    }}
    println()
    */
    val allExplanations = abducer.abduce(observation)
    println("Time taken: "+(new Date().getTime-startTime))
    allExplanations.foreach{ explanation => 
      println("Explanation: ")
      println(explanation.getAxioms.map(SimpleOWLFormatter.format).mkString("\n"))
      println()
    }
  }
}

