<%@ language = "JavaScript" %>
<% /*
     $Revision$
     $Id$

     File:              api_inssoap.asp
     Description:       API voor INS-soap berichten

     Parameters:        Een xml
     Status:            Opzet. Vereist bevestiging van SOAP-aanroepers en dan afmaken
     Context:
     Notes:

     Wat is het idee momenteel? Deze service is vooralsnog voor sensoren.
     De bedoeling is dat een sensor (een ins_deel) bij het relevant veranderen van de status
     een aanroep doet, met in essentie
     - id (key en/of omschrijving)
     - (nieuwe) waarde => alfanumeriek
     - (nieuwe) status => INSOUT/INSINN
     - optioneel: tijdstip
     De waarde wordt in ins_deel_state opgeslagen. Dat is het, maar daarop wordt elders
     indien de sensor in een reserveerbare ruimte zit gekeken of er een reservering
     bezig is/zou moeten zijn, en dan wordt daarop geacteerd, in de hoek van
     noshow en zo.
     Het meegegeven tijdstip kan worden gebruikt ipv sysdate om vertragingen te corrigeren..
*/
    DOCTYPE_Disable = 1;
    THIS_FILE = "appl/api/api_inssoap.asp";
%>
<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../Shared/xml_converter.inc" -->
<!-- #include file="../Shared/json2.js" -->
<!-- #include file="../api/api.inc" -->
<%
    // We sturen het antwoord in UTF-8.
    Session.Codepage = 65001;
    Response.Charset = 'utf-8';

    var API = new API_func();

    var asJSON = getQParam("json","0")!="0";

    var tsql = "-";        // Voor tijdelijke statement(s)
    var sql = "-";         // De uiteindelijke insert/update-sql
    var xmlReq = Server.CreateObject("MSXML2.DOMDocument.6.0");
    if (API.apidata.stylesheet)
    {
        var iXsl = Server.CreateObject("MSXML2.DOMDocument.6.0");
        if( ! iXsl.load(Server.MapPath(API.apidata.stylesheet)) )
        {
            API.error("Could not load XSL " + API.apidata.stylesheet + "\n" + iXsl.parseError.reason);
        }
        var inputXML = Server.CreateObject("MSXML2.DOMDocument.6.0");
        inputXML.load(Request);
        inputXML.transformNodeToObject(iXsl, xmlReq);
    }
    else
        xmlReq.load(Request);

    if (API.apidata.loglevel) __Log2File(xmlReq.xml, API.APIname + "_TUSSEN");

    var xmlResp = new ActiveXObject("MSXML2.DOMDocument.6.0");
    xmlResp.appendChild(xmlResp.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\""))

    // The response.
    var FCLTElement = xmlResp.createElement("facilitor");
    // The response header.
    var now = new Date();
    var nowtxt = now.getFullYear()+'-'+padout(now.getMonth()+1) +'-'+padout(now.getDate()) +' '
                           +padout(now.getHours()) +':'+padout(now.getMinutes())+':'+padout(now.getSeconds());
    var elmHeader = xmlResp.createElement("header");
    var headerinfo = {
//                      file: String(Request.ServerVariables("SCRIPT_NAME")).toLowerCase(),
                      datum: nowtxt,
                      naam: user.naam(),
                      custId: customerId,
                      language: user.lang()
                     }
    for (param in headerinfo)
    {
        var FCLTdata = xmlResp.createElement(param);
        FCLTdata.appendChild(xmlResp.createTextNode(headerinfo[param]));
        elmHeader.appendChild(FCLTdata);
    }
    //FCLTElement.appendChild(elmHeader);

    // Hier zou het echte werk moeten gebeuren nav. xmlReq
    // en FCLTElement moeten we uitbreiden met antwoorden.
    var detected ="?";

    // Dit is de objecteenloop (mochten er ooit nog anderen gaan volgen).
    var delen = xmlReq.getElementsByTagName("deel");
    for (i=0; i < delen.length; i++)
    {
        var resultcode = -1;   /* Zolang deze -1 is, is het nog goed. Uiteindelijk eindigt het met 0 (als goed). */
        var resulttekst = "";

        // Lees per node de (optionele) tags en waarden.
        var fields = []; // Bij te werken velden.
        var deel_key          = delen[i].getAttribute("key"); // Bij type=update/delete
        var insaction         = delen[i].getAttribute("type").toLowerCase();
        var deel_omschrijving = XMLval(delen[i], "omschrijving"); // soort van foreign ID
        var tijd              = XMLval(delen[i], "tijd");
        var waarde            = XMLval(delen[i], "waarde");
        var outinn            = XMLval(delen[i], "status");

        if (deel_key == null) { // Voorkom problemen als key-attribuut ontbreekt!
          deel_key = '';
        }

        user.checkAutorisation("WEB_INSUSE");

        if (insaction == 'update')   // of specifiek signal?
        {
          if (deel_key == '' && deel_omschrijving == '') {
            resultcode = 2;
            resulttekst = "Undefined object (key/omschrijving)";
          }
          else {
            // Waar hoort-ie bij?
            tsql = "SELECT MAX(ins_deel_key) deel_key, MAX(ins_deel_omschrijving) deel_oms, MAX(ins_deel_state) cur_state, MAX(ins_alg_ruimte_key_org) org_place, COUNT (*) aantal"
                + "   FROM ins_deel"
                + "  WHERE ins_deel_verwijder IS NULL"
                + (deel_key
                   ? " AND ins_deel_key=" + safe.quoted_sql(deel_key)
                   : "")
                + (deel_omschrijving
                   ? " AND ins_deel_upper = " + safe.quoted_sql(deel_omschrijving.toUpperCase())
                   : "");
            var oRs = Oracle.Execute(tsql);
            var aantal = oRs("aantal").value;
            if (aantal == 0) {
              resultcode = 2;
              resulttekst = "Invalid object (key/omschrijving)";
            }
            else if (aantal > 1) {
              resultcode = 3;
              resulttekst = "Object cannot be identified uniquely";
            }
            else {
              // Hier heb ik een geldige deel_key.
              deel_key = oRs("deel_key").value;
              var deel_oms = oRs("deel_oms").value;
              var cur_state = oRs("cur_state").value;
              var org_place = oRs("org_place").value;
              //var old_statedate = new Date(oRs("deel_statedate").Value);

          	  //var this_res = res.func_enabled(rsv_ruimte_key); // Wat heb ik zoal aan rechten op dit object
          	  //user.auth_required_or_abort(this_res.canChange);

              // Meegegeven meetdatumtijd of anders now als laatste teken van leven!
              //if (tijd != null) { // Bij update optioneel
              //  try {
              //    var new_statedate = XMLtoJsDate(tijd);
              //  }
              //  catch (e) {
              //    // Verkeerde datum-formaat, dan now gebruiken!
              //    __DoLog("Formaat ontvangen XML-datum incorrect: "+tijd, "#00FF00");
              //    new_statedate = now;
              //  }
              //} else {
              //  var new_statedate = now;
              //}

              if (waarde) {
                // Alleen bij wijziging!
                if (waarde != cur_state) {
                  // te kiezen: moet de datum altijd aangepast worden (als laatste teken van leven) of
                  // juist niet (als recentste moment van verandering)
                  // veilig kan zijn dit met een waarde in het bericht te sturen, maar ik wil wel graag
                  // dat wij een beste default gekozen hebben: wat is logisch?
                  sql = "UPDATE ins_deel"
                      + "   SET ins_deel_state=" + safe.quoted_sql(waarde)
                      + "     , ins_deel_statedate=SYSDATE" // TODO: de meegegeven meetdatumtijd nemen
                      + " WHERE ins_deel_key=" + deel_key;
                  Oracle.Execute(sql);
                  // FSN#28896: state-changes worden automatisch getrackt in ins_deel_state_history; geen updtracking meer
                  //shared.trackaction("INSUPD", deel_key, L("lcl_deel_state")+" "+safe.quoted_sql(waarde));
                }
              }
              else { // outinn != ''
                // Er zou dus een status moet zijn meegegeven.
                switch (outinn) {
                    case 'INSOUT':
                        // Alleen bij wijziging; object was ingenomen en wordt uitgegeven!
                        if (!org_place) {
                            sql = "UPDATE ins_deel "
                                + " SET ins_alg_ruimte_key_org=ins_alg_ruimte_key"
                                + "   , ins_alg_ruimte_type_org=ins_alg_ruimte_type"
                                + "   , ins_alg_ruimte_key=" + user_key
                                + "   , ins_alg_ruimte_type='P'"
                                + " WHERE ins_deel_key=" + deel_key;
                            Oracle.Execute(sql);

                            // Object [Fiets 1] is uitgegeven aan [Pseudo-user tbv. XXX-API]
                            shared.trackaction("INSOUT", deel_key, L("lcl_obj_is_uitgegeven_to").format(user.naam(), deel_oms));
                        }
                        break;
                    case 'INSINN':
                        // Alleen bij wijziging; object was uitgegeven en wordt ingenomen!
                        if (org_place) {
                            sql = "UPDATE ins_deel "
                                + " SET ins_alg_ruimte_key=ins_alg_ruimte_key_org"
                                + "   , ins_alg_ruimte_type=ins_alg_ruimte_type_org"
                                + "   , ins_alg_ruimte_key_org=NULL"
                                + "   , ins_alg_ruimte_type_org=NULL"
                                + " WHERE ins_deel_key=" + deel_key;
                            Oracle.Execute(sql);

                            // Object is ingenomen
                            shared.trackaction("INSINN", deel_key, L("lcl_obj_is_ingenomen"));
                        }
                        break;
                    default:
                        resultcode = 4;
                        resulttekst = "Invalid waarde/status";
                } // switch
              }

              if (resultcode == -1) { // nog steeds geen fouten
                resultcode = 0; // Ik heb gedaan wat ik moest en mocht doen voor dit object.
              }
            } // if aantal
            oRs.Close();
          } // if deel_key
        }
        else {
          resultcode = 2;
          resulttekst = "Undefined operation (type)";
        } // if insaction

        var binfo = {
                     returncode: resultcode,
                     returntekst: resulttekst,
                     // executed:sql, // debug
                     datum: nowtxt, // TODO: Beter ook xml-datum??? Of de teruggequeriede datumtijd?
                     deel_key: deel_key
                    }

        var FCLTBody = xmlResp.createElement("deel");   // type=response
        FCLTBody.setAttribute('key', deel_key);
        FCLTBody.setAttribute('type', 'response');
        for (param in binfo)
        {
            var FCLTdata = xmlResp.createElement(param);
            FCLTdata.appendChild(xmlResp.createTextNode(binfo[param]));
            FCLTBody.appendChild(FCLTdata);
        }

        FCLTElement.appendChild(FCLTBody);
    } // end for
    // Alle deel-nodes zijn behandeld.

    xmlResp.appendChild(FCLTElement);

    if (API.apidata.loglevel) __Log2File(xmlResp.xml, API.APIname + "_TUSSEN_OUT");
    if (API.apidata.stylesheet)
    {
        // Niet super efficient dat we eerst naar tekstuele xml gaan maar ach...
        STR2Stream(xmlResp.xml, API.apidata.stylesheet, Response, {});
    }
    else
    {
        if (asJSON)
            Response.ContentType = "application/json";
        else
            Response.ContentType = "text/xml";

        if (asJSON)
            var antwoord = JSON.stringify(xmlToJson(xmlResp), null, getQParam("pretty","0")=="1"?2:0);
        else
            var antwoord = xmlResp.xml;
        Response.Write(antwoord);
    }
%>
