using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Web;
using VDS.RDF;
using VDS.RDF.Nodes;
using VDS.RDF.Query;

namespace CARRE_DSS2.Models
{
    public class CarreRiskRepository
    {
        public CarreRiskRepository()
        {
            endpoint = new SparqlRemoteEndpoint(new Uri("http://carre.kmi.open.ac.uk/sparql"));
        }

        public SparqlResultSet getNodesWithAtributesByType(string type)
        {
            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("queriedType", new Uri(type));


            queryString.CommandText = @"SELECT ?node ?atr ?val
                                        WHERE { 
                                          ?node <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> @queriedType .
                                          ?node ?atr ?val .
                                        }";

            return endpoint.QueryWithResultSet(queryString.ToString());
        }

        public HashSet<Observable> getObservables()
        {
            var type = "http://carre.kmi.open.ac.uk/ontology/risk.owl#observable";

            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("queriedType", new Uri(type));


            queryString.CommandText = @"SELECT ?node ?name ?dataType ?type ?unit ?measurement 
                                        WHERE { 
                                            ?node <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> @queriedType .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_observable_name> ?name .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#observable_datatype> ?dataType .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#observable_unit> ?unit .
                                            OPTIONAL {?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#observable_type> ?type .}
                                            OPTIONAL {?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_observable_measurement>  ?measurement .}
                                        } GROUP BY ?node";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new HashSet<Observable>();

            foreach (SparqlResult result in ret)
            {
                var ob = new Observable()
                {
                    Id = 0,
                    Node = result["node"].ToString(),
                    Name = ((LiteralNode)result["name"]).Value,
                    DataType = ((LiteralNode)result["dataType"]).Value,
                    //Type = result["type"].ToString(),
                    Unit = ((LiteralNode)result["unit"]).Value
                };

                try
                {
                    ob.Measurement = result["measurement"].ToString();
                }
                catch (Exception e)
                {
                    ob.Measurement = null;
                }

                if (ob.Measurement == "")
                    ob.Measurement = null;

                //try
                //{
                //    ob.Type = result["type"].ToString();
                //}
                //catch
                //{
                //    ob.Type = "";
                //}


                output.Add(ob);
            }

            return output;
        }

        public HashSet<RiskElement> getRiskElements()
        {
            var type = "http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_element";

            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("queriedType", new Uri(type));


            queryString.CommandText = @"SELECT ?node ?name ?expression ?type
                                        WHERE { 
                                            ?node <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> @queriedType .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_element_name> ?name .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_element_condition> ?expression .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_element_type> ?type .
                                        }";


            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new HashSet<RiskElement>();

            foreach (SparqlResult result in ret)
            {

                var re = new RiskElement()
                {
                    Id = 0,
                    Node = result["node"].ToString(),
                    Name = ((LiteralNode)result["name"]).Value,
                    Expression = ((LiteralNode)result["expression"]).Value,
                    Type = result["type"].ToString()
                };

                output.Add(re);

            }

            return output;

        }

        public List<String> getObservablesOfRiskElement(String reNode)
        {
            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("reNode", new Uri(reNode));

            queryString.CommandText = @"SELECT ?obNode
                                        WHERE { 
                                            @reNode <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_element_observable> ?obNode .
                                        }";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new List<String>();

            foreach (SparqlResult result in ret)
                output.Add(result["obNode"].ToString());

            return output;
        }

        public HashSet<RiskEvidence> getRiskEvidences()
        {
            var type = "http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_evidence";

            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("queriedType", new Uri(type));


            queryString.CommandText = @"SELECT ?node ?expression ?type ?ratio
                                        WHERE { 
                                            ?node <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> @queriedType .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_observable_expression> ?expression .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_evidence_ratio_type> ?type .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_evidence_ratio_value> ?ratio .
                                        }";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new HashSet<RiskEvidence>();

            foreach (SparqlResult result in ret)
            {
                var re = new RiskEvidence()
                {
                    Id = 0,
                    Node = result["node"].ToString(),
                    Expression = ((LiteralNode)result["expression"]).Value,
                    RatioType = ((LiteralNode)result["type"]).Value
                };

                Thread.CurrentThread.CurrentCulture =
                    System.Globalization.CultureInfo.InvariantCulture;

                re.RatioValue = Convert.ToDouble(((LiteralNode)result["ratio"]).Value);

                output.Add(re);
            }

            return output;
        }

        public List<String> getObservablesOfRiskEvidence(String reNode)
        {
            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("reNode", new Uri(reNode));

            queryString.CommandText = @"SELECT ?obNode
                                        WHERE { 
                                            @reNode <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_evidence_observable> ?obNode .
                                        }";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new List<String>();

            foreach (SparqlResult result in ret)
                output.Add(result["obNode"].ToString());

            return output;
        }

        public HashSet<RiskFactor> getRiskFactors()
        {
            var type = "http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_factor";

            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("queriedType", new Uri(type));


            queryString.CommandText = @"SELECT ?node ?title ?type
                                        WHERE { 
                                            ?node <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> @queriedType .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_factor_title> ?title .
                                            ?node <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_factor_association_type> ?type .
                                        }";


            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new HashSet<RiskFactor>();

            foreach (SparqlResult result in ret)
            {

                var re = new RiskFactor()
                {
                    Id = 0,
                    Node = result["node"].ToString(),
                    Title = ((LiteralNode)result["title"]).Value,
                    AssociationType = result["type"].ToString(),
                };

                output.Add(re);

            }

            return output;
        }

        public List<String> getRiskEvidencesOfRiskFactor(String rfNode)
        {
            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("rfNode", new Uri(rfNode));

            queryString.CommandText = @"SELECT ?reNode
                                        WHERE { 
                                            @rfNode <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_evidence> ?reNode .
                                        }";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new List<String>();

            foreach (SparqlResult result in ret)
                output.Add(result["reNode"].ToString());

            return output;
        }

        public String getTargetRiskElementOfRiskFactor(String rfNode)
        {
            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("rfNode", new Uri(rfNode));

            queryString.CommandText = @"SELECT ?reNode
                                        WHERE { 
                                            @rfNode <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_factor_target> ?reNode .
                                        }";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());


            var result = ret[0];
            var output = result["reNode"].ToString();

            return output;
        }

        public List<String> getSourceRiskElementsOfRiskFactor(String rfNode)
        {
            SparqlParameterizedString queryString = new SparqlParameterizedString();
            queryString.Namespaces.AddNamespace("r", new Uri("http://carre.kmi.open.ac.uk/ontology/risk.owl#"));
            queryString.SetUri("rfNode", new Uri(rfNode));

            queryString.CommandText = @"SELECT ?reNode
                                        WHERE { 
                                            @rfNode <http://carre.kmi.open.ac.uk/ontology/risk.owl#has_risk_factor_source> ?reNode .
                                        }";

            var ret = endpoint.QueryWithResultSet(queryString.ToString());

            var output = new List<String>();

            foreach (SparqlResult result in ret)
                output.Add(result["reNode"].ToString());

            return output;
        }

        private SparqlRemoteEndpoint endpoint;
    }

}