/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package org.biohackathon.SPARQLBuilder.OWL;

import java.io.*;
import java.util.*;

/**
 *
 * @author atsuko
 */

public class QueryPathGenerator {
    private String sparqlEndpoint = null;
    private RDFSchemaAnalyzerFactory factory = null;
    private RDFSchemaAnalyzer analyzer = null;
    private OWLClassGraph graph;

    private Map<String, String> clabels;
    
    private static final String CDIR = "cdata";
    private static final String ODIR = "owldata";
        
    /*
    public static void main(String[] args){
        QueryPathGenerator qpg = new QueryPathGenerator();
        //String[] elist = qpg.getFactory().getEndpointURIList();
        List<String> elist = new LinkedList<String>();
        File file0 = new File("eplist.txt");
        try{
            BufferedReader br = new BufferedReader(new FileReader(file0));
            String buf = null;
            while( (buf = br.readLine()) != null){
                elist.add(buf);
            }
        }catch(IOException e){
            System.err.println(e);
        }
        
        ListIterator<String> eit = elist.listIterator();
        int i = 0;
        while(eit.hasNext()){
            String ep = eit.next();
            qpg.setSPARQLendpoint(ep);
            qpg.graph = new OWLClassGraph(qpg.analyzer);
            SClass[] classes = qpg.getClasses(null);
            File file1 = new File("path".concat(Integer.toString(i)).concat(".txt"));
            File file2 = new File("ptable".concat(Integer.toString(i)).concat(".txt"));
            try{
                BufferedWriter bw1 = new BufferedWriter(new FileWriter(file1));
                BufferedWriter bw2 = new BufferedWriter(new FileWriter(file2));
                String jsonstr = "[";
                int m = 0;
                for ( int j = 0 ; j < classes.length; j ++ ){
                    SClass start = classes[j];
                    for ( int k = j + 1 ; k < classes.length; k++ ){
                        SClass end = classes[k];
                        Path[] paths = qpg.getPaths(start.getClassURI(), end.getClassURI(), false);                        
	                for( int l = 0; l < paths.length; l++ ){
                            if ( paths[l] == null ){
                                continue;
                            }
	                    if (m > 0 ){
                 	        jsonstr += ",";
	                    }
                            double cost = paths[l].computeCost();                                                        
                            bw2.write(Double.toString(cost));
                            bw2.write(",");
                            bw2.write(Boolean.toString(EndpointAccess.checkPath(paths[l], ep)));
                            bw2.newLine();
                            jsonstr += paths[i].toJSONString3(classes);
                            m++;
	                }
                    }
                }
                jsonstr += "]";
                bw1.write(jsonstr);
                bw1.newLine();
                
                bw1.close();
                bw2.close();
            }catch(IOException e){
                System.err.println(e);
            }
            i++;
        }
    }
    */
    
    public QueryPathGenerator(){
        factory = new RDFSchemaAnalyzerFactory(CDIR);
    }

    public QueryPathGenerator(String sparqlEndpoint){
        factory = new RDFSchemaAnalyzerFactory(CDIR);
        setSPARQLendpoint(sparqlEndpoint);
    }
    
    public void setOWLClassGraph(String startClass){
        graph = new OWLClassGraph(analyzer, sparqlEndpoint, startClass);
    }
    
    public SClass[] getClasses(String keyword){
        String[] keywords = null;
        if ( keyword != null ){
            if ( keyword.length() != 0 ){
                keywords = new String[1];
                keywords[0] = keyword;
            }
        }
        try {
            return analyzer.getOWLClasses(null, keywords, null, true);
        }catch(Exception e){
            System.err.println(e);
            return null;
        }
    } 
    
    public Path[] getPaths(String startClass, String endClass){
        if (startClass == null || endClass == null){
            return null;
        }
        if ( graph == null ){
            //System.err.println("Class graph is null."); 
            setOWLClassGraph(startClass);
        }
        return graph.getPaths(startClass, endClass);
    }
    
    public void setSPARQLendpoint(String sparqlEndpoint){
        this.sparqlEndpoint = sparqlEndpoint;
        setAnalyzer();
    }
    
    public RDFSchemaAnalyzerFactory getFactory(){
        return factory;
    }

    private void setAnalyzer(){
        try {
            analyzer = factory.create(sparqlEndpoint);
        } catch (Exception e) {
            System.err.println(e);
        }
    }
    
    public String getClassLabel(String classURI){
        return clabels.get(classURI);
    }
    
    public void setClassLabels(SClass[] classes){
        clabels = new HashMap<String, String>();
        Map<String, String> extLabels = getClassLabelsFromExternal();
        
        for ( int i = 0 ; i < classes.length; i++ ){
            String classURI = classes[i].getClassURI();

            Label[] labels = classes[i].getLabels();
            String label = null;
            for ( int j = 0 ; j < labels.length; j++ ){
                if ( labels[j].getLanguage() == null ){
                    label = labels[j].getLabel(); 
                    break;
                }else if ( labels[j].getLanguage().equals("en") || labels[j].getLanguage().equals("") ){
                    label = labels[j].getLabel(); 
                    break;
                }
            }
            if ( label == null ){
                label = extLabels.get(classURI);
            }
            if ( label == null ){
                String[] uris = classURI.split("/");
                String tmplabel = uris[uris.length-1];
                String[] tmplabel2 = tmplabel.split("#");
                label = tmplabel2[tmplabel2.length-1];
            }
            clabels.put(classURI, label);
        }
    }

    public static String getClassLabelfromList(String classURI, SClass[] classes){
        if ( classURI == null ){
                    return "";
        }
        SClass sclass = null;
        for ( int i = 0 ; i < classes.length; i++ ){
            if ( classURI.equals(classes[i].getClassURI()) ){
                return getClassLabelfromClass(classes[i]);
            }
        }
        return "";
    }
    
    public static String getClassLabelfromClass(SClass sclass){
        Label[] labels = sclass.getLabels();
        for ( int i = 0 ; i < labels.length; i++ ){
            if ( labels[i].getLanguage() == null ){
                return labels[i].getLabel();
            }else if ( labels[i].getLanguage().equals("en") ){
                return labels[i].getLabel();
            }
        }
        String[] url = sclass.getClassURI().split("/");
        String tmplabel = url[url.length-1];
        String[] tmplabel2 = tmplabel.split("#");
        String label = tmplabel2[tmplabel2.length-1];
        return label;
    }
        
    public Map<String, String> getClassLabelsFromExternal(){
        return  OWLLabelReader.readLabels(ODIR);
    }
    
    public OWLClassGraph getOWLClassGraph(){
        /*if ( graph == null ){
            graph = new OWLClassGraph(analyzer);             
        }*/
        return graph;
    }
    
    public SClass[] getReachableClasses(){
        List<String> clURIs = graph.getReachableClasses();
        SClass[] orgclasses = null;
        try {
            orgclasses = analyzer.getOWLClasses(null, null, null, true);
        }catch( Exception e ){
            System.err.println(e);
            return null;
        }
        HashMap<String, SClass> orgmap = new HashMap<String, SClass>();
        for (int i = 0; i < orgclasses.length; i++ ){
            orgmap.put(orgclasses[i].getClassURI(), orgclasses[i]);
        }
        
        SClass[] classes = new SClass[clURIs.size()];
        int j = 0;
        ListIterator<String> uit = clURIs.listIterator();
        while(uit.hasNext()){
            String u = uit.next();
            SClass cl = orgmap.get(u);
            classes[j] = cl;
            j++;
        }
        return classes;
    }
    
    public SortedSet<String> getSortedClasses(SClass[] classes){
        setClassLabels(classes);
        SortedSet<String> sortedClasses = new TreeSet<String>();
        for (int i = 0 ; i < classes.length; i++ ){
            String uri = classes[i].getClassURI();
            String label = getClassLabel(uri);
            StringBuilder classbuilder = new StringBuilder(label);
            classbuilder.append("\t");
            classbuilder.append(classes[i].getNumOfInstances());
            classbuilder.append("\t");
            classbuilder.append(uri);
            sortedClasses.add(classbuilder.toString());
        }

        return sortedClasses;
    }
}
