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

    File:           facilitor.asp

    Description:    Adapter om standaard Facilitor xml om te zetten naar API1 en API2 aanroepen
    Parameters:
    Context:

    Notes:          Informatie m.b.t. facilitor API : https://developers.facilitor.com/
*/
var JSON_Result = true;
ANONYMOUS_Allowed = 1;
%>
<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../Shared/save2db.inc" -->
<!-- #include file="../Shared/xml_converter.inc" -->
<%
    var ll = getQParamInt("logging", 0);
    if (ll > 0)
        __Logging = ll; // Voor de rest van dit bestand

    function connectfacilitor(methode, actie, params)
    {
        var server_aut = params.info.api_key;
        var server_baseurl = params.info.base_url;
        var server_url = "";
        var missing_id = false;
        var contenttype = "application/json";
__Log(actie);
        var server_conn= { aut:         params.info.api_key
                          , baseurl:     params.info.base_url
                          , url:         ""
                          , contenttype: "application/json"
                          , methode:     methode
                          , actie:       actie
                          };

        switch (actie) // Gebruik hier de parameter uit de aanroep.
        {
            case "issue":           // We gaan nu van de API1 de mldsoap aanroepen
                                    // Dit is de initiele opdrachtverstrekking
                                    server_url = "/issues.json";
                                    switch (methode)
                                    {
                                        case "POST":    if (params.info.boundary) // Dus voor attachment.
                                                        {
                                                            missing_id = (params.info.get_id ? false : true);
                                                            server_conn.url = server_url + "/id/" + params.info.get_id + "/attachments";
                                                            server_conn.methode = "POST";
                                                            server_conn.actie = "attachment";
                                                            server_conn.contenttype = "multipart/form-data;boundary=" + params.info.boundary;
                                                        }
                                                        else
                                                        {
                                                            server_conn.url = server_url;
                                                        }
                                                        break;
                                        case "PUT":
                                        case "PATCH":   if (params.info.get_id) server_conn.url = "/issues/" + params.info.get_id + ".json";
                                                        break;
                                        case "GET":     server_conn.url = server_url + ( params.inc_id
                                                                                         ? "/id/" + params.info.get_id
                                                                                         : (params.start ? "?start="+params.start : "") // start is offset vanaf welk recordnr de volgende 10 records worden getoond.
                                                                                         );
                                                        break;
                                        default:        server_conn.methode = "";
                                    }
                                    break;
            case "order":           server_conn.url = server_conn.url = "/orders/" + params.info.get_id + ".json";
                                    server_conn.methode = "PUT";
                                    break;
            case "notes":           if (params.info.actie == "issue")
                                        server_conn.url = server_conn.url = "/notes.json?module=MLD&scope=fe";
                                    if (params.info.actie == "order")
                                        server_conn.url = server_conn.url = "/notes.json?module=ORD&scope=bo";
                                    server_conn.methode = "POST";
                                    break;
            case "department":      server_url = "/reports.json?rapcode=AFD_LOOKUP&";
                                    switch (methode)
                                    {
                                        case "GET":     server_conn.url = server_url + ((params.lookup && params.lookup.qparams) ? params.lookup.qparams : "");
                                                        break;
                                        default:        server_conn.methode = "";
                                    }
                                    break;
            case "account":         server_url = "/reports.json?rapcode=KPN_LOOKUP&";
                                    switch (methode)
                                    {
                                        case "GET":     server_conn.url = server_url + ((params.lookup && params.lookup.qparams) ? params.lookup.qparams : "");
                                                        break;
                                        default:        server_conn.methode = "";
                                    }
                                    break;
            case "kenmerk":         server_url = "/issueproperties.json?";
                                    switch (methode)
                                    {
                                        case "GET":     server_conn.url = server_url + ((params.lookup && params.lookup.qparams) ? params.lookup.qparams : "");
                                                        break;
                                        default:        server_conn.methode = "";
                                    }
                                    break;
        }
        if (missing_id)
        {
            __Logging = 3;
            __Log(params.info);
            __Log("connection:");
            __Log(server_conn);
        }
        //__Log("connectiondata:");
        //__Log(server_conn);
        server_url = server_conn.baseurl + server_conn.url;
        //__Log("URL to facilitor: " + server_url);
        //__Log("body data");
        //__Log(params.data);
        var errmsg = "";
        var status = -1;
        var data = {};
        if (server_conn.methode != "" && !missing_id)
        {
            try
            {
                var http_request = Server.CreateObject("WinHTTP.WinHTTPRequest.5.1");
                http_request.open(server_conn.methode, server_url, false); // Synchroon
                if (server_conn.methode == "POST")
                {
                    if (server_conn.actie == "issue" || server_conn.actie == "notes")
                    {
                        var body_data = params.data;
                        http_request.setRequestHeader("Authorization", server_aut);
                        http_request.setRequestHeader("Accept", "application/json");
                        http_request.setRequestHeader("Content-Type", server_conn.contenttype);
                        http_request.setRequestHeader("X-FACILITOR-API-Key", server_aut);
                        http_request.send(JSON.stringify(body_data));
                    }
                }
                else if (server_conn.methode == "PUT")
                {
                        var body_data = params.data;
                        http_request.setRequestHeader("Authorization", server_aut);
                        http_request.setRequestHeader("Accept", "application/json");
                        http_request.setRequestHeader("Content-Type", server_conn.contenttype);
                        http_request.setRequestHeader("X-FACILITOR-API-Key", server_aut);
                        http_request.send(JSON.stringify(body_data));
                }
                else if (methode == "GET")
                {
                    http_request.setRequestHeader("Authorization", server_aut);
                    http_request.setRequestHeader("Accept", "application/json");
                    http_request.setRequestHeader("X-FACILITOR-API-Key", server_aut);
                    http_request.send();
                }
                //
                status = http_request.status;
                var status_ok = "200,201,204,206";
                if (status_ok.indexOf(status) == -1)
                {
                    errmsg = "facilitor error. Status: " + http_request.status;
                }
                else
                {
                    if (http_request.responseText)
                    {
                        data = JSON.parse( http_request.responseText);
                    }
                    else
                        data = {};
                }
            }
            catch (e)
            {
                errmsg = "facilitor connection error: " + e.description;
            }
        }
        else
        {
            errmsg = (missing_id ? "unknown id in " : "No method found for executing ") + server_url;
        }
        var connect_result = { status: status
                             , message: errmsg
                             , data: data
                             };
        if (missing_id)
        {
            __Log(connect_result);
        }
        return connect_result;
    }

    function load_headerdata()
    {
        // Lees de xml-data uit de html-header.
        var xmlReq = Server.CreateObject("MSXML2.DOMDocument.6.0");
        xmlReq.load(Request);
        //__DoLog("In headerdata");
        //__DoLog(xmlReq.text);
        // Converteer de xml naar json-dataobject.
        var objreq = xmlToJson(xmlReq);
        return objreq.facilitor;
    }

    function getTypeOf(value)
    {
        if (typeof value === "string" || value instanceof String)               return "isString";
        if (typeof value === "number" && isFinite(value))                       return "isNumber";
        if (typeof value === "boolean")                                         return "isBoolean";
        if (typeof value === "symbol")                                          return "isSymbol";
        if (typeof value === "undefined")                                       return "isUndefined";
        if (typeof value === "function")                                        return "isFunction";
        if (value === null)                                                     return "isNull";
        if (value && typeof value === "object" && value.constructor === Array)  return "isArray";
        if (value && typeof value === "object" && value.constructor === Object) return "isObject";
        if (value && typeof value === "object" && value.constructor === RegExp) return "isRegExp";
        if (value instanceof Error && typeof value.message !== "undefined")     return "isError";
        if (value instanceof Date)                                              return "isData";
        return "isUnknown";
    }

    function resolve_obj(methode, src, path, value)
    {
        //__Log("resolve_obj " + path);
        var methode = (methode == "PATCH" ? "PATCH" : "GET");
        var result = src;
        var found = true;
        var path_arr = path.split(".");
        var last_index = path_arr.length;
        for (var i = 0; i < last_index; i++)
        {
            var indx = -1;
            var node = path_arr[i];
            //__Log("Node:" + node);
            if (node.indexOf("[") > 0)
            {
                node = path_arr[i].split("[")[0];
                indx = path_arr[i].split("[")[1].replace("[","").replace("]","");
            }
            var t = getTypeOf(result[node]);
            //__Log("__> " + node + ": "+ t + (indx != -1 ? " ["+indx+"]" : ""));
            switch (t)
            {
                case "isObject":
                case "isNumber":
                case "isString": if (methode == "PATCH" && (i == last_index-1))
                                    result[node] = value;
                                 else {
                                    result = result[node];
                                    __Log(JSON.stringify(result));
                                 }
                                 break;
                case "isArray":  if (result[node].length && indx >= 0 && indx < result[node].length)
                                 {
                                    if (methode == "PATCH" && (i == last_index-1))
                                        result[node][indx] = value;
                                    else
                                        result = result[node][indx];
                                 }
                                 else
                                 {
                                    found = false;
                                 }
                                 break;
                default: found = false;
            }
            if (!found)
                break;
        }
        //
        //__Log(path + (found?"":" not") + " resolved with methode " + methode);
        //__Log(result);
        //
        return ((found && methode == "GET") ? result : null);
    }

    function replaceLookups(p_obj_facilitor)
    {
        if (p_obj_facilitor.info.methode == "POST" || p_obj_facilitor.info.methode == "PUT" || p_obj_facilitor.info.methode == "GET")
        {
            // Haal eerst de foreign-keys op de je nodig hebt in het data-object.
            var lookup_list = p_obj_facilitor.info.lookup_list;

            // Als er maar 1 lookup gedefinieerd is zal deze als een object in lookup_list staan.
            // Dit moet echter ook in een array staan, net zoals gebeurd als er meer dan 1 lookup gedefinieerd is.
            if (getTypeOf(lookup_list.lookup) != "isArray")
            {
                if (!lookup_list.lookup)
                {
                    lookup_list.lookup = [];
                }
                else
                {
                    var obj_lookup = lookup_list.lookup;
                    delete lookup_list.lookup;
                    lookup_list.lookup = [obj_lookup];
                }
            }

            for (var i = 0; i < lookup_list.lookup.length; i++)
            {
                var z_info = lookup_list.lookup[i];
                //__Log(z_info);                                 // Wat zoek ik waar op en waar zet ik het resultaat weer neer.
                p_obj_facilitor.lookup = lookup_list.lookup[i];  // Maak een nieuwe node lookup aan met de parameters voor het opzoeken.
                // doe een connectfacilitor met een aanvraag voor gegevens (lookup is altijd GET!)
                var z_result = connectfacilitor("GET", z_info.actie, p_obj_facilitor);
                //__Log(z_result);
                if (z_result.message == "" && z_result.data.total_count == 1)
                {
                    // voeg het resultaat toe op de aangewezen plek in p_obj_facilitor
                    __Log("Resultaat lookup van " + z_info.actie);
                    var z_waarde = resolve_obj("GET", z_result, z_info.src);
                    //__Log(p_obj_faciltor);
                    resolve_obj("PATCH", p_obj_facilitor, z_info.dest, z_waarde);
                }
                else
                {
                    if (z_result.status == -1)
                        __Log(z_result.message);
                    else
                        __Log("Lookup heeft geen of meer dan 1 records gevonden");
                }
                delete p_obj_facilitor.lookup;                   // Node met parameters voor lookup weer verwijderen.
            }
        }
    }

    function replaceArrays(p_obj_facilitor)
    {
        if (p_obj_facilitor.info.methode == "POST" || p_obj_facilitor.info.methode == "PUT" || p_obj_facilitor.info.methode == "GET")
        {
            // Enkenvoudige arrays gaan we omzetten naar een array

               var custom_fields_list = {};
               if (p_obj_facilitor.data.issue)
                  custom_fields_list = p_obj_facilitor.data.issue;
               if (p_obj_facilitor.data.order)
                  custom_fields_list = p_obj_facilitor.data.order;

            // Als er maar 1 kenmerk gedefinieerd is zal deze als een object in structuur staan.
            // Dit moet echter ook in een array staan.
            if (getTypeOf(custom_fields_list.custom_fields) != "isArray")
            {
                if (!custom_fields_list.custom_fields)
                {
                    custom_fields_list.custom_fields = [];
                }
                else
                {
                    var obj_custom_fields = custom_fields_list.custom_fields;
                    delete custom_fields_list.custom_fieldsp;
                    custom_fields_list.custom_fields = [obj_custom_fields];
                }
            }
//__Log(custom_fields_list);
            for (var i = 0; i < custom_fields_list.custom_fields.length; i++)
            {
               var attachment_list = custom_fields_list.custom_fields[i];

               if (attachment_list.attachments) {
                   // Als er maar 1 kenmerk gedefinieerd is zal deze als een object in structuur staan.
                   // Dit moet echter ook in een array staan.
                   if (getTypeOf(attachment_list.attachments) != "isArray")
                   {
                       if (!attachment_list.attachments)
                       {
                           attachment_list.attachments = [];
                       }
                       else
                       {
                           var obj_attachments = attachment_list.attachments;
                           delete attachment_list.attachments;
                           attachment_list.attachments = [obj_attachments];
                       }
                   }
                   __Log(attachment_list);
                   // De structuur van de bijlagen in de xml is anders dan in API2
                   for (var j = 0; j < custom_fields_list.custom_fields[i].attachments.length; j++)
                   {
                      if (custom_fields_list.custom_fields[i].attachments[j].bijlage)
                      {
                          //__Log (custom_fields_list.custom_fields[i].attachments[j].bijlage.attachment);
                          custom_fields_list.custom_fields[i].attachments[j].content_base64 = custom_fields_list.custom_fields[i].attachments[j].bijlage.attachment;
                          custom_fields_list.custom_fields[i].attachments[j].name = custom_fields_list.custom_fields[i].attachments[j].bijlage.name;
                          delete custom_fields_list.custom_fields[i].attachments[j].bijlage;
                          //__Log(attachment_list);
                      }
                   }
               }
            }
        }
    }


    // *************************************************************************
    function sendNotes(p_obj_facilitor)
    {
        //__Log("sendNotes: " + p_obj_facilitor.info.methode);
        notes_result = [];
        if (p_obj_facilitor.info.methode == "PUT")
        {
            var t = (p_obj_facilitor.data.notes ? getTypeOf(p_obj_facilitor.data.notes.note) : "isUnknown");
            //__Log("note: " + t);
            switch (t)
            {
                case "isUndefined": var notes = [];                               break; // geen notes
                case "isObject":    var notes = [p_obj_facilitor.data.notes.note]; break; // 1 note
                case "isArray":     var notes = p_obj_facilitor.data.notes.note;   break; // 2 of meer notes
                default:            var notes = [];
            }
            for (var i=0; i < notes.length; i++)
            {
                var note = notes[i];
                var new_facilitor = { info: p_obj_facilitor.info };
                //new_facilitor.info.get_id = p_server_result.data.id;
                //__Log(new_facilitor);
                //
                new_facilitor.data = {"note": note};
                var result = connectfacilitor("POST", "notes", new_facilitor);
                //
                result.fclt_msg = ( (result.status == 200 || result.status == 201)
                                  ? "Note toegevoegd"
                                  : "Note kon niet worden toegevoegd"
                                  );
                notes_result.push(result);
            }
        }
        return notes_result;
    }

    // *************************************************************************
    function sendNotificaties(p_obj_facilitor)
    {
        //__Log("sendNotes: " + p_obj_facilitor.info.methode);
        notificaties_result = [];
        if (p_obj_facilitor.info.methode == "PUT")
        {
            var t = (p_obj_facilitor.data.notificaties ? getTypeOf(p_obj_facilitor.data.notificaties.notificatie) : "isUnknown");
            //__Log("notificatie: " + t);
            switch (t)
            {
                case "isUndefined": var notificaties = [];                               break; // geen notes
                case "isObject":    var notificaties = [p_obj_facilitor.data.notificaties.notificatie]; break; // 1 note
                case "isArray":     var notificaties = p_obj_facilitor.data.notificaties.notificatie;   break; // 2 of meer notes
                default:            var notificaties = [];
            }
            for (var i=0; i < notificaties.length; i++)
            {
                var notificatie = notificaties[i];
                var new_facilitor = { info: p_obj_facilitor.info };
                //new_facilitor.info.get_id = p_server_result.data.id;
                //__Log(new_facilitor);
                //
                new_facilitor.data = {"order": notificatie};
                var result = connectfacilitor("PUT", "order", new_facilitor);
                //
                result.fclt_msg = ( (result.status == 200 || result.status == 201)
                                  ? "Notificatie toegevoegd"
                                  : "Notificatie kon niet worden toegevoegd"
                                  );
                notificaties_result.push(result);
            }
        }
        return notes_result;
    }


    function update_mld(methode, actie, melding, params)
    {
        mld_key = melding.mld_melding_key || -1;
        //__Log(params);
        __Log(melding);
        if (params.ticket)
        {
            var opm = (methode == "POST" ? "Creating " : "Updating ") + actie + " facilitor. Status: " + params.ticket.status  + (params.ticket.message.length != 0?" Message: " + params.ticket.message:"");
            shared.trackaction("#MLDTRK", mld_key, opm);
        }
    }


    function update_mldopdr(methode, actie, melding, params)
    {
        var opdr_key = melding.opdracht.mld_opdr_key || -1;
        if (params.ticket)
        {
            if (params.ticket.status >= 200 && params.ticket.status < 300 && params.ticket.data.issue.id)
            {
                var sql = "";
                var v_id = "";
                if (methode == "POST" && actie == "issue")
                {
                    var v_omschr = "\nfacilitor nr: " + params.ticket.data.issue.id;
                    v_id = "Melding naar facilitor doorgestuurd. id: " + params.ticket.data.issue.id;
                    sql = "UPDATE mld_opdr"
                        + "   SET mld_opdr_externnr = " + safe.quoted_sql("" + params.ticket.data.issue.id)
                        + "     , mld_opdr_omschrijving = SUBSTR( mld_opdr_omschrijving"
                        + "                                     , GREATEST(LENGTH(mld_opdr_omschrijving)+LENGTH(" + safe.quoted_sql(v_omschr) + ")-3999, 1)"
                        + "                                     ) || " +  safe.quoted_sql(v_omschr)
                        + " WHERE mld_opdr_key = " + opdr_key;
                }
                else if (methode == "PUT" && actie == "issue")
                {
                    // Soms wordt er een nieuwe opdracht aangemaakt als er een bug wordt afgemeld die leidt tot een change
                    // Voor de change is dan een nieuwe opdracht aangemaakt die gelinkt is aan dezelfde melding in het logcenter
                    // In dat geval gaan we toch het externnummer vullen voor de verdere communicatie.
                    v_id = "Update naar facilitor doorgestuurd. id: " + params.ticket.data.issue.id;
                    sql = "UPDATE mld_opdr"
                        + "   SET mld_opdr_externnr = " + safe.quoted_sql("" + params.ticket.data.issue.id)
                        + " WHERE mld_opdr_externnr IS NULL "
                        + "   AND mld_opdr_key = " + opdr_key;
                }
                if (sql)
                    Oracle.Execute(sql);
                shared.trackaction("#ORDTRK", opdr_key, v_id);
            }
            else
            {
               if (params.ticket.data.message)
               {
                  shared.trackaction("#ORDTRK", opdr_key, "Foutmelding: " + safe.quoted_sql(params.ticket.data.message));
               }
            }
            //var opm = (methode == "POST" ? "Creating " : "Updating ") + actie + " facilitor. Status: " + params.ticket.status;
            //shared.trackaction("#MLDDOO", opdr_key, opm);
        }
    }

    // *************************************************************************
    __DoLog("*> facilitor.api");
    var facilitor = load_headerdata();

    if (facilitor && facilitor.server)
    {
        var obj_facilitor = facilitor.server || {};

        //
        // Zoek eerst de benodigde id's op
        replaceLookups(obj_facilitor);
        replaceArrays(obj_facilitor);

        // Deze log staat als commentaar omdat in deze JSON ook de base64 coded bijlage zit. Dat levert te veel logging op.
        //__Log(obj_facilitor);
        // We gaan alleen een bericht versturen als we een geldige methode hebben. We gebruiken de methode NONE om
        // aan te geven dat dit bericht niet verstuurd hoeft te worden. Dit is de mogelijkheid om
        // in de stylesheet aan te geven dat je geen bericht wilt versturen op deze notificatie.
        if (obj_facilitor.info.methode != 'NONE')
        {
            var data_result = connectfacilitor(obj_facilitor.info.methode, obj_facilitor.info.actie, obj_facilitor);
            __Log("facilitor result:");
            __Log(data_result);
            if (data_result.status != -1)
            {
                var note_result = sendNotes(obj_facilitor);
                var notificatie_result = sendNotificaties(obj_facilitor);

                var result = { ticket: data_result
                             , note: note_result
                             };

                if (facilitor.melding.opdracht)
                {
                    update_mldopdr(obj_facilitor.info.methode, obj_facilitor.info.actie, facilitor.melding, result)
                }
                else if (facilitor.melding)
                {
                    update_mld(obj_facilitor.info.methode, obj_facilitor.info.actie, facilitor.melding, result)
                }
                else
                {
                    var result = { ticket: { status: 600, message: "Onbekende melding" } };
                    __DoLog(facilitor);
                }
            }
            else
            {
                var result = { ticket: { status: 400, message: server_result.message } };
                __DoLog(safe.html(result.ticket.message), "ff0000");
            }
        }
        else
        {
           var result = { ticket: { status: 200, message: "er hoeft geen bericht verstuurd te worden" } };
        }
        //
    }
    else
    {
        var result = { ticket: { status: 600, message: "geen facilitor data aanwezig" } };
        __DoLog(safe.html(result.ticket.message), "ff0000");
    }
    __Log(result);
    __Log("*< facilitor.api");
    Response.Write(JSON.stringify(result));
    if (result.ticket.status)
    {
       Response.Status = result.ticket.status + " " + result.ticket.message;
    }
    Response.End;
%>
<% ASPPAGE_END(); %>
