package uk.ac.man.cs.lethe.internal.dl.proofs

import java.io.File
import org.semanticweb.owlapi.model.{IRI, OWLAxiom, OWLClass, OWLEntity, OWLOntology}
import com.clarkparsia.owlapi.explanation.DefaultExplanationGenerator
import com.clarkparsia.owlapi.explanation.util.ExplanationProgressMonitor
import org.semanticweb.owlapi.apibinding.OWLManager
import uk.ac.man.cs.lethe.internal.dl.datatypes.Subsumption
import uk.ac.man.cs.lethe.internal.dl.forgetting._
import uk.ac.man.cs.lethe.internal.dl.forgetting.abox.ABoxForgetter
import uk.ac.man.cs.lethe.internal.dl.interpolation.OntologyInterpolator
import uk.ac.man.cs.lethe.internal.dl.owlapi.{OWLApiConverter, OWLApiInterface}
import uk.ac.man.cs.lethe.internal.tools.MockProgressBar
import uk.ac.man.cs.lethe.internal.tools.formatting.SimpleOWLFormatter

class ProofGenerator(
  interpolator: OntologyInterpolator,
  ontology: OWLOntology) {

  val pinpointer = new DefaultExplanationGenerator(
    ontology.getOWLOntologyManager,
    new org.semanticweb.HermiT.Reasoner.ReasonerFactory(),
    ontology,
    new ExplanationProgressMonitor(){
      override def foundAllExplanations() = { }
      override def foundExplanation(axioms: java.util.Set[OWLAxiom]) =
      {}
      override def isCancelled = false
    }
  )


  def generateProofForSubsumption(lhs: OWLClass, rhs: OWLClass) = {    

    val manager = ontology.getOWLOntologyManager

    val axiom = manager.getOWLDataFactory.getOWLSubClassOfAxiom(lhs,rhs)

    val justification = pinpointer.getExplanation(axiom)


    val justOntology = manager.createOntology()
    manager.addAxioms(justOntology, justification)

    println()
    println()
    println("Justification for "+SimpleOWLFormatter.format(axiom))
    println("=====================================================================")
    println()
    println(SimpleOWLFormatter.format(justOntology))
    println()
    println()

    val signature = Set[OWLEntity](lhs, rhs)

    val interpolant = interpolator.uniformInterpolant(justOntology,signature)
  }

}


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

    val owlFile = args(0)
    val lhs = args(1)

    val rhs = 
      if(args.size>2)
        args(2)
      else
        "BOT"

    val ontology = OWLApiInterface.getOWLOntology(new File(owlFile), true)


    val factory = ontology.getOWLOntologyManager.getOWLDataFactory

    val lhsConcept = factory.getOWLClass(IRI.create(lhs))
    val rhsConcept =
      if(rhs.equals("BOT"))
        factory.getOWLNothing()
      else
        factory.getOWLClass(IRI.create(rhs))

//    ABoxForgetter.progressBar = MockProgressBar
    ABoxForgetter.noFiltration = true
    ABoxForgetter.clausifyOnce = true
    val inferenceLogger = ABoxForgetter.inferenceLogger


    val interpolator = new OntologyInterpolator(ABoxForgetter)//, universalRoles = false)

    val proofGenerator = new ProofGenerator(interpolator, ontology)

    proofGenerator.generateProofForSubsumption(lhsConcept, rhsConcept)

    println(inferenceLogger.derivations.mkString("\n"))
    println(inferenceLogger.translatedDerivations.mkString("\n"))

    inferenceLogger.printProofFor(
      Subsumption(
        OWLApiConverter.convert(lhsConcept),
        OWLApiConverter.convert(rhsConcept)
      )
    )

    //inferenceLogger.printWriter.close()
  }
}

object Example {
  def main(args: Array[String]) = {
    val manager = OWLManager.createOWLOntologyManager()
    val factory = manager.getOWLDataFactory()
    val ontology = manager.createOntology()

    val pizza = factory.getOWLClass(IRI.create("Pizza"));
    val hasTopping = factory.getOWLObjectProperty(IRI.create("hasTopping"))
    val vegetarianPizza = factory.getOWLClass(IRI.create("VegetarianPizza"))
    val margherita = factory.getOWLClass(IRI.create("Margherita"))
    val vegetarian = factory.getOWLClass(IRI.create("Vegetarian"))
    val mozarella = factory.getOWLClass(IRI.create("Mozarella"))
    val tomato = factory.getOWLClass(IRI.create("TomatoTopping"))

    manager.addAxiom(ontology, factory.getOWLSubClassOfAxiom(mozarella, vegetarian))
    manager.addAxiom(ontology, factory.getOWLSubClassOfAxiom(tomato, vegetarian))
    manager.addAxiom(ontology, factory.getOWLSubClassOfAxiom(margherita,
      factory.getOWLObjectAllValuesFrom(hasTopping,
        factory.getOWLObjectUnionOf(mozarella, tomato))))
    manager.addAxiom(ontology, factory.getOWLEquivalentClassesAxiom(vegetarianPizza,
      factory.getOWLObjectAllValuesFrom(hasTopping, vegetarian)
    ))

    println("Input ontology: ")
    println("================")
    SimpleOWLFormatter.format(ontology)
    println()

    ABoxForgetter.noFiltration = true
    ABoxForgetter.clausifyOnce = true

    val interpolator = new OntologyInterpolator(ABoxForgetter,universalRoles = false)


    val proofGenerator = new ProofGenerator(interpolator, ontology)

    proofGenerator.generateProofForSubsumption(margherita, vegetarianPizza)

    val inferenceLogger = ABoxForgetter.inferenceLogger
    //inferenceLogger.printWriter.close()
  }
}