
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.collection.mutable.{HashMap, HashSet}
import scala.io.Source
import uk.ac.man.cs.lethe.internal.dl.analysis.DeepSymbolAnalyser
import uk.ac.man.cs.lethe.internal.dl.datatypes.BaseConcept
import uk.ac.man.cs.lethe.internal.dl.datatypes.BaseRole
import uk.ac.man.cs.lethe.internal.dl.datatypes.OntologyFilter
import uk.ac.man.cs.lethe.internal.tools.MultiSet

/**
 * Determine for each symbol how many time outs it caused
 */

object TimeoutStatistics { 

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

    val resultsFile = new File(args(0))

    val experiments = new MultiSet[String]()
    val timeouts = new MultiSet[String]()
    val timeoutCausers = new HashMap[String, MultiSet[String]]() // ont -> (symbol -> timeouts)
    val appearances = new HashMap[String, MultiSet[String]]() // ont -> (symbol -> occurrences)
    

    val ontMatcher = """Ontology: (.*)""".r
    val forgMatcher = """Forgetting the following words: TreeSet\(([^)]+)\)""".r
    val sigMatcher = """Desired signature: Set\(([^)]+)\)""".r
    val timeoutMatcher = """.*Timeout exceeded.*""".r
  
    var currentlyForgetting = Iterable[String]()
    var currentOnt = ""


    val ont2sig = new HashMap[String, Set[String]]()
    
    val ignoreOntology = new HashSet[String]()

//    OWLApiConfiguration.SIMPLIFIED_NAMES = true

    def getSig(ontology: String): Set[String] = { 
      ont2sig.get(ontology) match { 
	case Some(sig) => sig
	case None => { 
	  println("loading "+ontology)
	  try{ 
	    val ont = OWLParser.parseFile(new File(ontology))
	    val sig = ont.signature
	    assert(!sig.isEmpty)
	    ont2sig.put(ontology, sig)
	    sig.foreach{ s => if(!timeoutCausers(ontology).contains(s)) timeoutCausers(ontology).put(s, 0)}
	    sig
	  } catch { 
	    case e: Throwable => Set();//ignoreOntology.add(ontology)
	  }
	}
      }
    }


    Source.fromFile(resultsFile)(io.Codec("ISO-8859-1")).getLines.foreach{ _ match { 
      case ontMatcher(ont) => { 
	if(!appearances.contains(ont)){ 
	  appearances.put(ont, new MultiSet[String]())
	  timeoutCausers.put(ont, new MultiSet[String]())
	}
	currentOnt = ont
	experiments.add(currentOnt)
      }
      case forgMatcher(list) => { 
	currentlyForgetting = list.split(", ")
	currentlyForgetting.foreach{ appearances(currentOnt).add }
      }
      case sigMatcher(list) => { 
	val uiSignature = list.split(", ").toSet
	val signature = getSig(currentOnt)
	currentlyForgetting = signature -- uiSignature 
	currentlyForgetting.foreach{ appearances(currentOnt).add }
      }
      case timeoutMatcher() => { 
	timeouts.add(currentOnt)
	currentlyForgetting.foreach{ timeoutCausers(currentOnt).add }
      }
      case _ => ;
    } }

    timeouts.foreach{ pair =>
      val (on, timeouts) = pair
      try{ 
	// var ontology = OWLParser.parseFile(new File(on))
	// ontology = OntologyFilter.restrictToALC(ontology)
	// val analysis = DeepSymbolAnalyser.analyseSymbols(ontology)
	println()
	val timeoutsAmount = timeouts.toDouble/experiments(on)
	println("Complete "+on+": %.2f%%" format timeoutsAmount*100)
	timeoutCausers(on).toSeq.sortBy(pair => pair._2.toDouble/appearances(on)(pair._1)).foreach{ pair => 
	  val symbol = pair._1.toString
          print(symbol+": "+timeoutCausers(on)(symbol)+" ("+timeouts+")")
    	  print(" ---> %.2f%%" format (100*timeoutCausers(on)(symbol).toDouble/appearances(on)(symbol)))
          println("  ("+timeoutCausers(on)(symbol)+"/"+appearances(on)(symbol)+")")
//	  println(analysis.getOrElse(BaseConcept(symbol), analysis.getOrElse(BaseRole(symbol),null)))
	}
      } catch { 
	case e: Throwable => e.printStackTrace(); println("Error with "+on)
      }
    }
  }
}

