"use strict"

const cayley = require("cayley");
const JSONStream = require("JSONStream");
const Combine = require("stream-combiner");
const Triples = require("./triples");
const entrypoint = require("./entrypoint");
const sequence = require("./sequence");
const visualization = require("./visualization");
const adapters = {};

// RDF constants
const RDF_SYNTAX = '<http://www.w3.org/1999/02/22-rdf-syntax-ns#';
const FLOW_VOCAB = '<http://schema.jillix.net/vocab/';
const SCHEMA = '<http://schema.org/';

module.exports = (config) => {

    // singleton
    if (adapters[config]) {
        return adapters[config];
    }

    const client = cayley(config);
    const incomming = (node, edges) => {
        return client.g.V.apply(client.g, nodes).Tag("o").In(null, "p").All();
    };
    const outgoing = (node, edges) => {
        return client.g.V.apply(client.g, nodes).Tag("s").Out(edges, "p").All();
    };
    const getObject = (node) => {
        return g.V(id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'json>', 'predicate')
        .Out(RDF_SYNTAX + 'string>', 'predicate')
        .All()
    };
    const write = (triples) => {
        if (triples && triples.length) {
            return client.write(triples);
        }
    };
    const remove = (triples) => {
        if (triples && triples.length) {
            return client.delete(triples);
        }
    };

    const combineAndParse = (streams) => {

        // parse cayley result
        streams.forEach((stream, i) => {
            streams[i] = streams[i].pipe(JSONStream.parse('result.*'));
        });

        // merge all data into one stream and parse object triples to array triples 
        return Triples.combine(streams).pipe(Triples.toArray());
    };

    // export store adapter
    return adapters[config] = Object.freeze({
        sequence: (sequence_id, role) => {
            return combineAndParse(sequence(client, sequence_id, role));
        },
        entrypoint: (entrypoint_name) => {
            return combineAndParse(entrypoint(client, entrypoint_name));
        },
        outNodeNames: (id) => {
            return combineAndParse(visualization.outNodeNames(client, id));
        },
        outNodeNamesFn: (id) => {
            return combineAndParse(visualization.outNodeNamesFn(client, id));
        },
        // TODO move to service api
        networks: (id) => {
            return combineAndParse(visualization.networks(client, id));
        },
        getObject: getObject,
        incomming: incomming,
        outgoing: outgoing,
        remove: remove,
        write: write
    });
};

@@ -929,20 +929,18 @@
 ject = (
-node
+id
 ) =%3E %7B%0A 
@@ -953,16 +953,23 @@
  return 
+client.
 g.V(id)%0A
@@ -1075,29 +1075,16 @@
 string%3E'
-, 'predicate'
 )%0A      
@@ -1091,16 +1091,17 @@
   .All()
+;
 %0A    %7D;%0A
@@ -1412,25 +1412,68 @@
 s) =%3E %7B%0A
-%0A
+        if (streams instanceof Array) %7B%0A%0A   
         
 // parse
@@ -1464,16 +1464,17 @@
         
+ 
 // parse
@@ -1488,16 +1488,20 @@
  result%0A
+    
         
@@ -1541,24 +1541,28 @@
             
+   
+ 
 streams%5Bi%5D =
@@ -1621,13 +1621,21 @@
     
+    
 %7D);%0A%0A
+    
     
@@ -1676,11 +1676,197 @@
 eam 
-and
+%0A            streams = Triples.combine(streams);%0A        %7D else %7B%0A%0A            // parse cayley result%0A            streams = streams.pipe(JSONStream.parse('result.*'));%0A        %7D%0A%0A        //
  par
@@ -1899,17 +1899,16 @@
  triples
- 
 %0A       
@@ -1919,32 +1919,15 @@
 urn 
-Triples.combine(
 streams
-)
 .pip
@@ -2299,20 +2299,16 @@
  outNode
-Name
 s: (id) 
@@ -2372,136 +2372,9 @@
 Node
-Names(client, id));%0A        %7D,%0A        outNodeNamesFn: (id) =%3E %7B%0A            return combineAndParse(visualization.outNodeNamesFn
+s
 (cli
@@ -2561,25 +2561,86 @@
 Object: 
-getObject
+(id) =%3E %7B%0A            return combineAndParse(getObject(id));%0A        %7D
 ,%0A      

combine streams of "outNodes" and "getObject"