<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    
    layout="vertical"
    horizontalAlign="left"
    
    width="100%"
    height="100%"
    
    creationComplete="onCreationComplete(event)" 
    
    viewSourceURL="srcview/index.html"
>
       
       <mx:Script>
              <![CDATA[
                  import mx.binding.utils.BindingUtils;
                   
            ///////////////////////////
                 // IMPORTS        ////
            ///////////////////////////
                   
                import mx.messaging.Channel;
                  import mx.messaging.events.ChannelEvent;
                  import flash.net.registerClassAlias;
                  import mx.rpc.remoting.mxml.RemoteObject;
                  import weborb.messaging.WeborbProducer;
                  import mx.messaging.messages.AsyncMessage;
                  import mx.messaging.ChannelSet;
                  import weborb.messaging.WeborbMessagingChannel;
                  import weborb.messaging.WeborbConsumer;
                  import mx.controls.Alert;
                  import mx.rpc.events.FaultEvent;
                  import mx.rpc.events.ResultEvent;
                  import mx.messaging.events.MessageFaultEvent;
                  import mx.messaging.events.MessageAckEvent;
                  import mx.messaging.events.MessageEvent;
                  import mx.messaging.events.ChannelFaultEvent;
                  import mx.events.FlexEvent;
                   
            
            /////////////////////////////
                 // PUBLIC VARIABLES ////
            /////////////////////////////
            
                 
            
            //////////////////////////////
                 // PRIVATE VARIABLES ////
            //////////////////////////////
            
                [Bindable]
                private var producer:WeborbProducer;
                [Bindable]
                private var consumer:WeborbConsumer;
                [Bindable]
                private var wOrb_nc:NetConnection;
                [Bindable]
                private var channel:WeborbMessagingChannel;
                [Bindable]
                private var cs:ChannelSet; 
                
                [Bindable]
                private var clientId:String;
                
                private const ENDPOINT:String = "http://localhost/johleromsmq/weborb.aspx";
                private const URI:String = "rtmp://localhost:2037/MessagingService";
                private const REMOTEDESTINATION:String = "GenericDestination";
                private const MESSAGINGDESTINATION:String = "JohleroMsmqChannel"
                private const NETCONNECTIONSUCCESS:String = "NetConnection.Connect.Success";
                private const MANAGEMENTSERVICE:String = "Weborb.Management.ManagementService";
                 
                 
            ///////////////////////////
                 // EVENT HANDLERS ////
            ///////////////////////////
                 
                /**
                * Application creationComplet handler
                */ 
                public function onCreationComplete(event:FlexEvent) : void 
                {
                    this.addLogMessage("onCreationComplete");
                    
                    registerClassAlias("Messaging.Messages.LockedAppleMessage", LockedAppleMessage);
                    registerClassAlias("Messaging.Messages.LockedPotatoeMessage", LockedPotatoeMessage);
                    registerClassAlias("Messaging.Messages.LockedBananaMessage", LockedBananaMessage);
                    
                    this.createChannelSet();
                }      
                
                /**
                * Result handler for pinging WebORB
                */ 
                private function onWebOrbPingResult(result:ResultEvent) : void 
                {
                    this.addLogMessage("onWebOrbPingResult(" + result.toString() + ")");
                    
                    this.initConnectionButton.enabled = true;
                    this.makeButtonGreen(this.pingWebOrbButton);
                }
                 
                /**
                * Fault handler for pinging WebORB
                */ 
                private function onWebOrbPingFault(fault:FaultEvent) : void 
                {
                    this.addLogMessage("onWebOrbPingFault(" + fault.toString() + ")");
                    
                    this.makeButtonRed(this.pingWebOrbButton);
                }   
                 
                /**
                * NetConnection Status Event
                */ 
                private function netStatusHandler(event:NetStatusEvent) : void 
                {
                    this.addLogMessage("netStatusHandler(" + event.info.code.toString() + ")");
                    
                    this.netConnectionCheckBox.selected = wOrb_nc.connected;
                        
                    switch (event.info.code) {
                        case NETCONNECTIONSUCCESS:
                            this.makeButtonGreen(this.initConnectionButton);
                            
                            break;     
                        default:
                            this.makeButtonRed(this.initConnectionButton);
                            break;           
                   }
                }
                 
                 
                /**
                * NetConnection security error handler
                */ 
                private function securityErrorHandler(event:SecurityErrorEvent) : void 
                {
                    this.addLogMessage("securityErrorHandler(" + event.toString() + ")");
                    
                    this.makeButtonRed(this.initConnectionButton);
                }      
                 
                /**
                * Channel Message handler
                */ 
                private function onChannelMessage(event:MessageEvent) : void 
                {
                    this.addLogMessage("onChannelMessage(" + event.toString() + ")");
                    
                    if(event.message.body is LockedPotatoeMessage)
                     {
                        this.addLogMessage("LockedPotatoeMessage arrived: " + event.message.body.toString());
                      }
                      else if(event.message.body is LockedBananaMessage)
                     {
                        this.addLogMessage("LockedBananaMessage arrived: " + event.message.body.toString());
                      }
                      else if(event.message.body is LockedAppleMessage)
                     {
                           this.addLogMessage("LockedAppleMessage arrived: " + event.message.body.toString());
                      }
                      else
                      {
                          this.addLogMessage("Unknown Message");
                      }
                }
                 
                /**
                * Channel is connected.
                */
                private function onChannelConnect(event:ChannelEvent) : void
                {
                    this.addLogMessage("onChannelConnect(" + event.toString() + ")");
                    
                    this.channelVBox.setStyle("backgroundColor", 0x3EFA04);
                }
                 
                /**
                * Channel is disconnected.
                */
                private function onChannelDisconnect(event:ChannelEvent) : void
                {
                     this.addLogMessage("onChannelDisconnect(" + event.toString() + ")");
                     
                     this.channelVBox.setStyle("backgroundColor", 0xFF0000);
                }
                 
                /**
                * Fault while connecting.
                */
                private function onChannelFault(event:ChannelEvent) : void
                {
                    this.addLogMessage("onChannelFault(" + event.toString() + ")");
                    
                    this.channelVBox.setStyle("backgroundColor", 0xFF0000);
                }
                 
                /**
                * Channel of Consumer successfully connected.
                */ 
                private function onConsumerMessageAck(event:MessageAckEvent) : void 
                {
                      this.addLogMessage("onConsumerMessageAck(" + event.toString() + ")");
                      
                      this.makeButtonGreen(this.connectConsumerButton);
                }
                 
                /**
                * If Channel of the Consumer can't connect, then this Fault is triggered together
                * with the onChannelFault. I guess behind the screens these two Fault events are the same, or better, 
                * the MessageFaultEvent contains the ChannelEvent from the onChannelFault event.
                */ 
                private function onConsumerMessageFault(event:MessageFaultEvent) : void 
                {
                       this.addLogMessage("onConsumerMessageFault(" + event.toString() + ")");
                       
                       this.makeButtonRed(this.connectConsumerButton);
                }       
                 
                /**
                * Channel of the Producer successfully connected.
                */ 
                private function onProducerMessageAck(event:MessageAckEvent) : void 
                {
                    this.addLogMessage("onProducerMessageAck(" + event.toString() + ")");     
                    
                    this.makeButtonGreen(this.connectProducerButton);
                }
                 
                /**
                * If the Channel of the Producer can't connect, then this Fault is triggered together with the 
                * onChannelFault. I guess behind the screens these two Fault events are the same, or better, 
                * the MessageFaultEvent contains the ChannelEvent from the onChannelFault event.
                */ 
                private function onProducerMessageFault(event:MessageFaultEvent) : void 
                {
                    this.addLogMessage("onProducerMessageFault(" + event.toString() + ")");   
                    
                    this.makeButtonRed(this.connectProducerButton);
                }                
                 
                 
            //////////////////////////////
                 // PRIVATE FUNCTIONS ////
            //////////////////////////////                 
                 
                /**
                * Creates the Channel.
                */ 
                private function createChannelSet() : void
                {
                    this.addLogMessage("createChannelSet()");
                    
                    cs = new ChannelSet();
                    channel = new WeborbMessagingChannel("WebOrbMessagingChannel", URI);
                    channel.addEventListener(MessageEvent.MESSAGE, onChannelMessage);
                    channel.addEventListener(ChannelEvent.CONNECT, onChannelConnect);
                    channel.addEventListener(ChannelEvent.DISCONNECT, onChannelDisconnect);
                    channel.addEventListener(ChannelFaultEvent.FAULT, onChannelFault);
                    cs.addChannel(channel);
                }
                
                /**
                * Pinging WebORB
                */ 
                private function pingWeborb() : void 
                {
                    this.addLogMessage("Pinging WebORB");    
                    
                    var ro:RemoteObject = new RemoteObject(REMOTEDESTINATION);
                    ro.source = MANAGEMENTSERVICE;
                    ro.endpoint = ENDPOINT;
                    ro.ping.addEventListener(ResultEvent.RESULT, onWebOrbPingResult);
                       ro.ping.addEventListener(FaultEvent.FAULT, onWebOrbPingFault);
                    ro.ping();
                }
                 
                /**
                * Initializing connection to receive unique ClientId
                */ 
                private function initConnection() : void
                {
                    this.addLogMessage("InitConnection");    
                    
                    var uri:String = URI;
                    wOrb_nc = new NetConnection();
                    
                    wOrb_nc.client = this;
                    wOrb_nc.objectEncoding = ObjectEncoding.AMF3;          
                    wOrb_nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
                    wOrb_nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);    
                    wOrb_nc.connect( uri, "NetConnection"); 
                }   
                
                /**
                * Disconnecting the InitConnection. After this, other clients will be notified that this 
                * application disconnected. However, the Consumer and Producer will continue to work after
                * this. This is not good behaviour. If NetConnection is disconnected, then the Consumer and Producer
                * should be disconnected as well so that no messages can be delivered or gotten.
                * Some thinking needs to be done concerning this...
                */ 
                private function disconnectInitConnection() : void
                {
                    this.addLogMessage("disconnectInitConnection()");
                    
                    wOrb_nc.close();    
                }
                 
                /**
                * Connecting as a Consumer
                */ 
                private function connectAsConsumer() : void
                {
                    this.addLogMessage("connectAsConsumer()");    
                     
                    consumer = new WeborbConsumer();
                    consumer.channelSet = cs;
                    consumer.destination = MESSAGINGDESTINATION;
                    consumer.subqueue = this.subQueueu.text;
                    consumer.addEventListener(MessageAckEvent.ACKNOWLEDGE, onConsumerMessageAck);
                    consumer.addEventListener(MessageFaultEvent.FAULT, onConsumerMessageFault);
                    consumer.subscribe(this.clientId); 
                }      
                
                /**
                * Disconnecting the client. Actually, the channel is disconnected.
                */
                private function disconnectConsumer() : void
                {
                    this.addLogMessage("disconnectConsumer()");
                    
                    this.consumer.disconnect();    
                }   
                 
                /**
                * Creating the Producer
                */ 
                private function connectAsProducer() : void
                {
                    this.addLogMessage("connectAsProducer()");    
                     
                    producer = new WeborbProducer();
                    producer.channelSet = cs;
                    producer.destination = MESSAGINGDESTINATION;
                    producer.subqueue = this.subQueueu.text;
                    producer.addEventListener(MessageAckEvent.ACKNOWLEDGE, onProducerMessageAck);
                    producer.addEventListener(MessageFaultEvent.FAULT, onProducerMessageFault);
                    producer.producerId = this.clientId;
                    producer.send(new AsyncMessage());
                }
                
                /**
                * Disconnects the producer.
                * This doesn't actually do anything (channel doesn't seem to be disconnected).
                */
                private function disconnectProducer() : void
                {
                    this.addLogMessage("disconnectProducer()");
                    
                    this.producer.disconnect();    
                } 
 
                 /**
                  * Adds a log message to the output panel.
                  */
                 private function addLogMessage(message:String) : void
                 {
                     this.outputPanel.text += message + "\n";    
                 }
                 
                 /**
                  * Sets the background of a button green.
                  */ 
                 private function makeButtonGreen(button:Button) : void
                 {
                     button.setStyle("fillColors", [0x40DE1C, 0x40DE1C]);
                 }  
                 
                 /**
                  * Sets the background of a button red.
                  */
                 private function makeButtonRed(button:Button) : void
                 {
                     button.setStyle("fillColors", [0xFF0000, 0xFF0000]);
                 } 
             
             //////////////////////////////////////
                 // FUNCTIONS CALLED BY SERVER ////
            ///////////////////////////////////////       
                            
                /**
                * Function called by the server to give this client a unique clientId.
                * This id is the id of the NetConnection (Consumer and Producer also get a Id, 
                * but they are not used as the unique id.
                */ 
                public function setClientID( myID:String) : void
                {  
                     this.addLogMessage("SERVER CALL: setClientID(" + myID + ")");
                     
                     this.clientId = myID;      
                }
                 
                /**
                * Function called by server when a client has disconnected.
                * As a result, all locked apples, potatoes or bananas that were locked by this client
                * need to be unlocked.
                */ 
                public function setClientDisconnected( clientID:String ) : void
                { 
                     this.addLogMessage("SERVER CALL: setClientDisconnected(" + clientID + ")");
                }
                 
                /**
                * Function called by server to initialize already locked apples when connecting
                */ 
                public function initLockedAppleMessages(lockedAppleMessages:Array) : void
                {
                     this.addLogMessage("SERVER CALL: initLockedAppleMessages(" + lockedAppleMessages.length + ")");
                }
                 
                /**
                * Function called by server to initialize already locked bananas when connecting
                */ 
                public function initLockedBananaMessages(lockedBananaMessages:Array) : void
                {
                     this.addLogMessage("SERVER CALL: initLockedBananaMessages(" + lockedBananaMessages.length + ")");
                }
                 
                /**
                * Function called by server to initialize already locked potatoes when connecting
                */ 
                public function initLockedPotatoeMessages(lockedPotatoeMessages:Array) : void
                {
                     this.addLogMessage("SERVER CALL: initLockedPotatoeMessages(" + lockedPotatoeMessages.length + ")");
                }
                
                /**
                * Send a locked potatoe message
                */
                private function sendLockedPotatoeMessage() : void
                {
                    this.addLogMessage("sendLockedPotatoeMessage()");
                    
                    var lockedPotatoeMessage:LockedPotatoeMessage = new LockedPotatoeMessage();
                     lockedPotatoeMessage.potatoeId = Math.round(Math.random() * 10000);
                     lockedPotatoeMessage.clientId = this.clientId;
                     lockedPotatoeMessage.locked = true;
                     lockedPotatoeMessage.userId = 1;
                    
                    producer.send(new AsyncMessage(lockedPotatoeMessage));
                }
                
                /**
                * Send a locked apple message
                */
                private function sendLockedAppleMessage() : void
                {
                    this.addLogMessage("sendLockedAppleMessage()");
                    
                    var lockedAppleMessage:LockedAppleMessage = new LockedAppleMessage();
                     lockedAppleMessage.appleId = Math.round(Math.random() * 10000);
                     lockedAppleMessage.clientId = this.clientId;
                     lockedAppleMessage.locked = true;
                     lockedAppleMessage.userId = 1;
                    
                    producer.send(new AsyncMessage(lockedAppleMessage));
                }
                
                /**
                * Send a locked banana message
                */
                private function sendLockedBananaMessage() : void
                {
                    this.addLogMessage("sendLockedBananaMessage()");
                    
                    var lockedBananaMessage:LockedBananaMessage = new LockedBananaMessage();
                     lockedBananaMessage.bananaId = Math.round(Math.random() * 10000);
                     lockedBananaMessage.clientId = this.clientId;
                     lockedBananaMessage.locked = true;
                     lockedBananaMessage.userId = 1;
                    
                    producer.send(new AsyncMessage(lockedBananaMessage));
                }
                 
                /**
                * Send three messages
                */ 
                private function sendApplePotatoeBananaMessage() : void
                {
                     this.addLogMessage("sendApplePotatoeBananaMessage()");
                     
                     sendLockedPotatoeMessage();
                     sendLockedBananaMessage();
                     sendLockedAppleMessage();
                }
              ]]>
        </mx:Script>
            <mx:HBox width="100%">
                <mx:VBox height="100%" width="50%">
                    <mx:Form width="100%" height="100%" borderStyle="solid">
                        <mx:FormHeading label="MSMQ with WebORB"/>
                           <mx:FormItem label="Id Client (provided by NetConnection)">
                               <mx:Label id="clientIdLabel" text="{this.clientId}"/>
                           </mx:FormItem>
                           <mx:FormItem label="SubQueue">
                               <mx:TextInput id="subQueueu" text="JohleroQueue"/>
                           </mx:FormItem>
                           <mx:FormItem label="Connecting">
                               <mx:Button
                                   id="pingWebOrbButton"
                                   label="Pinging WebORB to ensure MessagingServer is started"
                                   click="{pingWeborb()}"
                                     width="100%"
                               />
                               <mx:Button
                                   id="initConnectionButton"
                                   label="Initializing connection to get unique ClientId"
                                   click="{initConnection()}"
                                   enabled="true"
                                    width="100%"
                               />
                               <mx:HBox width="100%">
                                   <mx:VBox 
                                       height="100%" 
                                       horizontalAlign="left" 
                                       borderStyle="solid" borderThickness="3" borderColor="#000000" 
                                       paddingLeft="10" paddingBottom="10" paddingRight="10" paddingTop="10"
                                   >
                                        <mx:Button id="connectConsumerButton"
                                            label="Connect as Consumer to receive the messages"
                                            click="{connectAsConsumer()}"
                                            enabled="true"
                                        />
                                       <mx:Button id="connectProducerButton"
                                           label="Connect as Producer to send the messages"
                                           click="{connectAsProducer()}"
                                           enabled="true"
                                       />
                                   </mx:VBox>
                                   <mx:VBox id="channelVBox" 
                                       height="100%" 
                                       cornerRadius="3" borderStyle="solid" borderThickness="3" borderColor="#000000" 
                                       paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10" 
                                       horizontalAlign="center" verticalAlign="middle"
                                   >
                                       <mx:Label text="Channel" fontSize="20"/>
                                   </mx:VBox>
                               </mx:HBox>
                           </mx:FormItem>
                           <mx:FormItem label="Disconnecting">
                               <mx:Button id="disconnectingNetConnectionButton"
                                   label="Disconnecting NetConnection"
                                   click="{disconnectInitConnection()}"
                                   enabled="true"
                               />
                               <mx:Button id="disconnectingConsumerButton" 
                                   label="Disconnecting Consumer" 
                                   width="100%"
                                   click="{disconnectConsumer()}"
                               />
                               <mx:Button id="disconnectingProducerButton" 
                                   label="Disconnecting Producer" 
                                   width="100%"
                                   click="{disconnectProducer()}"
                               />
                           </mx:FormItem>
                       </mx:Form>
                   </mx:VBox>
                   <mx:VBox width="50%">
                       <mx:Form borderStyle="solid" width="100%">
                           <mx:FormHeading label="Bindings to connected properties"/>
                           <mx:FormItem label="NetConnection connected">
                               <mx:CheckBox id="netConnectionCheckBox" enabled="false"/>
                           </mx:FormItem>
                           <mx:FormItem label="Channel connected">
                               <mx:CheckBox selected="{this.channel.connected}" enabled="false"/>
                           </mx:FormItem>
                           <mx:FormItem label="ChannelSet connected">
                               <mx:CheckBox selected="{this.cs.connected}" enabled="false"/>
                           </mx:FormItem>
                           <mx:FormItem label="Consumer connected">
                               <mx:CheckBox selected="{this.consumer.connected}" enabled="false"/>
                           </mx:FormItem>
                           <mx:FormItem label="Producer connected">
                               <mx:CheckBox selected="{this.producer.connected}" enabled="false"/>
                           </mx:FormItem>
                       </mx:Form>
                       <mx:Form borderStyle="solid" width="100%">
                           <mx:FormHeading label="Sending messages"/>
                           <mx:FormItem>
                               <mx:Button id="sendLockedAppleMessageButton"
                                   label="Sending a Locked Apple Message" 
                                   click="{sendLockedAppleMessage()}"
                                   enabled="true"
                                    width="100%"
                                />
                               <mx:Button id="sendLockedBananaMessageButton"
                                   label="Sending a Locked Banana Message" 
                                   click="{sendLockedBananaMessage()}"
                                   enabled="true"
                                   width="100%"
                               />
                               <mx:Button id="sendLockedPotatoeMessageButton"
                                   label="Sending a Locked Potatoe Message" 
                                   click="{sendLockedPotatoeMessage()}"
                                   enabled="true"
                                    width="100%"
                                />
                               <mx:Button id="sendLockedAppleBananaPotatoeMessageButton"
                                   label="Sending a Locked Apple and Banana and Potatoe Message" 
                                   click="{sendApplePotatoeBananaMessage()}"
                                   enabled="true"
                               />
                           </mx:FormItem>
                       </mx:Form>
                   </mx:VBox>
            </mx:HBox>
            <mx:HBox width="100%" height="100%">
                <mx:FormItem label="Output Panel" width="100%" height="100%" borderStyle="solid">
                       <mx:TextArea width="100%" height="100%" id="outputPanel"/>
                   </mx:FormItem>
            </mx:HBox>
            <mx:HRule width="100%"/>
            <mx:HBox verticalAlign="middle">
                <mx:Label text="Created by Johlero (Lieven Cardoen) RDB Technologies"/>
                <mx:LinkButton label="Johlero Blog Link" click="navigateToURL(new URLRequest('http://blog.johlero.eu'), '_blank')" textDecoration="underline" color="#0D005A"/>
            </mx:HBox>
            
</mx:Application>