text: /*
  The MIT License (MIT)
  Copyright (c) 2014-2019 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
  
  Virtual World Framework Apache 2.0 license  (https://github.com/NikolaySuslov/livecodingspace/blob/master/licenses/LICENSE_VWF.md)
  */
  
  import { Helpers } from '/core/helpers.js';
  
  class ReflectorClient {
      constructor() {
          console.log("reflector client constructor");
          this.helpers = new Helpers;
          this.socket = undefined;
      }
  
      connect(component_uri_or_json_or_object, path){
  
          function isSocketIO07() {
              //return ( parseFloat( io.version ) >= 0.7 );
              return true
          } 
  
          try {
  
              let objToRef = this.helpers.reduceSaveObject(path);
  
              var options = {
  
                  // The socket is relative to the application path.
  
                  // resource: window.location.pathname.slice( 1,
                  //      window.location.pathname.lastIndexOf("/") ),
  
                  query: {
                      pathname: window.location.pathname.slice( 1,
                          window.location.pathname.lastIndexOf("/") ),
                      appRoot: "./public",
                      path: JSON.stringify(objToRef)//JSON.stringify(path)
                    },
                  // query: 'pathname=' + window.location.pathname.slice( 1,
                  //     window.location.pathname.lastIndexOf("/") ),
  
                  // Use a secure connection when the application comes from https.
                  
                  secure: window.location.protocol === "https:",
  
                  // Don't attempt to reestablish lost connections. The client reloads after a
                  // disconnection to recreate the application from scratch.
  
                  //reconnect: false,
                  reconnection: false,
                  upgrade: false,
                  transports: ['websocket']
  
              };
  
              if ( isSocketIO07() ) {
  
                  //window.location.host
          var host = window._app.reflectorHost; //localStorage.getItem('lcs_reflector'); 
          //if(!host) host = 'http://localhost:3002'; //window.location.origin;       
          this.socket = io.connect( host, options );
                  
  
              } 
  
          } catch ( e ) {
  
              // If a connection to the reflector is not available, then run in single-user mode.
              // Messages intended for the reflector will loop directly back to us in this case.
              // Start a timer to monitor the incoming queue and dispatch the messages as though
              // they were received from the server.
  
          //    this.dispatch();
  
          //     setInterval( function() {
  
          //         var fields = {
          //             time: vwf.now + 0.010, // TODO: there will be a slight skew here since the callback intervals won't be exactly 10 ms; increment using the actual delta time; also, support play/pause/stop and different playback rates as with connected mode.
          //             origin: "reflector",
          //         };
  
          //         _app.virtualTime.insert( fields, true ); // may invoke dispatch(), so call last before returning to the host
  
          //     }, 10 );
  
          }
  
          if ( this.socket ) {
  
              this.socket.on('connect_error', function(err) {
                  console.log(err);
                  var errDiv = document.createElement("div");
                  errDiv.innerHTML = "<div class='vwf-err' style='z-index: 10; position: absolute; top: 80px; right: 50px'>Connection error!" + err + "</div>";
                  document.querySelector('body').appendChild(errDiv);
                  
              });
  
              this.socket.on( "connect", function() {
  
                  vwf.logger.infox( "-socket", "connected" );
  
                  if ( isSocketIO07() ) {
                      vwf.moniker_ = this.id;                        
                  } else {  //Ruby Server
                      vwf.moniker_ = this.transport.sessionid;
                  }
  
              } );
  
              // Configure a handler to receive messages from the server.
              
              // Note that this example code doesn't implement a robust parser capable of handling
              // arbitrary text and that the messages should be placed in a dedicated priority
              // queue for best performance rather than resorting the queue as each message
              // arrives. Additionally, overlapping messages may cause actions to be performed out
              // of order in some cases if messages are not processed on a single thread.
  
              this.socket.on( "message", function( message ) {
  
                  // vwf.logger.debugx( "-socket", "message", message );
  
                  try {
  
                      if ( isSocketIO07() ) {
                          var fields = message;
                      } else { // Ruby Server - Unpack the arguements
                          var fields = JSON.parse( message );
                      }
  
                      fields.time = Number( fields.time );
                      // TODO: other message validation (check node id, others?)
  
                      fields.origin = "reflector";
  
                      // Update the queue.  Messages in the queue are ordered by time, then by order of arrival.
                      // Time is only advanced if the message has no action, meaning it is a tick.
  
                      if(_app.config.streamMsg) {
                          vwf.virtualTime.streamAdapter.induce(fields);
                      } else {
                          vwf.virtualTime.insert( fields, !fields.action ); 
                      }
                      
                      //
                      
                      // may invoke dispatch(), so call last before returning to the host
  
                      // Each message from the server allows us to move time forward. Parse the
                      // timestamp from the message and call dispatch() to execute all queued
                      // actions through that time, including the message just received.
                  
                      // The simulation may perform immediate actions at the current time or it
                      // may post actions to the queue to be performed in the future. But we only
                      // move time forward for items arriving in the queue from the reflector.
  
                  } catch ( e ) {
  
                      vwf.logger.warn( fields.action, fields.node, fields.member, fields.parameters,
                          "exception performing action:", vwf.utility.exceptionMessage( e ) );
  
                  }
  
              } );
  
              this.socket.on( "disconnect", function() {
  
                  vwf.logger.infox( "-socket", "disconnected" );
  
                  // Reload to rejoin the application.
  
                  window.location = window.location.href;
  
              } );
  
              this.socket.on( "error", function() { 
  
                  //Overcome by compatibility.js websockets check
                  document.querySelector('body').innerHTML = "<div class='vwf-err'>WebSockets connections are currently being blocked. Please check your proxy server settings.</div>";
                  // jQuery('body').html("<div class='vwf-err'>WebSockets connections are currently being blocked. Please check your proxy server settings.</div>"); 
  
              } );
  
              if ( !isSocketIO07() ) {
                  // Start communication with the reflector. 
  
                  this.socket.connect();  // TODO: errors can occur here too, particularly if a local client contains the socket.io files but there is no server; do the loopback here instead of earlier in response to new io.Socket.
              }
  
          } else if ( component_uri_or_json_or_object ) {
  
              // Load the application. The application is rooted in a single node constructed here
              // as an instance of the component passed to initialize(). That component, its
              // prototype(s), and its children, and their prototypes and children, flesh out the
              // entire application.
  
              // TODO: add note that this is only for a self-determined application; with socket, wait for reflection server to tell us.
              // TODO: maybe depends on component_uri_or_json_or_object too; when to override and not connect to reflection server?
  
              this.createNode( component_uri_or_json_or_object, "application" );
  
          } else {  // TODO: also do this if component_uri_or_json_or_object was invalid and createNode() failed
  
              // TODO: show a selection dialog
  
          }
  
      }
  
  
  }
  
  export { ReflectorClient }