/* global Meteor */

import uuid from 'node-uuid';

export default class Join {
  constructor(data, store, worker) {
    const self = this;
    const needStartWorker = store.joinArr.length === 0;

    const {
      name,
      interval,
      doJoin,
      context,
    } = data;

    // NOTE: _id is used to find and clear the instance when the publication is stopped
    self._id = uuid.v1();

    self.name = name;
    self.interval = interval;
    self.doJoin = Meteor.bindEnvironment(doJoin);
    self.context = context;
    self.lastPublish = new Date();
    self.isPublishing = false;

    store.joinArr.push(self);

    self.context.added('PublishJoin', self.name, {
      value: undefined,
    });

    if (needStartWorker) {
      worker.startPublishWorker(store);
    }

    // remove this instance from cache array when the publication is stopped
    self.context.onStop(() => {
      // get the index
      const index = store.joinArr.findIndex(obj => obj._id === self._id);

      // remove the instance
      if (index > -1) {
        store.joinArr.splice(index, 1);
      }

      if (store.joinArr.length === 0) {
        worker.stopPublishWorker(store);
      }
    });
  }

  _changed(value) {
    const self = this;

    self.context.changed('PublishJoin', self.name, {
      value,
    });

    self.lastPublish = new Date();
    self.isPublishing = false;
  }

  publish() {
    const self = this;

    try {
      self.isPublishing = true;
      const value = self.doJoin();

      if (value instanceof Promise) {
        value.then((data) => {
          self._changed(data);
        });
      } else {
        self._changed(value);
      }
    } catch (e) {
      console.error(e);
    }
  }

  needPublish() {
    const self = this;

    const now = new Date().getTime();

    return (now - self.lastPublish.getTime()) >= self.interval && self.isPublishing === false;
  }
}

@@ -230,16 +230,34 @@
 terval,%0A
+      maxWaiting,%0A
       do
@@ -549,32 +549,71 @@
 self.lastPublish
+ed = new Date();%0A    self.lastRunDoJoin
  = new Date();%0A 
@@ -641,16 +641,58 @@
 = false;
+%0A    self.maxWaiting = maxWaiting %7C%7C 5000;
 %0A%0A    st
@@ -1424,16 +1424,18 @@
 tPublish
+ed
  = new D
@@ -1557,16 +1557,55 @@
 = true;%0A
+      self.lastRunDoJoin = new Date();%0A
       co
@@ -1934,26 +1934,97 @@
 ();%0A
-%0A
     
-return (now -
+const lastRunDoJoinTime = self.lastRunDoJoin.getTime();%0A    const lastPublishedTime =
  sel
@@ -2036,16 +2036,18 @@
 tPublish
+ed
 .getTime
@@ -2052,56 +2052,339 @@
 me()
-) %3E= self.interval && self.isPublishing === fals
+;%0A%0A    const isPublishingButExceedMaxWaitingTime = self.isPublishing &&%0A      (now - lastRunDoJoinTime %3E= self.maxWaiting);%0A%0A    const isNotPublishingAndExceedIntervalTime = !self.isPublishing &&%0A      (now - lastPublishedTime %3E= self.interval)%0A%0A    return isPublishingButExceedMaxWaitingTime %7C%7C isNotPublishingAndExceedIntervalTim
 e;%0A 

Add max waiting time option. Force re-publishing if exceed max waiting time