﻿
// huffware script: zen mondo's mailbox, modified by fred huffhines.
//
// original attributions are below.
//
// my changes are licensed via:
//   this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html
//   do not use it in objects without fully realizing you are implicitly accepting that license.
//

//////////////////////////////////////
// ZenMondo's Mailbox by ZenMondo Wormser
//
// Displays Online Status, as well as accepting
// notecard "mail" to be be delivered to owner.
//
// Cleans Up after itself, deletes non-notecards.
//
//
// LICENSE:
//
//  This script is given for free, and may NOT be 
//  resold or used in a commercial product.
//  You may copy and distribute this script for free.
//  When you redistribute or copy this script, you must
//  do so with FULL PERMS (modify, copy, and transfer),
//  and leave this notice intact.
//
//  You are free to modify this code, but any derivitive
//  scripts must not be used in a commercial product or
//  or sold, and must contain this license.  
//
//  This script is provided free for learning 
//  purposes, take it apart, break it, fix it, 
//  learn something.  If you come up with something 
//  clever, share it.
//
//  Questions about codepoetry (scripting) can always be addressed
//  to me, ZenMondo Wormser.
//
///////////////////////////////////////// 

key online_query;

key name_query;

string user_name;


//////////////
// huffware script: auto-retire, by fred huffhines, version 2.5.
// distributed under BSD-like license.
//   !!  keep in mind that this code must be *copied* into another
//   !!  script that you wish to add auto-retirement capability to.
// when a script has auto_retire in it, it can be dropped into an
// object and the most recent version of the script will destroy
// all older versions.
//
// the version numbers are embedded into the script names themselves.
// the notation for versions uses a letter 'v', followed by two numbers
// in the form "major.minor".
// major and minor versions are implicitly considered as a floating point
// number that increases with each newer version of the script.  thus,
// "hazmap v0.1" might be the first script in the "hazmap" script continuum,
// and "hazmap v3.2" is a more recent version.
//
// example usage of the auto-retirement script:
//     default {
//         state_entry() {
//            auto_retire();  // make sure newest addition is only version of script.
//        }
//     }
// this script is partly based on the self-upgrading scripts from markov brodsky
// and jippen faddoul.
//////////////
auto_retire() {
    string self = llGetScriptName();  // the name of this script.
    list split = compute_basename_and_version(self);
    if (llGetListLength(split) != 2) return;  // nothing to do for this script.
    string basename = llList2String(split, 0);  // script name with no version attached.
    string version_string = llList2String(split, 1);  // the version found.
    integer posn;
    // find any scripts that match the basename.  they are variants of this script.
    for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) {
        string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn);
        if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) {
            // found a basic match at least.
            list inv_split = compute_basename_and_version(curr_script);
            if (llGetListLength(inv_split) == 2) {
                // see if this script is more ancient.
                string inv_version_string = llList2String(inv_split, 1);  // the version found.
                // must make sure that the retiring script is completely the identical basename;
                // just matching in the front doesn't make it a relative.
                if ( (llList2String(inv_split, 0) == basename)
                    && ((float)inv_version_string < (float)version_string) ) {
                    // remove script with same name from inventory that has inferior version.
                    llRemoveInventory(curr_script);
                }
            }
        }
    }
}
//
// separates the base script name and version number.  used by auto_retire.
list compute_basename_and_version(string to_chop_up)
{
    // minimum script name is 2 characters plus a version.
    integer space_v_posn;
    // find the last useful space and 'v' combo.
    for (space_v_posn = llStringLength(to_chop_up) - 3;
        (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v");
        space_v_posn--) {
        // look for space and v but do nothing else.
    }
    if (space_v_posn < 2) return [];  // no space found.
    // now we zoom through the stuff after our beloved v character and find any evil
    // space characters, which are most likely from SL having found a duplicate item
    // name and not so helpfully renamed it for us.
    integer indy;
    for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) {
        if (llGetSubString(to_chop_up, indy, indy) == " ") {
            // found one; zap it.  since we're going backwards we don't need to
            // adjust the loop at all.
            to_chop_up = llDeleteSubString(to_chop_up, indy, indy);
        }
    }
    string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1);
    // ditch the space character for our numerical check.
    string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1);
    // strip out a 'v' if there is one.
    if (llGetSubString(chop_suffix, 0, 0) == "v")
        chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1);
    // if valid floating point number and greater than zero, that works for our version.
    string basename = to_chop_up;  // script name with no version attached.
    if ((float)chop_suffix > 0.0) {
        // this is a big success right here.
        basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1);
        return [ basename, chop_suffix ];
    }
    // seems like we found nothing useful.
    return [];
}
//
//////////////


default {
    state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; }
    on_rez(integer parm) { state rerun; }
}
state rerun { state_entry() { state default; } }

state real_default
{
    state_entry()
    {
        auto_retire();
        llAllowInventoryDrop(TRUE);
        name_query = llRequestAgentData(llGetOwner(), DATA_NAME);
        llSetText("Setting Up, Ready in one minute.", <0,1,1>, 1.0);
        llSetTimerEvent(60);
        
        
    }

    timer()
    {
        online_query = llRequestAgentData(llGetOwner(),DATA_ONLINE);          
    }
    
    dataserver(key queryid, string data)
    {
        
        if(queryid == name_query)
        {
            user_name = data;
            //llSay(0, data + " " + user_name);
        }
        
        if(queryid == online_query)
        {
            integer online = (integer) data;
        
            if(online)
            {
                llSetText(user_name + " is ONLINE\nDrop a NoteCard into me\nto Send " + user_name + " a message.", <0,1,0>, 1.0);
                return;   
            }
        
            else
            {
                llSetText(user_name + " is OFFLINE\nDrop a NoteCard into me\nto Send " + user_name + " a message.", <1,0,0>, 1.0);
                return;
            }
       
        }     
    }
    
    changed(integer mask)
    {
        if(mask & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY))
        {
            integer num_notes = llGetInventoryNumber(INVENTORY_NOTECARD);
            
            if(num_notes > 0)
            {
                string note_name = llGetInventoryName(INVENTORY_NOTECARD, 0);
                            
                llSay(0, "Sending Notecard, '" + note_name +"' please stand by.");
            
                llGiveInventory(llGetOwner(), note_name);
                
                llInstantMessage(llGetOwner(), "A NoteCard has been sent to you: " + note_name);
                llSay(0, "The Notecard, " + note_name + " has been sent. Thank you.");
                
            
                llRemoveInventory(note_name);
                
                num_notes = llGetInventoryNumber(INVENTORY_NOTECARD);
                
                while(num_notes > 0) // They dropped more than one notecard. Clean it up
                {   
                    note_name = llGetInventoryName(INVENTORY_NOTECARD, 0);
                      
                    llSay(0, "Deleting " + note_name + ". It was not submitted.  Try Dropping one note at a time.");
                    
                    llRemoveInventory(note_name);
                    
                    num_notes = llGetInventoryNumber(INVENTORY_NOTECARD);
                    
                }
                
            }
            
            else //Not a Notecard
            {
               //find out what was dropped and remove it.  
                
                
                list inventory;
                integer num_inv = llGetInventoryNumber(INVENTORY_ALL); // Should be 2
                integer counter = 0;
                while(counter < num_inv)
                {
                    inventory += [llGetInventoryName(INVENTORY_ALL, counter)];
                    counter ++;   
                }
                
                // WHat we expect to find
                list this_script = [llGetScriptName()];
                
                //Delete this script (which belong in the inventory) from the list
                integer index = llListFindList(inventory, this_script);
                inventory = llDeleteSubList(inventory, index, index);
                
                
                index = llGetListLength(inventory);
                
                
                //Just in case they snuck in more than one inventory item
                while (index >= 1)
                {                
                    llSay(0, "That was not a notecard. Removing " + llList2String(inventory, 0));
                    llRemoveInventory(llList2String(inventory, 0));
                    inventory = llDeleteSubList(inventory, 0, 0);
                    index = llGetListLength(inventory);   
                } 
            }
        }
    }
    
    on_rez(integer start_param)
    {
        llResetScript();
    }
}
