//
//              Three approaches to component event handling
//              http://www.bdontwerp.nl/articles/component_eventhandling.html
//

class com.jgraup.utils.jgDelegate
{

        /*

        *
        *
        *
        *
                        @parameter s = Scope to run function
                        @paramater f = Function to run.
                        ----------------------------
                        @paramater a = PROXY arguments without s & f to strore in function
                        @paramater na = New arguments & a
                        ----------------------------
                        @paramater return = Scoped Function
        *
        *
        *
        *

        //
        //
        //              function o (){ trace( arguments.join(' ') )}; // output of function - traces the arguments passed
        //
        //

        */


        public function jgDelegate () {}






        public static function create (s:Object, func:Function):Function
        {

                //              SCOPED FUNCTION
                //              ______________________________
                //
                //              dFunc = jgDelegate.create ( this, o );
                //              dFunc ( 'Hello World' ); // Hello World

                return function():Void{ func.apply(s, arguments);  };
        }






        public static function proxy (s:Object, func:Function):Function
        {

                //              SCOPED FUNCTION WITH STORED PRAMS
                //              ______________________________
                //
                //              dFunc = jgDelegate.proxy ( this, o, 'Hello World' );
                //              dFunc ( "Won't take new args" ); // Hello World

                var a:Array = arguments.slice(2, arguments.length);
                return function ():Void { func.apply(s, a);  };
        }





        public static function proxyAFTER (s:Object, func:Function):Function
        {

                //              SCOPED FUNCTION TO RUN RUNTIME ARGUMENTS WITH PROXY ARGUMENTS APPENDED TO THE END
                //              ______________________________
                //
                //              dFunc = jgDelegate.proxyAFTER ( this, o, 'World.' );
                //              dFunc ( 'Hello' ); // Hello World

                var a:Array = arguments.slice(2, arguments.length);
                return function ():Void { func.apply(s, arguments.concat(a));        };
        }

        public static function proxyBEFORE (s:Object, func:Function):Function
        {

                //              SCOPED FUNCTION TO RUN PROXY ARGUMENTS WITH RUNTIME ARGUMENTS APPENDED TO THE END
                //              ______________________________
                //
                //              dFunc = jgDelegate.proxyBEFORE ( this, o, 'Hello' );
                //              dFunc ( 'World.' ); // Hello World.

                var a:Array = arguments.slice(2, arguments.length);
                return function ():Void { func.apply(s, a.concat(arguments));        };
        }





        public static function proxyRETURN (s:Object, func:Function):Function
        {

                //              SCOPED FUNCTION TO RETURN VALUE TO THE SECOND PROXY FUNCTION
                //              ______________________________
                //
                //              f1 = function ( v ) { return (v + 2) };
                //              f2 = function ( v ) { trace ( 'sum = ' + (v + 2) ) };
                //              dFunc = jgDelegate.proxyRETURN ( this, f1, create ( this, f2 ) );
                //              dFunc ( 2 ); // sum = 6

                var a:Array = arguments.slice(2, arguments.length);
                var returnFunction = a[0];
                return function ():Void { returnFunction( func.apply(s, arguments ) ); };
        }





        public static function proxyOVERWRITTEN (s:Object, func:Function):Function
        {

                //              ARGUMENTS OVERRIDE PROXY ARGUMENTS
                //              ______________________________
                //
                //              dFunc = jgDelegate.proxyOVERWRITTEN ( this, o, 'Hello', 'World' );
                //              dFunc ( ); // Hello World
                //              dFunc ( 'GoodBye' ); // GoodBye World
                //              dFunc ( 'GoodBye', 'Amigo' ); // GoodBye Amigo

                var a:Array = arguments.slice(2, arguments.length);
                return function ():Void { var na:Array = arguments.concat ( a.slice ( arguments.length, a.length ) ); func.apply(s, na);       };
        }

        public static function proxyOVERWRITE (s:Object, func:Function):Function
        {

                //              ARGUMENTS OVERWRITE RUNTIME ARGUMENTS
                //              ______________________________
                //
                //              dFunc = jgDelegate.proxyOVERWRITE ( this, o, 'Hello' );
                //              dFunc ( ); // Hello
                //              dFunc ( 'GoodBye' ); // Hello
                //              dFunc ( 'GoodBye', 'World' ); // Hello World

                var a:Array = arguments.slice(2, arguments.length);
                return function ():Void { a = a.concat( arguments.slice( 0, arguments.length ).slice( a.length, arguments.length ) ); func.apply(s, a); };
        }

}