<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" creationPolicy="all"
    backgroundGradientColors="[#FFFFFF, #FFFFFF]" verticalGap="20" horizontalAlign="left"
    creationComplete="initApp()" viewSourceURL="srcview/index.html">

    <mx:states>
        <mx:State name="inNewSession">
            <mx:RemoveChild target="{collab}"/>
            <mx:AddChild position="lastChild">
                <mx:VBox>
                    <mx:Label text="You have started a new collaboration session. The collaboration session id is:"/>    
                    <mx:HBox verticalAlign="middle">
                        <mx:Text text="{sessionId}"/>    
                        <mx:Button label="Copy to Clipboard" click="System.setClipboard(sessionId)"/>
                    </mx:HBox>
                    <mx:Label text="Provide this session id to people you want to collaborate with."/>    
                </mx:VBox>
            </mx:AddChild>
        </mx:State>
        <mx:State name="inSession">
            <mx:RemoveChild target="{collab}"/>
            <mx:AddChild position="lastChild">
                <mx:Text text="You have joined a collaboration with the following session id: {sessionId}"/>
            </mx:AddChild>
        </mx:State>
    </mx:states>

    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.utils.UIDUtil;
            import mx.events.CollectionEvent;
            import mx.events.CollectionEventKind;
            import mx.events.PropertyChangeEvent;
            import mx.events.IndexChangedEvent;
            import mx.messaging.messages.AsyncMessage;
            import mx.messaging.events.MessageEvent;

            [Bindable]
            private var sessionId:String; // collaboration session id

            private var userId:String; // Unique user id

            private var isSessionInitiator:Boolean = false;

            private function initApp():void
            {
                 userId = UIDUtil.createUID();    // Generate unique session id
            }

            private function accordionChange(event:IndexChangedEvent):void
            {
                sendMessage("accordionChange", {selectedIndex: event.newIndex});
            }

            private function propertyChangeHandler(event:PropertyChangeEvent):void
            {
                sendMessage("propertyChange", {property: event.property, value: event.newValue});
            }

            private function job_propertyChangeHandler(event:PropertyChangeEvent):void
            {
                sendMessage("job_propertyChange", {index: mortgageApplication.jobList.getItemIndex(event.source), property: event.property, value: event.newValue});
            }

            private function jobListChangeHandler(event:CollectionEvent):void
            {
                if (event.kind == CollectionEventKind.ADD)
                {
                    mortgageApplication.jobList.getItemAt(event.location).addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, job_propertyChangeHandler);
                    sendMessage("jobList_add");
                }
                else if (event.kind == CollectionEventKind.REMOVE)
                {
                    sendMessage("jobList_remove", {location: event.location});
                }
            }

            private function messageHandler(event:MessageEvent):void
            {
                var remoteUserId:String = event.message.body.userId;
                // If the message was sent by this user, don't handle it
                if (remoteUserId == userId)
                {
                    return;
                }            

                var data:Object = event.message.body.data
                switch (event.message.body.action)
                {
                    case "accordionChange":
                        accordion.selectedIndex = data.selectedIndex;
                        return;
                    case "propertyChange":
                        mortgageApplication.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler);
                        mortgageApplication[data.property] = data.value; 
                        mortgageApplication.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler);
                        return;
                    case "job_propertyChange":
                        var job:Job = mortgageApplication.jobList.getItemAt(data.index) as Job;
                        job.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, job_propertyChangeHandler);
                        job[data.property] = data.value; 
                        job.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, job_propertyChangeHandler);
                        return;
                    case "jobList_add":
                        mortgageApplication.jobList.removeEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler);
                        mortgageApplication.jobList.addItem(new Job());
                        mortgageApplication.jobList.addEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler);
                        return;
                    case "jobList_remove":
                        mortgageApplication.jobList.removeEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler);
                        mortgageApplication.jobList.removeItemAt(data.location);
                        mortgageApplication.jobList.addEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler);
                        return;
                    case "joining":
                        if (isSessionInitiator)
                        {
                            sendMessage("syncing", mortgageApplication, event.message.body.userId);
                        }
                        return;
                    case "syncing":
                        mortgageApplication.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler);
                        mortgageApplication.jobList.removeEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler);
                        typeObject(data, mortgageApplication);
                        mortgageApplication.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler);
                        mortgageApplication.jobList.addEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler);
                        return;
                }
            }
            
            private function submitApplication():void
            {
                Alert.show("Your application has been submitted", "Thank You");
            }

            private function createSession():void
            {
                isSessionInitiator = true;
                sessionId = UIDUtil.createUID();
                subscribe();
                currentState = "inNewSession"
            }

            private function joinSession():void
            {
                sessionId = tiSessionId.text;
                subscribe();
                currentState = "inSession"
            }

            private function subscribe():void
            {
                consumer.selector = "sessionId='" + sessionId + "' AND (toUserId='*' OR toUserId='" + userId + "')";
                consumer.subscribe();
                mortgageApplication.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler);
                mortgageApplication.jobList.addEventListener(CollectionEvent.COLLECTION_CHANGE, jobListChangeHandler); 
                sendMessage("joining");
            }
            
            private function sendMessage(action:String, data:Object = null, toUserId:String = "*"):void
            {
                var message:AsyncMessage = new AsyncMessage();
                message.headers["sessionId"] = sessionId;
                message.headers["toUserId"] = toUserId;
                message.body.userId = userId;
                message.body.action = action;
                message.body.data = data;
                producer.send(message);
            }        
            
            private function typeObject(o:Object, ma:MortgageApplication):void
            {
                ma.address = o.address;
                ma.city = o.city;
                ma.closingDate = o.closingDate;
                ma.downPayment = o.downPayment;
                ma.email = o.email;
                ma.firstName = o.firstName;
                ma.lastName = o.lastName;
                ma.mobilePhone = o.mobilePhone;
                ma.notify = o.notify;
                ma.phone = o.phone;
                ma.salePrice = o.salePrice;
                ma.singleFamily = o.singleFamily;
                ma.ssn = o.ssn;
                ma.state = o.state;
                ma.usCitizen = o.usCitizen;
                ma.zip = o.zip;
                ma.jobList = new ArrayCollection();
                for (var i:int; i<o.jobList.length; i++)
                {
                    var j:Object = o.jobList.getItemAt(i);
                    var job:Job = new Job();
                    job.company = j.company;
                    job.startDate = j.startDate;
                    job.endDate = j.endDate;
                    job.salary = j.salary;
                    ma.jobList.addItem(job);
                    job.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, job_propertyChangeHandler);
                }
            }    

        ]]>
    </mx:Script>

    <mx:Style source="main.css"/>
    
    <MortgageApplication id="mortgageApplication"/>
    
    <mx:Producer id="producer" destination="mortgage"/>
    <mx:Consumer id="consumer" destination="mortgage" message="messageHandler(event)"/>
    
    <mx:Panel id="panel" title="My Mortgage Application" backgroundImage="img/background.jpg" backgroundAlpha=".8">

        <mx:Accordion id="accordion" width="700" height="520" change="accordionChange(event)">

            <ApplicantView id="applicantView" label="Applicant Information" mortgageApplication="{mortgageApplication}"/>
    
            <PropertyView id="property" label="Property Information" mortgageApplication="{mortgageApplication}"/>

            <MortgageView id="info" label="Mortgage Information" mortgageApplication="{mortgageApplication}"/>
    
            <EmploymentView id="employment" label="Employment History"  mortgageApplication="{mortgageApplication}"/>
    
        </mx:Accordion>

        <mx:ControlBar bottom="20">
            <mx:Button label="Submit Application" icon="@Embed('img/icon_save.png')" click="submitApplication()"/>
        </mx:ControlBar>        

    </mx:Panel>    
    
    <mx:HBox id="collab">
        <mx:VBox>
            <mx:Label text="Create new collaboration session" styleName="title"/>
            <mx:Button label="Create Session" click="createSession()"/>
        </mx:VBox>
        <mx:Label text="or" width="100" textAlign="center"/>
        <mx:VBox verticalGap="0">
            <mx:Label text="Join existing collaboration session" styleName="title"/>
            <mx:Label text="Enter a collaboration session id:"/>
            <mx:TextInput id="tiSessionId" width="260"/>
            <mx:Spacer height="4"/>
            <mx:Button label="Join Session" click="joinSession()"/>
        </mx:VBox>
    </mx:HBox>

</mx:Application>