<?xml version="1.0" encoding="utf-8"?>
<!--

  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

-->
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
		   xmlns:s="library://ns.adobe.com/flex/spark" 
		   xmlns:mx="library://ns.adobe.com/flex/mx"
		   preinitialize="preInit()">
	<!--
	This is the base class for all of the monitors. The idea behind monitors is to provide plugable testing: 
	Essentially, monitors do the actual operations of detecting whether or not something is behaving based on a pre-
	defined criteria (e.g. symmetric change) without actually interfacing with the thing being tested directly. This
	enables them to be swapped in at runtime by Mustella without needing to create seperate files for each test.
	-->
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayList;
			import mx.core.IFlexDisplayObject;
			import mx.events.CloseEvent;
			import mx.events.EffectEvent;
			import mx.events.FlexEvent;
			
			protected var timer:Timer;
			public var start:int;
			public var stop:int;
			public var end:int;
			public var repeat:int;
			
			[Bindable]
			public var initialValues:Vector.<Number>;
			protected var initialUpdates:Vector.<Number>;
			
			[Bindable]
			public var returnValues:Vector.<Number>;
			protected var returnUpdates:Vector.<Number>;
			
			[Bindable]
			public var isReturn:Boolean;
			
			[Bindable]
			public var valueFunction:Function;
			[Bindable]
			public var target:Object;
			[Bindable]
			public var passed:Boolean;
			[Bindable]
			public var error:String;
			
			public function preInit():void{
				timer = new Timer(20);
				initialValues = new Vector.<Number>();
				initialUpdates = new Vector.<Number>();
				
				returnValues = new Vector.<Number>();
				returnUpdates = new Vector.<Number>();
				
				isReturn = false;
				passed = true;
			}
			
			public function effectStart(event:EffectEvent):void{
				timer.start();
				start = timer.currentCount * 20;
			}
			
			public function effectStop(event:EffectEvent):void{
				stop = timer.currentCount * 20;
				timer.stop();
			}
			
			public function effectUpdate(event:EffectEvent):void{
				if(isReturn){
					returnValues.push(valueFunction.call(target) as Number);
					returnUpdates.push((timer.currentCount * 20) - start);
				}else{
					initialValues.push(valueFunction.call(target) as Number);
					initialUpdates.push((timer.currentCount * 20) - start);
				}
			}
			
			public function effectEnd(event:EffectEvent):void{
				end = timer.currentCount * 20;
				timer.stop();
			}
			
			public function effectRepeat(event:EffectEvent):void{
				repeat++;
			}
			
			public function resetMonitors():void {
				start = 0;
				stop = 0;
				repeat = 0;
				end = 0;
			} 
			
			protected function computeDeltas(vector:Vector.<Number>):Vector.<Number> {
				var diff:Vector.<Number> = new Vector.<Number>();
				var prev:Number = Number.NaN;
				for each(var n:Number in vector){
					if(!isNaN(prev)){
						diff.push(Math.abs(n - prev));
					}
					prev = n;
				}
				
				return diff;
			}
			
			protected function computeRates(values:Vector.<Number>,times:Vector.<Number>):Vector.<Number> {
				var rates:Vector.<Number> = new Vector.<Number>();
				var deltaV:Vector.<Number> = computeDeltas(values);
				var deltaT:Vector.<Number> = computeDeltas(times);
				
				for(var i:int = 0; i < deltaV.length; i++){
					var deltaVNum:Number = deltaV.pop();
					var deltaTNum:Number = deltaT.pop();
					
					if(deltaTNum != 0){
						if(deltaVNum == 0){
							rates.push(0);
						}else{
							rates.push(deltaVNum / deltaTNum);
						}
					}
				}
				
				return rates.reverse();
			}
			
			public function check():void {
				if(Math.abs(initialValues[0] - initialValues[initialValues.length - 1]) < 0.5){
					passed = false;
					error = "Initial value is not substantially different from end value in the first transition. " + initialValues[0] + " vs. " + initialValues[initialValues.length - 1];
					trace("Monitor: " + error);
				}
			}
		]]>
	</fx:Script>
	<s:Label id="readout" text="Passed: {passed}"/>
</s:Group>