/*
 *  delegate.jc
 *
 *  This script demonstrates "delegates", which are function variables in JewelScript.
 *
 *  Delegates can be used to define variables that can store references to global functions,
 *  and even instance member functions of a class. If you take a reference of an instance
 *  member function, JewelScript stores a reference to the function AND a reference to the
 *  instance of the class in the variable. For example:
 *
 *  Foo foo = new Foo();
 *  MyDelegate myDel = foo.HandleEvent;     // stores 'foo' and 'HandleEvent' in myDel
 *  myDel("open");                          // calls foo.HandleEvent("open");
 */

// import and use stdlib
import stdlib;
using stdlib;

/*  delegate Comparator
 *
 *  This defines a delegate type for functions or methods that compare two string constants and return an integer result.
 *  Functions or methods that match this delegate's signature can be passed into the Sort() function.
 */

delegate int Comparator(const string, const string);

/*  function Smaller
 *
 *  This function returns true if the length of 'b' is smaller than 'a'.
 */

function int Smaller(const string a, const string b)
{
    return b.length < a.length;
}

/*  function Bigger
 *
 *  This function returns true if the length of 'b' is bigger than 'a'.
 */

function int Bigger(const string a, const string b)
{
    return b.length > a.length;
}

/*  function Sort
 *
 *  This function sorts an array of strings according to the given Comparator function.
 */

function Sort( string[] arr, Comparator fn )
{
    for( int i = 1; i < arr.length; i++ )
    {
        for( int j = i; j >= 1; j-- )
        {
            if( fn(arr[j-1], arr[j]) )  // call our delegate to compare both elements
            {
                arr.swap(j-1, j);
            }
            else
            {
                break;
            }
        }
    }
    for( int i = 0; i < arr.length; i++ )
    {
        printf("%2d: %s\n", {i, arr[i]});
    }
    print("\n");
}

/*
 *  function main
 *
 *  This is the main entry-point function of the script
 */

function string main(const string[] args)
{
    string[] names = { "Judy", "Christopher", "Helen", "James", "Sandra", "Rick", "Elisabeth", "Johnboy" };

    Sort( names, Smaller );     // pass our array and the Smaller function to the Sort function
    Sort( names, Bigger );      // pass our array and the Bigger function to the Sort function

    return "";
}