<?xml version="1.0" encoding="UTF-8" ?>
<!-- get_objects.xml -->
<!-- Author: Ian Smith (imsmith@uw.edu) -->
<Module>
<ModulePrefs title="Get Sky Objects" 
    height="10"
    scrolling="true">
     <Require feature="dynamic-height"/>
     <Require feature="opensocial-0.8"/> 
     <Require feature="minimessage"/>
</ModulePrefs> 

<Content type="html"><![CDATA[

<script src="js/DataInterface.js" type="text/javascript"></script>
<script src="js/widgetlib1.js" type="text/javascript"></script>
<script src="js/astroObjectLib.js" type="text/javascript"></script>

<div id="divSelectService">
<table> 
  <TBODY>
  <tr> 
    <td>
        <SELECT id="selService">
            <OPTION value="none">Select Service</OPTION>
            <OPTION value="SDSS">SDSS</OPTION>
        </SELECT>
    </td> 
  </tr> 
  <tr> 
    <td>Max: <INPUT id="txtMaxObjects" type="text" size="3" value="50"/></td>
  </tr>
  <tr>  
    <td><INPUT id="butGetObjects" onclick="gsobj.getObjects();" type="button" value="Get Objects">
    <img id="imgSpinner" src="images/spinnerGrey.gif" style="display:none" />
    </td> 
  </tr> 
  </TBODY>
</table> 
</div>

<div id="divObjectData">
</div>

<script type="text/javascript">

// GetSkyObjects object is global
var gsobj = null,
    debug = true;


// CONSTANTS
var GADGET_NAME = "GetSkyObjects" + "_" + Math.floor(Math.random()*100000+1).toString();

// Writes to the console if debug (global) is true  
function debugLog(msg){
    if ((debug === true) && (window.console && console.log)) {
        console.log(GADGET_NAME + ": " + msg);
    }
    return;
}


// create GetSkyObj object
function init(){
    gsobj = new GetSkyObj();
    gadgets.window.adjustHeight();
}


function GetSkyObj(){
    var my = new Object();
    // CONSTANTS
    var DEFAULT_NAMESPACE = "NS1",
        MM_TIMER_DURATION = 4;

    // PRIVATE
    var _namespaceList = [ DEFAULT_NAMESPACE ];      // list of our current Namespaces. Just init with the default
    
    // Private Helper Variables
    var di = new UW.astro.DataInterface(GADGET_NAME, DEFAULT_NAMESPACE); // make dataInterface object, init with default
    var miniMsg = new gadgets.MiniMessage();// make MiniMessage object

    // INIT

    var msg = miniMsg.createStaticMessage("Attempting to register gadget...");
    doRegistration(_namespaceList);
    
    
    // REGISTRATION stuff
    // do complete registration for all namespaces in the array
    function doRegistration(namespaceArray){
        // TODO: check that namespaceArray is actually and array
        for (var i=0, len=namespaceArray.length; i<len; i++){
            registerMe(namespaceArray[i]);
        }
    }
    // register this gadget in a particular namespace
    function registerMe(namespaceName){
        //F irst, Register the gadget with success and failure callbacks
        di.registerGadget(namespaceName, function(){continueRegistration(namespaceName);}, 
                                                function(){registrationFailure(namespaceName);});
    }    
    
    // Callback after a successful registration of this gadget in a namespace
    // Displays messages and registers variables
    function continueRegistration(namespaceName){
        debugLog('Registration was total Success!');
        if (msg) {
            miniMsg.dismissMessage(msg);
            // free up msg
            msg = null;
            miniMsg.createTimerMessage("Registration Succesful.", MM_TIMER_DURATION);
        }
        registerVariables(namespaceName);
        // di.registerVariable();
        // di.addTrigger();
    }
    
    // Callback after a failure of registration
    // displays message showing failure
    function registrationFailure(namespaceName){
        debugLog('Registration was total failure!');
        miniMsg.dismissMessage(msg);
        miniMsg.createDismissibleMessage("Unable to register gadget.\nWe cannot communicate with other gadgets.");
    }
    
    // Registers variables, and if successful, calls registerTriggers
    function registerVariables(namespaceName){
        debugLog('Attempting to register variables...');
        var varList = [ "Viewport_Point_List", "Viewport_Current_Bounds" ] // list of variables to register

        for (var i=0, len=varList.length; i<len; i++) {
            // TODO: should we do this for every namespace?
            if (di.registerVariable(namespaceName, varList[i], null)) {
                debugLog('Successfully registered variable "' + varList[i] + '"');
                registerTriggers(namespaceName);
            }
            else {
                debugLog('FAILED to register variable "' + varList[i] + '"');
            }
        }
    }
    
    // registers Triggers
    function registerTriggers(namespaceName){
        // none to register
    }
   

    // METHODS
    my.getObjects = function(){
        
        // First check to make sure we have everything we need to start:
        // service, bounding box, etc.

        // get the selected service
        var selObj = document.getElementById('selService');
        var service = selObj.options[selObj.selectedIndex].value;
        var url = "";
        if (service === "SDSS"){
            // TODO: We will need to create a RemoteDataInterface("SDSS") object
            // for now, we set url
            url = 'http://cas.sdss.org/public/en/tools/search/x_sql.asp';
        }
        else {
            alert('Select Service');
            return;
        }

        var txtMax = document.getElementById('txtMaxObjects');
        var maxObjs = parseInt(txtMax.value);
        // reset the text box to the parsed number
        txtMax.value = maxObjs;

        if (isNaN(maxObjs)){
            alert('Set max objects');
            return;
        }
            
        // get the bounding box
        // bounds is array of CelestialCoordinates: [topLeft, bottomRight]
        // TODO: other ways to choose the bounds we want on the gadget
        var bounds = di.readVariable(DEFAULT_NAMESPACE, "Viewport_Current_Bounds");
        if (bounds === null){
            alert('Set bounds');
            return;
        }
    /*  var data = { cmd: "select  top 50 g,r,i,g-r,r-i,ra,dec from star where ra between " +
            bounds[1].getRa() + " and " + bounds[0].getRa() +
            " and dec between " + bounds[1].getDec() + " and " + bounds[0].getDec() +
            " and r < 18 order by r",
                    format: "csv" };
    */
        // we have valid values.. begin the query
        // set the spinner...
        showSpinner(true); 

        // multiply ra by 15 to convert to degrees
        var sdssQueryData = {cmd: "SELECT TOP " + maxObjs + " objid,modelMag_g,modelMag_r,modelMag_i,ra,dec FROM PhotoPrimary WHERE ra BETWEEN " +
               bounds[0].getRa() * 15 + " AND " + bounds[1].getRa() * 15 +
               " AND dec BETWEEN " + bounds[1].getDec() + " AND " + bounds[0].getDec() +
               " AND modelMag_g > -9999" +
               " ORDER BY modelMag_g ASC",
            format: "xml" };
        //alert(sdssQueryData.cmd);
        makeGETRequest(url, sdssQueryData, sdssResponseCB);
    }
    
    function makeGETRequest(url, data, callback) {
        var params = {};
        getdata = gadgets.io.encodeValues(data);
        params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
        url = url + '?' + getdata;
//alert(url);
        gadgets.io.makeRequest(url, callback, params); 
    }
    function sdssResponseCB(obj) {
//alert(obj.text); 
        // parse the XML
        if (obj.errors.length > 0){
            // errors
            debugLog(obj.errors);
            showObjectData('Service: ' + obj.errors);
            return;
        }
        else if (obj.text === ""){
            // returned empty string
            showObjData('Service returned empty string');
            return;
        }
        xmlDoc = xmlStringToDoc(obj.text);
        // walk XML to create points and write to objectData
        // TODO: make objectData with tree widget
        var objDataText = [];
        var pointsList = [];

        var rows = xmlDoc.getElementsByTagName('Row');
        if (rows.length === 0){
            // no rows
            showObjectData('No Objects');
        }
        else if ((rows.length === 1) && (rows[0].textContent.indexOf('No rows returned') !== -1)){
            // the special case answer is that no rows were returned
            showObjectData('No Objects');
            return;
        }
        
        // We probably have valid data at this point, so parse it and display it
            
        // Write total # rows to the gadget display
        objDataText.push("<b>Total Objects: " + rows.length + "</b></br>");
        for (var i=0,len=rows.length; i<len; i++){
            var row = rows[i];
            var cc = new UW.astro.CelestialCoordinate(0,0);
            // loop through attributes
            for (var k=0, kLen=row.attributes.length; k<kLen; k++){
                // k is the attribute index
                var attName = row.attributes[k].nodeName;
                var attValue = row.attributes[k].nodeValue;

                // TODO: make an SDSS Data table inside the description 
                // set all the cc properties
                switch(attName){
                    case "ra":
                        // divide ra by 15 to convert to hours
                        cc.setRa(attValue /15);
                    case "dec":
                        cc.setDec(attValue);
                    default:
                        cc.appendDescription('<b>' + attName + "</b>: " + attValue + "</br>");
                }
                
//                else if (attName === "objid"){
//                    cc.setName(attValue);
//                }
                
                // add text for gadget display
                objDataText.push(attName + ": " + attValue + "</br>");
            }
            // add point to the list
            pointsList.push(cc);
            // add newline between each object
            objDataText.push("</br>");
        }
        
        // write the points to the public point list
        var pubList = di.readVariable(DEFAULT_NAMESPACE, "Viewport_Point_List");
        // TODO: test for the UniqIDList type
        if (pubList === null){
            pubList = new UW.astro.UniqIdList();
        }
        for (var i=0, len=pointsList.length; i<len; i++){
            pubList.append(pointsList[i]);
        }

        di.writeVariable(DEFAULT_NAMESPACE, "Viewport_Point_List", pubList);
        
        // write the text to the div
	// TMI - Removed
        // showObjectData(objDataText.join('')); 
        showSpinner(false);
    }

    // HELPER
        // Write object data text to the div
    function showObjectData(text){
        document.getElementById('divObjectData').innerHTML = text;
        
        // resize gadget
        gadgets.window.adjustHeight();

        // hide spinner
        showSpinner(false);
    }

    function showSpinner(show){
        if (show){
            document.getElementById('imgSpinner').style.display = 'inline';
        }
        else{
            document.getElementById('imgSpinner').style.display = 'none';
        }
    }
    function xmlStringToDoc(text){
        if (window.DOMParser){
            parser=new DOMParser();
            xmlDoc=parser.parseFromString(text,"text/xml");
        }
        else // Internet Explorer
        {
            xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async="false";
            xmlDoc.loadXML(text); 
        } 
        // TODO: test to verify its created
        return xmlDoc;
    }
    
    return my;
}

gadgets.util.registerOnLoadHandler(init); 

</script>

]]></Content>
</Module>
