const Writable = require('stream').Writable;

function isBlankNode (string) {
    return string.indexOf('_:') === 0;
}

module.exports = (scope, event, args) => {
    return new Writable({
        objectMode: true,
        write: (triple, enc, done) => {

            let subject = triple[0] || triple.subject;
            let predicate = triple[1] || triple.predicate;
            let object = triple[2] || triple.object;

            switch (predicate) {

                case 'http://schema.jillix.net/vocab/onEnd':
                    event.e = object;
                    break;

                case 'http://schema.jillix.net/vocab/onError':
                    event.r = object;
                    break;

                case 'http://schema.jillix.net/vocab/module':
                    event.module(subject, object);
                    break;

                case 'http://schema.jillix.net/vocab/roles':
                    event.instance(subject, 'role', object);
                    break;

                case 'http://schema.jillix.net/vocab/args':

                    try {
                        object = JSON.parse(object.slice(1, -1));
                    } catch (error) {
                        event.emit('error', error);
                        break;
                    }

                    if (isBlankNode(subject)) {
                        event.handler(subject, 'args', object);
                        break;
                    }

                    event.instance(subject, 'args', object);
                    break;

                case 'http://schema.jillix.net/vocab/sequence':

                    if (isBlankNode(subject)) {
                        event.handler(subject, 'next', object);
                        break;
                    }

                    event.handler(object, 'first', true);
                    break;

                case 'http://schema.jillix.net/vocab/instance':
                    event.handler(subject, 'instance', object);
                    break; 

                case 'http://schema.jillix.net/vocab/dataHandler':
                    event.handler(subject, 'data', object.split('#')[1]);
                    break;

                case 'http://schema.jillix.net/vocab/streamHandler':
                    event.handler(subject, 'stream', object.split('#')[1]);
                    break;

                case 'http://schema.jillix.net/vocab/emit':
                    event.handler(subject, 'emit', object);
                    break; 

                default:
                    console.log('[Parser] Unknown triple:', predicate);
            }

            done();
        }
    });
}; 

@@ -37,16 +37,92 @@
 ritable;
+%0Aconst Module = require('./Module');%0Aconst Instance = require('./Instance');
 %0A%0Afuncti
@@ -618,18 +618,24 @@
 ent.
-e =
+set('e',
  object
+)
 ;%0A  
@@ -753,18 +753,24 @@
 ent.
-r =
+set('r',
  object
+)
 ;%0A  
@@ -881,36 +881,272 @@
     
-event.module(subject, object
+Module(scope, args, object, (error, module) =%3E %7B%0A%0A                        if (error) %7B%0A                            return event.error(error);%0A                        %7D%0A%0A                        Instance(scope, args, subject, 'module', module);%0A                    %7D
 );%0A 
@@ -1245,39 +1245,33 @@
                 
-event.i
+I
 nstance(subject,
@@ -1267,30 +1267,240 @@
 ce(s
-ubject, 'role', object
+cope, args, subject, (error, instance) =%3E %7B%0A%0A                        if (error) %7B%0A                            return event.error(error);%0A                        %7D%0A%0A                        instance.role(object);%0A                    %7D
 );%0A 
@@ -1751,22 +1751,14 @@
 ent.
-emit('
 error
-', 
+(
 erro
@@ -2005,15 +2005,9 @@
     
-event.i
+I
 nsta
@@ -2011,32 +2011,218 @@
 stance(s
-ubject, '
+cope, args, subject, (error, instance) =%3E %7B%0A%0A                        if (error) %7B%0A                            return event.error(error);%0A                        %7D%0A%0A                        instance.
 args
-', 
+(
 object);
@@ -2214,32 +2214,56 @@
 e.args(object);%0A
+                    %7D);%0A
                 
@@ -2679,49 +2679,349 @@
     
-event.handler(subject, 'instance', object
+++event.load;%0A                    Instance(scope, args, object, (error, instance) =%3E %7B%0A%0A                        if (error) %7B%0A                            return event.error(error);%0A                        %7D%0A%0A                        event.handler(subject, 'instance', instance);%0A                        event.done(event);%0A                    %7D
 );%0A 
@@ -3450,16 +3450,50 @@
 /emit':%0A
+                    ++event.load;%0A
         
@@ -3536,32 +3536,71 @@
 emit', object);%0A
+                    event.done(event);%0A
                 

use Module and Instance loaders