<?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"
		 creationComplete="init()">

	<!-- Metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	
	<fx:Metadata>
		[Event(name="vehicleRequestEvent", type="events.VehicleRequestEvent")]
	</fx:Metadata>
	
	<!-- Styles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	
	
	
	<!-- Script ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	
	<fx:Script>
		<![CDATA[
			
			// import statements ----------------------------------------
			
			import events.VehicleRequestEvent;
			
			import mx.collections.ArrayCollection;
			import mx.controls.Alert;
			import mx.events.CalendarLayoutChangeEvent;
			
			import valueObjects.VehicleRequest;
			
			// variable declarations ------------------------------------
			
			[Bindable]
			public var employees:ArrayCollection;
			
			// getter/setters -------------------------------------------
			
			
			// helper methods -------------------------------------------
			
			
			// event handlers -------------------------------------------
			
			private function dateChangeHandler(event:CalendarLayoutChangeEvent):void
			{
				Alert.show('You have selected ' + event.target.selectedDate.toDateString());
				
				if ((event.target.id == "returnDate") && (pickupDate.selectedDate > returnDate.selectedDate)) 
				{
					Alert.show("Pickup date must be scheduled before return date.");
				}
				
				if ((event.target.id == "pickupDate") && (pickupDate.selectedDate > returnDate.selectedDate) && (returnDate.selectedDate != null)) 
				{
					Alert.show("Pickup date must be scheduled before return date.")
				}
				
			}
			
			private function init():void
			{
				pickupDate.addEventListener(CalendarLayoutChangeEvent.CHANGE, dateChangeHandler);
				returnDate.addEventListener(CalendarLayoutChangeEvent.CHANGE, dateChangeHandler);
			}
			
			protected function submitButton_clickHandler(event:MouseEvent):void
			{
				if (dropDownList.selectedItem == null) 
				{
					Alert.show("You must select an employee.");
				}
				else
				{
					if (returnDate.selectedDate == null || pickupDate.selectedDate == null)
					{
						Alert.show("You must select a start and ending request date.");
					}
					else
					{
						var vehicleRequestData:VehicleRequest = new VehicleRequest();
						vehicleRequestData.id = dropDownList.selectedItem.id;
						vehicleRequestData.phone = phone.text;
						vehicleRequestData.pickupDate = pickupDate.selectedDate.toDateString();
						vehicleRequestData.returnDate = returnDate.selectedDate.toDateString();
						
						var eventObject:VehicleRequestEvent = new VehicleRequestEvent("vehicleRequestEvent", vehicleRequestData);
						dispatchEvent(eventObject);
					}
				}
			}
			
		]]>
	</fx:Script>
	
	<!-- Declarations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	
	<!-- UI components ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

	<s:Form x="10" y="70">
		
		<s:FormItem label="Employee:">
			<s:DropDownList id="dropDownList"
							dataProvider="{employees}"
							labelField="lastName"/>
		</s:FormItem>
		
		<s:FormItem label="Office Phone:">
			<s:TextInput id="phone"
						 text="{dropDownList.selectedItem.phone}"/>
		</s:FormItem>
		
		<s:FormItem label="Mobile Phone:">
			<s:TextInput id="mobilePhone"/>
		</s:FormItem>
		
		<s:FormHeading label="Dates Requested"/>
		
		<s:FormItem label="Pickup Date:">
			<mx:DateChooser id="pickupDate"/>
		</s:FormItem>
		
		<s:FormItem label="Return Date:">
			<mx:DateChooser id="returnDate"/>
		</s:FormItem>
		
		<s:FormItem>
			<s:Button id="submitButton" 
					  label="Submit Request"
					  click="submitButton_clickHandler(event)"/>
		</s:FormItem>
		
	</s:Form>
	
</s:Group>
