#!python

import logging
import argparse
from libabstractor.SparqlQuery import SparqlQuery
from libabstractor.QueryLibrary import QueryLibrary
from libabstractor.RdfGraph import RdfGraph


class Abstractor(object):
    """Abstractor main class"""

    def __init__(self):
        """Init

        Parse args and get prefixes
        """
        parser = argparse.ArgumentParser(description="Generate AskOmics abstraction from a SPARQL endpoint")

        parser.add_argument("-s", "--source", type=str, help="RDF data source (SPARQL endpoint url or path to RDF file)", required=True)
        parser.add_argument("-t", "--source-type", choices=['sparql', 'xml', 'turtle', 'nt'], help="Source format", default="sparql")

        parser.add_argument("--askomics-internal-namespace", type=str, help="AskOmics internal namespace", default="http://askomics.org/internal/")

        parser.add_argument("-o", "--output", type=str, help="Output file", default="abstraction.rdf")
        parser.add_argument("-f", "--output-format", choices=['xml', 'turtle', 'nt'], help="RDF format", default="turtle")

        parser.add_argument("-m", "--mode", choices=["all", "batch", "owl", "askomics"], help="Scan mode: all: 3 queries to get all entities,\
         relation and attributes. batch: 3 queries for each entity. owl: 3 queries using existant owl ontology. askomics: 3 queries using askomics ontology (NOT IMPLEMENTED YET)", default="all")

        parser.add_argument("-v", "--verbosity", action="count", help="increase output verbosity")

        self.args = parser.parse_args()

        logging_level = logging.CRITICAL
        if self.args.verbosity is None or self.args.verbosity == 1:
            logging_level = logging.ERROR
        elif self.args.verbosity == 2:
            logging_level = logging.WARNING
        elif self.args.verbosity == 3:
            logging_level = logging.INFO
        elif self.args.verbosity > 3:
            logging_level = logging.DEBUG

        logging.basicConfig(level=logging_level)

    def main(self):
        """main"""
        sparql = SparqlQuery(self.args.source, self.args.source_type)
        library = QueryLibrary()

        rdf = RdfGraph(self.args.askomics_internal_namespace)

        if self.args.source_type == "sparql":
            rdf.add_location(self.args.source)

        if self.args.mode == "all":
            logging.debug("Get entities and relation")
            rdf.add_entities_and_relations(sparql.process_query(library.entities_and_relations))
            logging.debug("Get decimal attributes")
            rdf.add_decimal_attributes(sparql.process_query(library.entities_and_numeric_attributes))
            logging.debug("Get text attributes")
            rdf.add_text_attributes(sparql.process_query(library.entities_and_text_attributes))

        elif self.args.mode == "batch":
            logging.debug("Get all entities, then, get relations and attributes for each entity")
            entities = sparql.process_query(library.get_entities)
            rdf.add_entities(entities)
            for entity_dict in entities:
                entity = entity_dict["entity"]
                if rdf.check_entity(entity):
                    # relation
                    relations = sparql.process_query(library.get_relation_for_entity(entity))
                    for relation_dict in relations:
                        rdf.add_relation(entity, relation_dict["relation"], relation_dict["target_entity"])
                    # numeric attribute
                    attributes = sparql.process_query(library.get_numeric_attribute_for_entity(entity))
                    for attribute_dict in attributes:
                        rdf.add_attribute(entity, attribute_dict["attribute"])

                    text_attributes = sparql.process_query(library.get_text_attribute_for_entity(entity))
                    for attribute_dict in text_attributes:
                        rdf.add_attribute(entity, attribute_dict["attribute"], decimal=False)

        elif self.args.mode == "owl":
            logging.debug("Use OWL ontology")
            result = sparql.process_query(library.ontologies)
            for res in result:
                logging.debug(res["ontology"])
                logging.debug("Get entities and relation")
                rdf.add_entities_and_relations(sparql.process_query(library.entities_and_relations_with_ontology(res["ontology"])))
                logging.debug("Get decimal attributes")
                rdf.add_decimal_attributes(sparql.process_query(library.entities_and_numeric_attributes_with_ontology(res["ontology"])))
                logging.debug("Get text attributes")
                rdf.add_text_attributes(sparql.process_query(library.entities_and_text_attributes_with_ontology(res["ontology"])))

        elif self.args.mode == "askomics":
            logging.debug("Use AskOmics ontology")
            raise NotImplementedError

        logging.debug("Write RDF ({}) into {}".format(self.args.output_format, self.args.output))
        rdf.graph.serialize(destination=self.args.output, format=self.args.output_format, encoding="utf-8" if self.args.output_format == "turtle" else None)


if __name__ == '__main__':
    """main"""
    Abstractor().main()
