/**
 * WebSampConnector Toolkit.
 * 
 * This file contains the Javascript object associated to the WebSampConnector
 * Java applet. It defines the WebSampConnector namespace and its properties.
 * @see http://vo.imcce.fr/webservices/samp/?manual 
 * @author J. Berthier <berthier@imcce.fr> (IMCCE/OBSPM/VOParis Data Centre)
 * @author A. Tregoubenko <http://arty.name>
 * @version 1.5, 2010-03-13
 * @copyright 2010, VO-Paris Data Centre <http://vo.obspm.fr/>
 *
 * @usage: You can override the default configuration values by passing new 
 *   values through the configure property of the WebSampConnector object, e.g.:
 *       <script type="text/javascript">
 *           WebSampConnector.configure({
 *               jAppletId: 'WebSampConnectorApplet',
 *               jAppletCodeBase: '/mypath/',
 *               jAppletVersion: '1.5'
 *           });
 *           WebSampConnector.configureStatusIcon({
 *               iconId: 'hubStatusIcon',
 *               iconPrefix: 'icons/hub2-',
 *               iconExt: '.png'
 *           });
 *           WebSampConnector.setHandlerId('HubMsg');
 *       </script>
 * 
 * Note: you are encouraged to override or provide your own callbackFunction and
 * handler methods to fulfill the requirements of your Web application 
 * (cf. websampconnector.Handlers.js file)
 */
var WebSampConnector = {

   // Id of the Japplet tag (to be overrided by client)
   jAppletId: 'WebSampConnectorApplet',
   // Absolute path to the JApplet directory (to be overrided by client)
   jAppletCodeBase: './',
   // Version of the WebSampConnector JApplet
   jAppletVersion: '1.5',

   // Becomes true if IE is used
   IE: window.navigator.appName.indexOf("Microsoft Internet Explorer") != -1,

   // Minimum version of JDK to use
   javaVersion: '1.6',
   
   /**
    * Client configuration method to override default configuration values
    */
   configure: function(options) {
      this.jAppletId        = options.jAppletId        || this.jAppletId;
      this.jAppletCodeBase  = options.jAppletCodeBase  || this.jAppletCodeBase;
      this.jAppletVersion   = options.jAppletVersion   || this.jAppletVersion; 
   },

   /**
    * Logs a message
    */
   log: function(message) {
      if (window.console) {
         console.log(message);
      } else if (window.opera && opera.postError) {
         opera.postError(message);
      } else {
         alert(message);
      }
   },

   /**
    * Returns the JApplet HTML element
    */
   getApplet: function() {
      return document.getElementById(WebSampConnector.jAppletId);
   },

   /**
    * Generic method to broadcast messages to the hub
    */
   proxyMethod: function(methodName) {
      return function() {
         var applet = this.getApplet();
         if (!applet) {
            throw new Error('WebSampConnector.proxyMethod: cannot find applet, call WebSampConnector.connect() before calling other methods.');
         }
         // Test if the connection is active
         if (methodName != 'isConnected') {
            if (!applet.isConnected()) {
               throw new Error('WebSampConnector.proxyMethod: applet is not connected to hub.');
            }
         }
         // Call Java method
         if (!this.IE) {
            return applet[methodName].apply(applet, arguments);
         }
         // Workaround for IE to call Java method
         var a = arguments[0];
         var b = arguments[1];
         var c = arguments[2];
         var d = arguments[3];
         var e = arguments[4];
         switch (methodName) {
            case 'disconnect':           return applet.disconnect(); 
            case 'isConnected':          return applet.isConnected();
            case 'sendMsg':              return applet.sendMsg(a,b,c,d,e);
            case 'pointAtSky':           return applet.pointAtSky(a,b);
            case 'tableHighlightRow':    return applet.tableHighlightRow(a,b,c);
            case 'tableSelectRowList':   return applet.tableSelectRowList(a,b,c);
            case 'sendAladinScript':     return applet.sendAladinScript(a);
            case 'getRegisteredClients': return applet.getRegisteredClients();
            case 'getSubscribedClients': return applet.getSubscribedClients(a);
            default: return false;
         }
      }
   },

   /**
    * This method is dedicated to the getRegisteredClients and getSubscribedClients
    * methods, in order to format their outputs properly (i.e. associative array)
    */
   migrateClients: function(method) {
      return function() {
         var clients = method.apply(WebSampConnector, arguments);
         var data = [];
         for (var index = 0; index < clients.length; ++index) {
            var client = clients[index];
            data.push({
               'id': client.id,
               'name': client.name,
               'descriptionText': client.descriptionText,
               'descriptionHtml': client.descriptionHtml,
               'iconUrl': client.iconUrl,
               'documentationUrl': client.documentationUrl
            });
         }
         return data;
      }
   },

   /**
    * This method builds the Japplet, and connects and registers the Web browser 
    * to a running Samp hub
    */
   connect: function() {
      // Destroy the old applet if it exists
      var el = this.getApplet();
      if (el) {
         el.parentNode.removeChild(el);
      }
      // Define the applet tag
      if (this.IE) {
         var parameters = " codebase='" + this.jAppletCodeBase + "'"
            + " archive='sWebSampConnector-" + this.jAppletVersion + ".jar'"
            + " code='org.voparis.WebSampConnector'" 
            + " mayscript='true'>";
      } else {
         var parameters = ">"
            + " <param name='code' value='org.voparis.WebSampConnector' />"
            + " <param name='codebase' value='" + this.jAppletCodeBase + "' />"
            + " <param name='JAVA_CODEBASE' value='" + this.jAppletCodeBase + "' />"
            + " <param name='archive' value='sWebSampConnector-" + this.jAppletVersion + ".jar' />"
            + " <param name='mayscript' value='true' />";
      }
      var applet = "<object type='application/x-java-applet;version=" + this.javaVersion + "'"
         + " id='" + this.jAppletId + "' name='" + this.jAppletId + "'"
         + " archive='sWebSampConnector-" + this.jAppletVersion + ".jar'"
         + " style='visibility: hidden; position: absolute; top:0; left:0;' width='0' height='0'"
         + parameters
         + " WebSampConnector: you need a Java-enabled browser to launch it.<br />"
         + " <a href='http://java.sun.com/products/plugin/downloads/'>Get the latest Java Plug-in here.</a>"
         + " </object>";
      // Append the applet to the document
      var body = document.body;
      var div = document.createElement("div");
      div.innerHTML = applet;
      body.appendChild(div);
   },

   /**
    * This function is used as default NOP handler for all WebSampConnector events
    */
   empty: function() {}

};

/**
 * This method unregisters the client and terminates the connection.
 * @return true if the client is disconnected, false if not 
 */
WebSampConnector.disconnect = WebSampConnector.proxyMethod('disconnect');

/**
 * This method allows the client to know if he is connected to a running Samp hub.
 * @return true if the client is connected, false if not 
 */
WebSampConnector.isConnected = WebSampConnector.proxyMethod('isConnected');

/**
 * This method retrieves the list of client public IDs for those clients currently registered.
 * The result is returned as a WebSampConnectorClient object containing the list of registered clients. 
 * The output is converted into an associative array by the migrateClients method, and contains
 * all the metadata of the registered applications.
 */
WebSampConnector.getRegisteredClients = WebSampConnector.proxyMethod('getRegisteredClients');
WebSampConnector.getRegisteredClients = WebSampConnector.migrateClients(WebSampConnector.getRegisteredClients);

/**
 * This method retrieves the list of clients which subscribed a given MType.
 * The result is returned as a WebSampConnectorClient object containing the list of registered clients. 
 * The output is converted into an associative array by the migrateClients method, and contains
 * all the metadata of the registered applications.
 * @param mtype the given MType (e.g. table.load.votable)
 */
WebSampConnector.getSubscribedClients = WebSampConnector.proxyMethod('getSubscribedClients');
WebSampConnector.getSubscribedClients = WebSampConnector.migrateClients(WebSampConnector.getSubscribedClients);

/**
 * This method broadcasts a message from the Web page to VO applications via the Samp hub 
 * @param type the MType of the resource 
 * @param keyName the key of the identifier (param id) which may be used to refer to the loaded resource in subsequent messages
 * @param id the Id of the resource 
 * @param name the name of the resource 
 * @param url the URL where is located the resource
 * @return true if no error occurs, false if not
 * @throws exception if an error occurs
 */
WebSampConnector.sendMsg = WebSampConnector.proxyMethod('sendMsg');

/**
 * This method allows the client to point a given celestial coordinate 
 * in a VO application (e.g. Aladin) by selecting it in the Web page.
 * @param ra the right ascension to point (in degrees)
 * @param dec the declination to point (in degrees)
 * @return true if no error occurs, false if not (if an exception is rises then a message is printed)
 */
WebSampConnector.pointAtSky = WebSampConnector.proxyMethod('pointAtSky');
 
/**
 * This method allows the client to highlight a given row of a table
 * in a VO application (e.g. Aladin) by selecting it in the Web page.
 * @param tableId the Id of the resource (table)
 * @param url the URL where is located the resource
 * @param row the number of the row to highlight (from 0 to n-1)
 * @return true if no error occurs, if not false (if an exception is rises then a message is printed)
 * @throws PrivilegedActionException 
 */
WebSampConnector.tableHighlightRow = WebSampConnector.proxyMethod('tableHighlightRow');
 
/**
 * This method allows the client to highlight a set of rows of the table
 * in a VO application (e.g. Aladin) by selecting them in the Web page.
 * @param tableId the Id of the resource (table)
 * @param url the URL where is located the resource
 * @param rowList an array of integers providing the list of the rows to highlight (from 0 to n-1)
 * @return true if no error occurs, if not false (if an exception is rises then a message is printed)
 */
WebSampConnector.tableSelectRowList = WebSampConnector.proxyMethod('tableSelectRowList');
 
/**
 * This method allows the client to send a script to be executed by Aladin
 * @param ascript a string containing the Aladin script to be executed
 * @return true if no error occurs, if not false (if an exception is rises then a message is printed)
 */
WebSampConnector.sendAladinScript = WebSampConnector.proxyMethod('sendAladinScript');

/**
 * This function is called immediately after the connection has been established.
 * Feel free to override it with your own functions in WebSampConnector.Handlers.js.
 */
WebSampConnector.onlineHandler = WebSampConnector.empty;

/**
 * -----------------------------------------------------------------------
 * Following handlers are called by Java applet when it receives specific
 * events from hub. Feel free to override them with your own functions in
 * WebSampConnector.Handlers.js.
 * -----------------------------------------------------------------------
 */

/**
 * This method allows a VO application to point a given celestial coordinate in the Web page
 * The data are returned as an array containing the celestial coordinates: RA, DEC
 */
WebSampConnector.pointAtSkyHandler = WebSampConnector.empty;

/**
 * This method allows a VO application to highlight a given row in the Web page
 * The data are returned as an array containing the tableId, url and row number
 * of the highlighted row.
 */
WebSampConnector.highlightRowHandler = WebSampConnector.empty;

/**
 * This method allows a VO application to highlight a selection of rows in the Web page
 * The data are returned as an array containing the tableId, url and row numbers
 * of the highlighted rows.
 */
WebSampConnector.selectRowListHandler = WebSampConnector.empty;

