
// PIVOTE Player
//
// Copyright (C) 2009 Daden Limited
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// See http://www.gnu.org/licenses/ for a copy of the GNU General Public License
//
// For more details and information about the PIVOTE project go to www.pivote.info
// Download source and documentation from http://code.google.com/p/pivote
//  Contact us at info@pivote.info
//




// DO NOT CHANGE BELOW THIS LINE
string gStartImage = "preview"; // default show, usually do not change
vector txtcol = <1,1,1>;
float txtalpha = 1.0;

integer gIdleTimer = 1800; // returns to first slide, make lot longer if doing a conference! !!! IMPLEMENTED??
integer gPIVOTEChannel = 687686; // different for each master within 20m - MUST CHANGE ALL OBJECTS
integer gMediaCh = -63342;
integer gUseDialog = FALSE; // deprecated?

integer gOffset;
integer gBlock = 5;
string gPage = "node";

integer lh;
key mediakey;
integer mediamode;
string gNodeLabel;
string gNodeDesc;
string gNodeImage;
string gNodeMedia;
string gNodeOptions;
string gSSID;
string gPIVOTEPrefix;
integer gQuickStart=FALSE;
integer gQuickOption=FALSE;
string gStartCommands;
string gEndCommands;
string gResetCommands;


string gServiceUID = "";
string gServicePwd = "";

string gTutorGroupID="";
string gControllerName="";
string gCustomMVP=""; // NYI
integer gUserLock=FALSE;  // NYI

// configs
integer gShowNodeLabel=FALSE;
string gFilter = "";

string gServiceURL = "http://www.daden.co.uk/cgi-bin/clients/mvp/mvpplayer.pl";
string gServicePageURL = "http://www.daden.co.uk/clients/mvp/slpages/";
string gHelpURL = "http://www.daden.co.uk/clients/mvp/slpages/slhelp.html";
string gMenuURL = "http://www.daden.co.uk/clients/mvp/slpages/slmenu.html";
string gIdleURL = "http://www.daden.co.uk/clients/mvp/slpages/slmenu.html";
string gUpdatingURL = "http://www.daden.co.uk/clients/mvp/slpages/slupdating.html";
string gObjectBox = "MVP Paramedic Equipment Box";
integer gShowHUD=TRUE;
integer gShowObjects=TRUE;
integer gShowSession=TRUE;
//

integer gAutoShow = FALSE;
integer gAutoShowTime = 5;
key gUserKey = NULL_KEY;
string gNode = "";
string urlroot;
//string gServicePageURL;
string gCase;
list gOptions;
key Rq_getnode;
key Rq_getpage;
key Ds_getLine;
string gConfigCard = "pivotecontroller.cfg";
integer gLine;
string gExerciseList = "";



option_reset() {
    llWhisper(0, "Please wait, loading configuration data ...");
    set_media(gUpdatingURL);
    send_cmd(gResetCommands);
    gLine = 0;
    Ds_getLine = llGetNotecardLine(gConfigCard, gLine);
}


config_load(string p, string v) {
    if (p == "gShowNodeLabel") {
        gShowNodeLabel = TRUE;
        if (v == "FALSE") {
            gShowNodeLabel = FALSE;
        }
    }
    if (p == "gShowHUD") {
        gShowHUD = TRUE;
        if (v == "FALSE") {
            gShowHUD = FALSE;
            set_button("hud", "hide");
        } else {
            set_button("hud", "show");
        }
    }
    if (p == "gShowObjects") {
        gShowObjects = TRUE;
        if (v == "FALSE") {
            gShowObjects = FALSE;
            set_button("objects", "hide");
        } else {
            set_button("objects", "show");
        }
    }
    if (p == "gShowSession") {
        gShowSession = FALSE;
        if (v == "TRUE") { gShowSession = TRUE;}
    }
    if (p == "gServiceURL") {
        gServiceURL = v;
    }
    if (p == "gServicePageURL") {
        gServicePageURL = v;
    }
    if (p == "gHelpURL") {
        gHelpURL = v;
    }
    if (p == "gMenuURL") {
        gMenuURL = v;
    }
    if (p == "gUpdatingURL") {
        gUpdatingURL = v;
    }
    if (p == "gFilter") {
        gFilter = llEscapeURL(v);
    }
    if (p == "gExerciseList") {
        gExerciseList = v;
    }
    if (p == "gPIVOTEChannel") {
        gPIVOTEChannel = (integer)v;
    }
    if (p == "gPIVOTEPrefix") {
        gPIVOTEPrefix = v;
    }
    if (p == "gMediaCh") {
        gMediaCh = (integer)v;
    }
    if (p == "gIdleTimer") {
        gIdleTimer = (integer)v;
    }
    if (p == "gQuickStart") {
        gQuickStart=FALSE;
        if (v == "TRUE") { gQuickStart = TRUE;}
    }
    if (p == "gQuickOption") {
        gQuickOption=FALSE;
        if (v == "TRUE") { gQuickOption = TRUE;}
    }

    if (p == "gUserLock") {
        gUserLock=TRUE;
        if (v == "FALSE") { gUserLock = FALSE;}
    }
    if (p == "gServiceUID") {
        gServiceUID = v;
    }
    if (p == "gServicePwd") {
        gServicePwd = v;
    }
    if (p == "gTutorGroupID") {
        gTutorGroupID = v;
    }
    if (p == "gControllerName") {
        gControllerName = v;
    }
    if (p == "gStartCommands") {
        gStartCommands = v;
    }
    if (p == "gEndCommands") {
        gEndCommands = v;
    }
    if (p == "gResetCommands") {
        gResetCommands = v;
    }

    if (p == "gCustomMVP") {
        gCustomMVP = v;
    }
    llListenRemove(lh);
    lh = llListen(gPIVOTEChannel, "", NULL_KEY, "");
    urlroot = gServiceURL+"?op=sl&wl=sl";
    urlroot += "&uid="+llEscapeURL(gServiceUID);
    urlroot += "&pwd="+llEscapeURL(gServicePwd);
    urlroot += "&controller="+llEscapeURL(gControllerName);
    urlroot += "&tutor="+llEscapeURL(gTutorGroupID);
}

send_cmd(string s) {
    if (s != "") {
        if (gPIVOTEPrefix == "") {
                llSay(gPIVOTEChannel, s);
        } else {
                llSay(gPIVOTEChannel, gPIVOTEPrefix+":"+s);
        }
    }
}

option_start(key id) {
    //integer i;
    //gNode = "";
    //gCase = llGetObjectDesc();
    //string url = urlroot+"&case="+gCase+"&node="+gNode;
    //llSay(0, "Case is: "+gCase);
    //llWhisper(0, "Fetching Node feed from web ...");
    // set_button("play_hide");
    string url = urlroot;
    url += "&mvp="+llEscapeURL(gCustomMVP);
    send_cmd(gResetCommands);
    //send_cmd("all|die");
    //send_cmd("all|reset");
    gOffset = 0;
    if (gExerciseList == "") {
        url += "&block="+(string)gBlock+"&offset=0&api=list&filter="+gFilter;
        //llSay(0, "URL: " + url);
        Rq_getpage = llHTTPRequest(url, [HTTP_METHOD,"GET"], "");
    } else {
        if (gQuickStart && (llSubStringIndex(gExerciseList, ",") == -1)) {
            // just one
            gCase = gExerciseList;
            string msg = llEscapeURL(gExerciseList);
            Rq_getnode = llHTTPRequest(url+"&api=shownode&av="+llEscapeURL(llKey2Name(id))+"&case="+msg, [HTTP_METHOD,"GET"], "");
        } else {
            // more than one or not quick start
            url += "&block="+(string)gBlock+"&offset=0&api=list&filter="+gFilter+"&avail="+llEscapeURL(gExerciseList);
            //llSay(0, "URL: " + url);
            Rq_getpage = llHTTPRequest(url, [HTTP_METHOD,"GET"], "");
        }
    }
}

option_options(key id) {
    string msg = gNodeDesc+"\n\n";
    gOptions = llParseString2List(gNodeOptions,["</o>"],[]);
    integer l = llGetListLength(gOptions);
    integer i;
    if ((gQuickOption) && (l==1)) {
        // call option 1
        option_option(0);
    } else {
        set_media(gServicePageURL+gSSID+"_options.html?"+gNode);

    }
}


option_text() {
    set_media(gServicePageURL+gSSID+"_title.html?"+gNode);
    llSay(0, gNodeDesc);
}
option_media() {
    if (gNodeImage != "") {
        set_media(gNodeImage);
    } else {
        if (gNodeMedia != "") {
            set_media(gNodeMedia);
        } else {
            set_media(gIdleURL);
        }
    }
}
option_help() {
    set_media(gHelpURL);
}
option_menu() {
    set_media(gMenuURL);
}
option_back() {
    if (gPage == "node") {
        llSay(0, "Going back");
        Rq_getnode = llHTTPRequest(urlroot+"&api=back&case="+gCase+"&ssid="+gSSID, [HTTP_METHOD,"GET"], "");
    } else {
        llSay(0, "Back is only active during an exercise");
    }
}
option_showbrowser(key id) {
    llSay(gMediaCh, (string)id + "~showbrowser");
}
option_option(integer num) {
    integer l = llGetListLength(gOptions);
    list o = llParseString2List(llList2String(gOptions, num), ["</l><i>"],[]);
    //llOwnerSay("heard "+(string)num+" with gPage "+gPage);
    if (llList2String(o, 0) != "") {
        set_media(gUpdatingURL);
        string msg = llGetSubString(llList2String(o, 1), 0, -5);
        //llOwnerSay("Fetching Node "+msg+"from web ...");
        if (gPage == "node") {
            msg = llEscapeURL(msg);
            Rq_getnode = llHTTPRequest(urlroot+"&api=shownode&case="+gCase+"&node="+msg+"&ssid="+gSSID, [HTTP_METHOD,"GET"], "");
        }
        if (gPage == "case list") {
            if (msg == "_start") {
                msg = "";
                option_start(NULL_KEY);
                msg == "";
            }
            if (msg == "_more") {
                gOffset += gBlock;
                msg = "";
                Rq_getpage = llHTTPRequest(urlroot+"&api=list&offset="+(string)gOffset+"&block="+(string)gBlock+"&filter="+gFilter+"&avail="+llEscapeURL(gExerciseList), [HTTP_METHOD,"GET"], "");
            }
            if (msg != "") {
                gCase = msg;
                msg = llEscapeURL(msg);
                Rq_getnode = llHTTPRequest(urlroot+"&api=shownode&av="+llEscapeURL(llKey2Name(gUserKey))+"&case="+msg, [HTTP_METHOD,"GET"], "");
            }

        }

    }
}


set_button(string btn, string cond) {
    llMessageLinked(LINK_SET, 0, btn+"_"+cond, NULL_KEY);
    //llSay(mvpch, "HUD button "+btn+" "+cond); !!!!!!!!!!!why?
}


set_media(string url) {
    llSay(gMediaCh, url);
    //llOwnerSay("set media on"+(string)gMediaCh+"to " + url);
}

string XMLextractTag (string stream, string tag) {
    string param;
    integer sts = llSubStringIndex(stream, "<"+tag+">");
    integer ste = llSubStringIndex(stream, "</"+tag+">");
    integer len = llStringLength(tag);
    sts += len + 2;
    ste--;
    if (sts > ste) {
        param = "";
    } else {
        param = llGetSubString(stream,sts,ste);
    }
    //llWhisper(0,"s:"+(string)sts+" e:"+(string)ste+" l:"+(string)len+" p:"+param);
    return param;
}


default
{
    state_entry() {
        integer i;
        option_reset();
        //lh = llListen(mvpch, "", NULL_KEY, "" ); - move to config load
    }


    listen(integer channel, string name, key id, string msg) {
        integer update = FALSE;
        gUserKey = id;
        if (llSubStringIndex(msg, "user=") == 0) {
            integer amp = llSubStringIndex(msg, "&");
            amp--;
            gUserKey = (key)llGetSubString(msg, 5, amp);
            id = gUserKey;
            amp += 2;
            msg = llGetSubString(msg, amp, -1);
            //llOwnerSay((string)gUserKey+" = "+llKey2Name(id)+" leaving "+msg);
        }
        if (msg == "start") {
            option_start(NULL_KEY);
        }
        if (msg == "reset") {
            option_reset();
        }
        if (msg == "options") {
            option_options(id);
        }
        if (llSubStringIndex(msg, "option=") != -1) {
            llSay(0, msg);
            integer num = (integer) llGetSubString(msg, 7, -1);
            option_option(num);
        }
        if (msg == "text") {
            option_text();
        }
        if (msg == "media") {
            option_media();
        }
        if (msg == "back") {
            option_back();
        }

        if (msg == "menu") {
            option_menu();
        }
        if (msg == "help") {
            option_help();
        }
        if (msg == "hardreset") {
            llResetScript();
        }
        if (llSubStringIndex(msg, "node=") == 0) {
            msg = llGetSubString(msg, 5, -1);
            //llSay(0, "heard "+msg);
            update = TRUE;
        }
        if (update) {
            // fetch next scene
            //llWhisper(0, "Fetching Node "+msg+" from web ...");
            set_media(gUpdatingURL);
            msg = llEscapeURL(msg);
            Rq_getnode = llHTTPRequest(urlroot+"&case="+gCase+"&node="+msg+"&ssid="+gSSID, [HTTP_METHOD,"GET"], "");
        }

    }

        http_response(key request_id, integer status, list metadata, string body) {
        string response;
        //llOwnerSay(body);
        //llSay(0, "Response: " + body);

        if (request_id == Rq_getnode) { // simple get
            // split into fields
            //list fields = llParseStringKeepNulls(body,["|"],[]);
            //llSay(0, body);
            gSSID = XMLextractTag(body, "ss");
            //llOwnerSay("ssid = "+gSSID);
            gPage = "node";
            set_button("media", "hide");
            set_button("options", "hide");
            // show text first
            gNode = XMLextractTag(body, "id");
            set_media(gServicePageURL+gSSID+"_title.html?"+gNode);
            gNodeMedia = "";
            gNodeImage = "";
            gNodeLabel = XMLextractTag(body, "lbl");
            string rd =  XMLextractTag(body, "rd");
            string localtext;
            if (gShowNodeLabel) {
                llSay(0, gNodeLabel); // + " ("+gNode+")");
            }
            if (rd != "") {
                llSay(0, rd);
            }
            list dam = llParseString2List(body, ["</dam>"], []);
            integer ndam = llGetListLength(dam);
            integer i;
            for (i = 0; i < ndam; i++) {
                string dtext = XMLextractTag(llList2String(dam, i), "d");
                string device = XMLextractTag(llList2String(dam, i), "v");
                string type = XMLextractTag(llList2String(dam, i), "type");

                integer done = FALSE;
                if (type == "VPDImage") {
                    gNodeImage =  XMLextractTag(llList2String(dam, i), "d");
                    //llOwnerSay("img = " + gNodeImage);
                    dtext = "";
                    //set_media(gNodeImage);
                    done = TRUE;
                    set_button("media", "show");
                }
                if (type == "VPDMedia") {
                    gNodeMedia =  XMLextractTag(llList2String(dam, i), "d");
                    //llOwnerSay("media = " + gNodeMedia);
                    dtext = "";
                    //set_media(gNodeMedia);
                    done = TRUE;
                    set_button("media", "show");

                }



                if (dtext != "") {
                    // check device
                    if (device == "") {
                    // default
                    //llReplaceStringList
                        llSay(0, dtext);
                        localtext = localtext + dtext + ". ";

                    } else {
                         // assume at beginning
                        send_cmd("<device>"+device+"</device>"+dtext);
                        // check how handle images
                    }
                }
                if (gNode == "finish") {
                    send_cmd(gEndCommands);
                    if (gShowSession) {
                        llSay(0, "Please note that your Session ID was "+(string)gSSID+". Please make a note of it as you may need it for later assessment or review.");
                    }

                }


            }

            gNodeOptions = XMLextractTag(body, "links");
            if (llSubStringIndex(gNodeOptions, "</o>") != -1) {
                set_button("options", "show");
                gOptions = llParseString2List(gNodeOptions,["</o>"],[]);
            }
            if (gAutoShow) {
                llSleep(gAutoShowTime);
                if (gNodeImage != "") {
                    set_media(gNodeImage);
                } else {
                    if (gNodeMedia != "") {
                        set_media(gNodeMedia);
                    }
                }
                //llSleep(gAutoShowTime);
                //nodeoptions(gUserKey);
            }
            //nodeoptions(NULL_KEY);
        }
        if (request_id == Rq_getpage) { // simple get
            gSSID = XMLextractTag(body, "ss");
            gPage = "case list";
            // split into fields
            //list fields = llParseStringKeepNulls(body,["|"],[]);
            //llSay(0, body);
            set_button("media", "hide");
            set_button("options", "hide");
            // show text first
            set_media(gServicePageURL+gSSID+"_title.html?");
            gNodeOptions = XMLextractTag(body, "cl");
            if (llSubStringIndex(gNodeOptions, "</o>") != -1) {
                set_button("options", "show");
            }
            if (gAutoShow) {
                llSleep(gAutoShowTime);
                option_options(NULL_KEY);
            }
            //nodeoptions(NULL_KEY);
        }

    }


    link_message(integer sender_num, integer num, string str, key id) {
        integer done = FALSE;
        gUserKey = id;

        if (str == "start") {
            done = TRUE;
            option_start(NULL_KEY);
        }
        if (str == "reset") {
            done = TRUE;
            option_reset();
        }

        if (str == "options") {
            done = TRUE;
            option_options(id);
        }
        if (str == "text") {
            done = TRUE;
            option_text();
        }

        if (str == "media") {
            option_media();
            done = TRUE;
        }
        if (str == "back") {
            option_back();
            done = TRUE;
        }

        if (str == "help") {
            done = TRUE;
            option_help();
        }
        if (str == "menu") {
            done = TRUE;
            option_menu();
        }

        if (str == "option") {
            option_option(num);
        }
        if (str == "hud") {
            // NOTE - WILL FAIL IF CONTROLLER IS GROUP OWNED
            llGiveInventory(id, "MVP HUD Player");
            // ALTERNATIVE TO REZ - ENSURE OBJECT IS COPYABLE
            llRezObject("MVP HUD Player", llGetPos()+<0,0,1>, <0,0,0>, <0,0,0,0>, 0);
        }
        if (str == "objects") {
            // NOTE - WILL FAIL IF CONTROLLER IS GROUP OWNED
            llGiveInventory(id, gObjectBox);
            // ALTERNATIVE TO REZ - ENSURE OBJECT IS COPYABLE
            llRezObject(gObjectBox, llGetPos()+<0,0,1>, <0,0,0>, <0,0,0,0>, 0);
            // FINAL IMPLEMENTATION SHOULD ALLOW DIALOG BOX FOR MULTIPLE OBJECTS

        }
        if (str == "showbrowser") {
            option_showbrowser(gUserKey);
        }
        if (str == "hardreset") {
            llResetScript();
        }



    }

    timer() {
        //llResetScript(); - too violent?
        llSetTimerEvent(0);
        llWhisper(0, "Resetting display");
        option_start(NULL_KEY);
    }

    dataserver(key query_id, string data) {
        list l;
        string param;
        string value;
        if (query_id == Ds_getLine) {
            if (data != EOF) {    // not at the end of the notecard
                if ((llSubStringIndex(data, "//") == 0) || (llSubStringIndex(data, "=") == -1)) {
                    // comment or invalid
                } else {
                    // valid
                    l = llParseString2List(data, ["="], []);
                    param = llList2String(l, 0);
                    value = llList2String(l, 1);
                    config_load(param, value);
                }
                // next line
                Ds_getLine = llGetNotecardLine(gConfigCard, ++gLine);
            } else {
                llWhisper(0, "Config loaded. Started.");
                option_start(NULL_KEY); // id
            }
        }
    }

}

