import macro from 'vtk.js/Sources/macro';
import DefaultProtocol from 'vtk.js/Sources/IO/Core/ImageStream/DefaultProtocol';
import ViewStream from 'vtk.js/Sources/IO/Core/ImageStream/ViewStream';

function vtkImageStream(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkImageStream');

  // --------------------------------------------------------------------------
  // Internal private method
  // --------------------------------------------------------------------------

  function onImage(data) {
    const message = data[0];
    if (!message || !message.image) {
      return;
    }
    for (let i = 0; i < model.viewStreams.length; i++) {
      model.viewStreams[i].processMessage(message);
    }
  }

  // --------------------------------------------------------------------------
  // PublicAPI
  // --------------------------------------------------------------------------

  publicAPI.setServerAnimationFPS = (maxFPS = 30) => {
    let changeDetected = false;
    if (model.serverAnimationFPS !== maxFPS) {
      model.serverAnimationFPS = maxFPS;
      changeDetected = true;
    }

    if (!model.protocol) {
      return Promise.resolve(true);
    }

    if (changeDetected) {
      publicAPI.modified();
    }

    return model.protocol.setServerAnimationFPS(maxFPS);
  };

  // --------------------------------------------------------------------------

  publicAPI.connect = (session, protocol = DefaultProtocol) => {
    if (model.connected || !session || !protocol) {
      return;
    }
    model.protocol = protocol(session);
    model.protocol
      .subscribeToImageStream(onImage)
      .then((subscription) => {
        model.renderTopicSubscription = subscription;
        model.connected = true;
      })
      .catch((e) => {
        model.connected = false;
        console.error(e);
      });
  };

  // --------------------------------------------------------------------------

  publicAPI.disconnect = () => {
    if (model.protocol && model.connected) {
      model.protocol.unsubscribeToImageStream(
        model.imageStreamTopicSubscription
      );
      model.imageStreamTopicSubscription = null;
    }
  };

  // --------------------------------------------------------------------------

  function unregisterViewStream(view) {
    model.viewStreams = model.viewStreams.filter((v) => v !== view);
  }

  // --------------------------------------------------------------------------

  publicAPI.createViewStream = (viewId = '-1', size = [400, 400]) => {
    const { setServerAnimationFPS, getServerAnimationFPS } = publicAPI;
    const viewStream = ViewStream.newInstance({
      protocol: model.protocol,
      unregisterViewStream,
      sharedAPI: {
        setServerAnimationFPS,
        getServerAnimationFPS,
      },
    });
    viewStream.setViewId(viewId);
    viewStream.setSize(size[0], size[1]);
    model.viewStreams.push(viewStream);

    return viewStream;
  };

  // --------------------------------------------------------------------------

  publicAPI.delete = macro.chain(() => {
    while (model.viewStreams.length) {
      model.viewStreams.pop().delete();
    }
    publicAPI.disconnect();
  }, publicAPI.delete);
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
  viewStreams: [],
  serverAnimationFPS: -1,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, DEFAULT_VALUES, initialValues);

  // Object methods
  macro.obj(publicAPI, model);
  macro.get(publicAPI, model, ['serverAnimationFPS']);

  // Object specific methods
  vtkImageStream(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend, 'vtkImageStream');

// ----------------------------------------------------------------------------

export default { newInstance, extend };

@@ -2252,25 +2252,192 @@
 ----%0A%0A  
-function 
+publicAPI.registerViewStream = (view) =%3E %7B%0A    model.viewStreams.push(view);%0A  %7D;%0A%0A  // --------------------------------------------------------------------------%0A%0A  publicAPI.
 unregist
@@ -2448,22 +2448,28 @@
 ewStream
+ = 
 (view)
+ =%3E
  %7B%0A    m
@@ -2531,24 +2531,25 @@
 = view);%0A  %7D
+;
 %0A%0A  // -----
@@ -2701,16 +2701,22 @@
  const %7B
+%0A     
  setServ
@@ -2730,16 +2730,22 @@
 tionFPS,
+%0A     
  getServ
@@ -2758,16 +2758,49 @@
 ationFPS
+,%0A      unregisterViewStream,%0A   
  %7D = pub
@@ -3089,31 +3089,43 @@
 ze%5B1%5D);%0A    
-model.v
+publicAPI.registerV
 iewStreams.p
@@ -3117,30 +3117,24 @@
 erViewStream
-s.push
 (viewStream)
@@ -3631,16 +3631,37 @@
 UES = %7B%0A
+  // protocol: null,%0A
   viewSt
@@ -3952,16 +3952,16 @@
 model);%0A
-
   macro.
@@ -4003,16 +4003,28 @@
 tionFPS'
+, 'protocol'
 %5D);%0A%0A  /

Add ViewStream inheritance support