package uk.ac.man.cs.lethe.internal.application.statistics

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

import java.io.File
import scala.io.Source
import scala.util.parsing.json.JSON
import uk.ac.man.cs.lethe.internal.application.benchmarks.Benchmark
import uk.ac.man.cs.lethe.internal.dl.datatypes._
import uk.ac.man.cs.lethe.internal.dl.forgetting.direct.ALCFormulaPreparations
import uk.ac.man.cs.lethe.internal.dl.owlapi.OWLExporter


object ClausalFormStatistics { 
  var benchmarkOntologies: Iterable[String] = _


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

    loadConfiguration(new File(args(0)))

    benchmarkOntologies.foreach { ont => 
      println("Ontology: "+ont)
      try { 
	val ontology = try{ 
	  OWLParser.parseURL(ont)
	} catch { 
	  case _: IllegalArgumentException => OWLParser.parseFile(new File(ont))
	}

	ALCFormulaPreparations.initDefinitions()

	val clauses = ALCFormulaPreparations.clauses(ontology)

	val numClauses = clauses.size
	val depth = maxDepth(ontology.tbox.axioms)

	println("Num of clauses: "+clauses.size)
	println("Max depth: "+depth)
	println("Min expansion depth if cyclic: "+(math.pow(2,numClauses+1)+depth))
      } catch { 
	case _: Throwable => println("Exception while parsing")
      }
      
    }
    
  }

  def maxDepth(axioms: Set[Axiom]): Int = { 
    axioms.map(maxDepth).fold(0)(math.max)
  }

  def maxDepth(axiom: Axiom): Int = axiom match { 
    case Subsumption(a, b) => math.max(maxDepth(a), maxDepth(b))
    case ConceptEquivalence(a,b) => math.max(maxDepth(a), maxDepth(b))
  }

  def maxDepth(concept: Concept): Int = concept match { 
    case TopConcept => 0
    case BottomConcept => 0
    case _:BaseConcept => 0
    case ConceptComplement(c) => maxDepth(c)
    case ConceptConjunction(cs) => cs.map(maxDepth).fold(0)(math.max)
    case ConceptDisjunction(cs) => cs.map(maxDepth).fold(0)(math.max)
    case ExistentialRoleRestriction(_, c) => 1+maxDepth(c)
    case UniversalRoleRestriction(_, c) => 1+maxDepth(c)
  }

  def loadConfiguration(configurationFile: File) = { 
    val confString = Source.fromFile(configurationFile).getLines().mkString("\n")

    JSON.parseFull(confString) match { 
      case Some(map: Map[String, Any]) =>  
	benchmarkOntologies = map("benchmarkOntologies").asInstanceOf[List[String]]

        benchmarkOntologies = Set()

        // Check if ontology list is given
        map.get("benchmarkOntologies") match { 
	  case Some(ontologies) => benchmarkOntologies ++= ontologies.asInstanceOf[List[String]]
	  case None => ;
	}

	map.get("benchmarkRoot") match { 

	  // There is a benchmark root given
	  case Some(root) => 
	    var benchmark = new Benchmark(new File(root.asInstanceOf[String]))
	  
	    // check whether we want to filter the benchmark 
	    map.get("expressivities") match { 
	      case Some(exps) => 
		benchmark = benchmark.filterOntologies("expressivity", exps.asInstanceOf[List[String]])
	      case None => ;
	    }
	    map.get("excludeFamilies") match { 
	      case Some(exps) => 
		println("Exclude families: "+exps.asInstanceOf[List[String]].mkString(", "))
		benchmark = benchmark.filterOutOntologies("expressivity", exps.asInstanceOf[List[String]])
	      case None => ;
	    }

            // Add all ontologies of the benchmark
            benchmarkOntologies ++= benchmark.ontologies
	  
	  // There is no benchmark root given
	  case None => ;
	}
      case other => println("nothing parsed: "+other.toString)
    }
  }
}
