use Test::More;

use LWP::UserAgent;


my $url='http://closure-compiler.appspot.com/';
diag('testing your internet connection');
my $ua = LWP::UserAgent->new();
   $ua->timeout(10);
my $r = $ua->get($url);
   $r->code == 200 ? plan tests    => 1
                   : plan skip_all => "$url not reachable. The servir or your internet connection may be down.";

diag('internect connection looks good');

use Javascript::Closure qw(minify);

my $javascript_before=<<'JS_BEFORE';
Event.Publisher = Class.create();
Object.extend( Event.Publisher, {
	_ls_event_targets: null,
	
	_event_source_id: null,
	
	_fl_trace_events: false,
	
	getEventSourceId: function() {
		if ( typeof this._event_source_id == 'function' )
			return this._event_source_id();
		else
			return this._event_source_id;
	},
	
	getEventTarget: function( event_name ) {
		if ( ! this._ls_event_targets )
			this._ls_event_targets = new Array();
		
		if ( ! this._ls_event_targets[ event_name ] )
			document.body.appendChild(
				this._ls_event_targets[ event_name ] = document.createElement( 'A' )
			);
		
		return this._ls_event_targets[ event_name ];
	},
	
	addEventListener: function( event_name, callback_func, capturing ) {
		var targ = this.getEventTarget( event_name );
		
		Event.observe( targ, 'click', callback_func, capturing );
		
		if ( this._fl_trace_events ) {
			var data =  {
				publisher: this.getEventSourceId(),
				event_name: event_name,
				listener: callback_func,
				capturing: capturing,
				event_source_proxy: targ
			};
			
			this.dispatchEvent( 'eventListenerAdded', data, true, true );
		}
	},
	
	removeEventListener: function( event_name, callback_func, capturing ) {
		var targ = this.getEventTarget( event_name );
		
		Event.stopObserving( targ, 'click', callback_func, capturing );
		
		if ( this._fl_trace_events ) {
			var data =  {
				publisher: this.getEventSourceId(),
				event_name: event_name,
				listener: callback_func,
				capturing: capturing,
				event_source_proxy: targ
			};
			
			this.dispatchEvent( 'eventListenerRemoved', data, true, true );
		}
	},
	
	dispatchEvent: function( event_name, data, can_bubble, cancelable ) {
		var targ = this.getEventTarget( event_name );
		var event_data = {
			event_name: event_name,
			event_target: this,
			data: data ? data : null
		};
		
		if ( ! can_bubble ) can_bubble = false;
		if ( ! cancelable ) cancelable = false;
		
		var event = Event.create( event_data, can_bubble, cancelable, true, targ );
		
		if ( this._fl_trace_events ) {
			if ( event_name.match( /event(?:ListenerAdded|ListenerRemoved|Dispatched|Received)/ ) )
				return;
			
			var data =  {
				publisher: this.getEventSourceId(),
				event_name: event_name,
				event_data: event_data,
				can_bubble: can_bubble,
				cancelable: cancelable,
				event_source_proxy: targ,
				result: event
			};
			
			this.dispatchEvent( 'eventDispatched', data, true, true );
		}
	},
	
	toggleEventsTrace: function() {
		var trace = Event.Tracer.findTracer();
		
		if ( ! trace || ! this._fl_trace_events ) {
			this._fl_trace_events = true;
			
			trace = Event.Tracer.startTrace();
			
			trace.registerPublisher( this );
		}
		else {
			this._fl_trace_events = false;
			
			if ( trace )
				trace.unregisterPublisher( this );
		}
		
		return this._fl_trace_events;
	},
	
	isEventsTraceActive: function() {
		return this._fl_trace_events;
	}
} );

/**
  *  MIX IN: Event.Listener
  *  
  *  Description:
  *    easily add support for receiving totally custom events
  *    (to any object or class) by mixing this class into
  *    your own
  *  
  *  Usage:
  *	   To receive custom events:
  *      1. mix this class with your own via
  *         Object.extend( [your class or prototype], EventListener )
  *      2. listen for events by calling (from your object)
  *         this.listen()
  *         (see params for this.listen, below)
  **/
Event.Listener = Class.create();
Object.extend( Event.Listener,
{
	_listens: null,
	
	getEventHandlerName: function( event_name ) {
		var onEvent_name = event_name.split( /[ _]/ ).join( '-' ).camelize();
		
		return "on" + onEvent_name.charAt( 0 ).toUpperCase() + onEvent_name.substr( 1 );
	},
	
	/**
	  *	 Params:
      *    event_source [object]:
      *      the object which will generate the events, and which implements (or
      *      mixes in) the Event.Publisher interface (we need addEventListener)
      *    event_name [string]:
      *      the name of the event for which your object will listen
      *    use_capture [boolean]:
      *      standard DOM Event API param
      *    onEvent_name [string]:
      *      the name of the method in your object which will be called when the
      *      event is received if you omit this param, listen will look for a
      *      function named with the CapitalizedCamelCased name of the event with
      *      "on" at the front. So, if the event is named "message_received",
      *      we'll look for a function named "onMessageReceived" You can override
      *      this behavior by overriding getEventHandlerName in your object.
	  **/
	listenForEvent: function( event_source, event_name, use_capture, onEvent_name ) {
		if ( ! onEvent_name )
			onEvent_name = this.getEventHandlerName( event_name );
		
		if ( ! this._listens ) this._listens = new Array();
		
		//added this in to allow for anonymous function handling of an event
		var eventHandler = this[onEvent_name];
		
		if(typeof(onEvent_name) == 'function') {
			eventHandler = onEvent_name;
		}
		
		var cb = eventHandler.bindAsEventListener( this );
		this._listens.push( [ event_source, event_name, use_capture, onEvent_name, cb ] )
		
		event_source.addEventListener( event_name, cb, use_capture );
	},
	
	stopListeningForEvent: function( event_source, event_name, use_capture, onEvent_name ) {
		if ( ! this._listens ) return false;
		
		if ( ! onEvent_name )
			onEvent_name = this.getEventHandlerName( event_name );
		
		var ix_item = -1;
		var ls = this._listens.detect( function( val, ix ) {
			if ( ( val[ 0 ] == event_source )
			  && ( val[ 1 ] == event_name )
			  && ( val[ 2 ] == use_capture )
			  && ( val[ 3 ] == onEvent_name ) ) {
				ix_item = ix;
				return true;
			}
		} );
		
		if ( ix_item >= 0 ) {
			this._listens.splice( ix_item, 1 );
			
			event_source.removeEventListener( event_name, ls[ 4 ], use_capture );
			
			return true;
		}
		
		return false;
	}
} );

/**
  *  Extensions to Prototype's Event object,
  *  for cleanly creating and dispatching custom events
  *  
  *  Called from Event.Publisher
  **/
Object.extend( Event,
{
	create: function( event_data, can_bubble, cancelable, fl_dispatch, target ) {
		var event;
		
		if ( document.createEvent ) {  // gecko, safari
			if ( ! can_bubble ) can_bubble = false;
			if ( ! cancelable ) cancelable = false;
			
			if ( /Konqueror|Safari|KHTML/.test( navigator.userAgent ) ) {
				event = document.createEvent( 'HTMLEvents' )
				
				event.initEvent( 'click', can_bubble, cancelable );
			}
			else {  // gecko uses MouseEvents
				event = document.createEvent( 'MouseEvents' )
				
				event.initMouseEvent( "click", can_bubble, cancelable,
				                      window, 0, 0, 0, 0, 0,
				                      false, false, false, false, 0, null );
			}
		}
		else {  // msie
			event = document.createEventObject();
			event.event_type = 'onclick';
		}
		
		event.event_data = event_data;
		
		if ( fl_dispatch )
			Event.dispatch( target, event );
		
		return event;
	},
	
	dispatch: function( target, event ) {
		if ( document.createEvent )
			return target.dispatchEvent( event );
		else
			return target.fireEvent( ( typeof( event.event_type ) != "undefined" ) ? event.event_type : 'onclick', event );
	}
} );


JS_BEFORE

my $javascript_after=<<'JAVASCRIPT_AFTER';
Event.Publisher=Class.create();
Object.extend(Event.Publisher,{_ls_event_targets:null,_event_source_id:null,_fl_trace_events:false,getEventSourceId:function(){if(typeof this._event_source_id=="function")return this._event_source_id();else return this._event_source_id},getEventTarget:function(event_name){if(!this._ls_event_targets)this._ls_event_targets=new Array;if(!this._ls_event_targets[event_name])document.body.appendChild(this._ls_event_targets[event_name]=document.createElement("A"));return this._ls_event_targets[event_name]},addEventListener:function(event_name,
callback_func,capturing){var targ=this.getEventTarget(event_name);Event.observe(targ,"click",callback_func,capturing);if(this._fl_trace_events){var data={publisher:this.getEventSourceId(),event_name:event_name,listener:callback_func,capturing:capturing,event_source_proxy:targ};this.dispatchEvent("eventListenerAdded",data,true,true)}},removeEventListener:function(event_name,callback_func,capturing){var targ=this.getEventTarget(event_name);Event.stopObserving(targ,"click",callback_func,capturing);if(this._fl_trace_events){var data=
{publisher:this.getEventSourceId(),event_name:event_name,listener:callback_func,capturing:capturing,event_source_proxy:targ};this.dispatchEvent("eventListenerRemoved",data,true,true)}},dispatchEvent:function(event_name,data,can_bubble,cancelable){var targ=this.getEventTarget(event_name);var event_data={event_name:event_name,event_target:this,data:data?data:null};if(!can_bubble)can_bubble=false;if(!cancelable)cancelable=false;var event=Event.create(event_data,can_bubble,cancelable,true,targ);if(this._fl_trace_events){if(event_name.match(/event(?:ListenerAdded|ListenerRemoved|Dispatched|Received)/))return;
var data={publisher:this.getEventSourceId(),event_name:event_name,event_data:event_data,can_bubble:can_bubble,cancelable:cancelable,event_source_proxy:targ,result:event};this.dispatchEvent("eventDispatched",data,true,true)}},toggleEventsTrace:function(){var trace=Event.Tracer.findTracer();if(!trace||!this._fl_trace_events){this._fl_trace_events=true;trace=Event.Tracer.startTrace();trace.registerPublisher(this)}else{this._fl_trace_events=false;if(trace)trace.unregisterPublisher(this)}return this._fl_trace_events},
isEventsTraceActive:function(){return this._fl_trace_events}});Event.Listener=Class.create();
Object.extend(Event.Listener,{_listens:null,getEventHandlerName:function(event_name){var onEvent_name=event_name.split(/[ _]/).join("-").camelize();return"on"+onEvent_name.charAt(0).toUpperCase()+onEvent_name.substr(1)},listenForEvent:function(event_source,event_name,use_capture,onEvent_name){if(!onEvent_name)onEvent_name=this.getEventHandlerName(event_name);if(!this._listens)this._listens=new Array;var eventHandler=this[onEvent_name];if(typeof onEvent_name=="function")eventHandler=onEvent_name;var cb=
eventHandler.bindAsEventListener(this);this._listens.push([event_source,event_name,use_capture,onEvent_name,cb]);event_source.addEventListener(event_name,cb,use_capture)},stopListeningForEvent:function(event_source,event_name,use_capture,onEvent_name){if(!this._listens)return false;if(!onEvent_name)onEvent_name=this.getEventHandlerName(event_name);var ix_item=-1;var ls=this._listens.detect(function(val,ix){if(val[0]==event_source&&val[1]==event_name&&val[2]==use_capture&&val[3]==onEvent_name){ix_item=
ix;return true}});if(ix_item>=0){this._listens.splice(ix_item,1);event_source.removeEventListener(event_name,ls[4],use_capture);return true}return false}});
Object.extend(Event,{create:function(event_data,can_bubble,cancelable,fl_dispatch,target){var event;if(document.createEvent){if(!can_bubble)can_bubble=false;if(!cancelable)cancelable=false;if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){event=document.createEvent("HTMLEvents");event.initEvent("click",can_bubble,cancelable)}else{event=document.createEvent("MouseEvents");event.initMouseEvent("click",can_bubble,cancelable,window,0,0,0,0,0,false,false,false,false,0,null)}}else{event=document.createEventObject();
event.event_type="onclick"}event.event_data=event_data;if(fl_dispatch)Event.dispatch(target,event);return event},dispatch:function(target,event){if(document.createEvent)return target.dispatchEvent(event);else return target.fireEvent(typeof event.event_type!="undefined"?event.event_type:"onclick",event)}});
JAVASCRIPT_AFTER

my $ret =  minify(input=>$javascript_before);
diag('testing the default compression settings with a scalar input => $js');
ok($ret eq $javascript_after,'Javascript code was compressed properly.');
