<?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 ' + requestDateFormatter.format(event.target.selectedDate));
				
				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);
					}
				}
			}
			
			protected function mobilePhone_focusOutHandler(event:FocusEvent):void
			{
				mobilePhone.text = phoneFieldFormatter.format(mobilePhone.text);
				
				if (phoneFieldFormatter.error) 
				{
					Alert.show("Phone format error: " + phoneFieldFormatter.error);	
				}
			}
			
		]]>
	</fx:Script>
	
	<!-- Declarations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	
	<fx:Declarations>
		
		<s:DateTimeFormatter id="requestDateFormatter"
							 dateTimePattern="MM-dd-yyyy"/>
		
		<mx:PhoneFormatter id="phoneFieldFormatter"
						   formatString="(###) ###-####"/>
		
	</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"
						 focusOut="mobilePhone_focusOutHandler(event)"/>
		</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>
