////////////////////////////////////////////////////////////////////////////////
//
//  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.
//
////////////////////////////////////////////////////////////////////////////////

package mx.messaging
{

import flash.events.EventDispatcher;

import mx.core.IMXMLObject;
import mx.core.mx_internal;
import mx.events.PropertyChangeEvent;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.messaging.FlexClient;
import mx.messaging.channels.PollingChannel;
import mx.messaging.config.ConfigMap;
import mx.messaging.config.ServerConfig;
import mx.messaging.errors.InvalidDestinationError;
import mx.messaging.events.ChannelEvent;
import mx.messaging.events.ChannelFaultEvent;
import mx.messaging.events.MessageAckEvent;
import mx.messaging.events.MessageEvent;
import mx.messaging.events.MessageFaultEvent;
import mx.messaging.messages.AbstractMessage;
import mx.messaging.messages.AcknowledgeMessage;
import mx.messaging.messages.CommandMessage;
import mx.messaging.messages.ErrorMessage;
import mx.messaging.messages.IMessage;
import mx.messaging.messages.MessagePerformanceUtils;
import mx.netmon.NetworkMonitor;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
import mx.utils.Base64Encoder;
import mx.utils.UIDUtil;

use namespace mx_internal;

/**
 *  Dispatched when an acknowledge message is received for a sent message.
 *
 *  @eventType mx.messaging.events.MessageAckEvent.ACKNOWLEDGE
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3    
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3       
 */
[Event(name="acknowledge", type="mx.messaging.events.MessageAckEvent")]

/**
 *  Dispatched when a message fault occurs.
 *
 *  @eventType mx.messaging.events.MessageFaultEvent.FAULT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
[Event(name="fault", type="mx.messaging.events.MessageFaultEvent")]

/**
 *  Dispatched when the underlying Channel the MessageAgent is using connects.
 *
 *  @eventType mx.messaging.events.ChannelEvent.CONNECT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
[Event(name="channelConnect", type="mx.messaging.events.ChannelEvent")]

/**
 *  Dispatched when the underlying Channel the MessageAgent is using disconnects.
 *
 *  @eventType mx.messaging.events.ChannelEvent.DISCONNECT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
[Event(name="channelDisconnect", type="mx.messaging.events.ChannelEvent")]

/**
 *  Dispatched when the underlying Channel the MessageAgent is using faults.
 *
 *  @eventType mx.messaging.events.ChannelFaultEvent.FAULT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
[Event(name="channelFault", type="mx.messaging.events.ChannelFaultEvent")]

/**
 *  Dispatched when the <code>connected</code> property of the MessageAgent changes.
 *  Also dispatched when the <code>subscribed</code> of a Consumer changes.
 *  @see mx.messaging.Consumer
 *  @eventType mx.events.PropertyChangeEvent.PROPERTY_CHANGE
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
[Event(name="propertyChange", type="mx.events.PropertyChangeEvent")]

[ResourceBundle("messaging")]

/**
 *  The MessageAgent class provides the basic low-level functionality common to
 *  message handling for a destination.
 *
 *  <p><b>Note:</b> For advanced use only.
 *  Use this class for creating custom message agents like the existing Producer
 *  and Consumer classes.</p>
 *
 *  @mxml
 *  <p>
 *  All message agent classes, including the Producer and Consumer classes, extend
 *  MessageAgent and inherit the following tag attributes:
 *  </p>
 *  <pre>
 *   &lt;mx:<i>tagname</i><br>
 *    <b>Properties</b>
 *    channelSet="<i>No default.</i>"
 *    clientId="<i>No default.</i>"
 *    connected="<i>false</i>"
 *    destination="<i>No default.</i>"
 *    requestTimeout="<i>-1</i>"
 *    subtopic="<i>No default.</i>"
 *
 *
 *   <b>Events</b>
 *    acknowledge="<i>No default.</i>"
 *    channelConnect="<i>No default.</i>"
 *    channelDisconnect="<i>No default.</i>"
 *    channelFault="<i>No default.</i>"
 *    fault="<i>No default.</i>"
 *    propertyChange="<i>No default.</i>"
 *  /&gt;
 *  </pre>
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
public class MessageAgent extends EventDispatcher implements IMXMLObject
{
    //--------------------------------------------------------------------------
    //
    // Internal Static Constants
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Indicates that the MessageAgent is used an automatically configured ChannelSet
     *  obtained from ServerConfig.
     */
    mx_internal static const AUTO_CONFIGURED_CHANNELSET:int = 0;

    /**
     *  @private
     *  Indicates that the MessageAgent is using a manually assigned ChannelSet.
     */
    mx_internal static const MANUALLY_ASSIGNED_CHANNELSET:int = 1;

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3           
     */
    public function MessageAgent()
    {
        super();
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  The type of MessageAgent.
     *  This variable is used for logging and MUST be assigned by subclasses.
     */
    protected var _agentType:String = "mx.messaging.MessageAgent";

    /**
     *  @private
     *  The Base64 encoded credentials that will be passed through to
     *  the ChannelSet.
     */
    protected var _credentials:String;

    /**
     *  @private
     *  The character set encoding used to create the credentials String.
     */
    protected var _credentialsCharset:String;

    /**
     *  @private
     *  Indicates whether the agent is explicitly disconnected.
     *  This allows agents to supress processing of acks/faults that return
     *  after the client has issued an explicit disconnect().
     */
    protected var _disconnectBarrier:Boolean;

    /**
     *  @private
     *  This helps in the runtime configuration setup by delaying the connect
     *  event until the configuration has been setup. See acknowledge().
     */
    private var _pendingConnectEvent:ChannelEvent;

    /**
     *  @private
     *  The Base64 encoded credentials that are passed through to a
     *  3rd party.
     */
    private var _remoteCredentials:String = "";

    /**
     *  @private
     *  The character set encoding used to create the remoteCredentials String.
     */
    private var _remoteCredentialsCharset:String;

    /**
     *  @private
     *  Indicates that the remoteCredentials value has changed and should
     *  be sent to the server.
     */
    private var _sendRemoteCredentials:Boolean;

    /**
     *  @private
     *  The logger MUST be assigned by subclasses, for example
     *  Consumer and Producer.
     */
    protected var _log:ILogger;

    /**
     *  @private
     *  A queue to store pending outbound messages while waiting for a server response
     *  that contains a server-generated clientId.
     *  Serializing messages from a MessageAgent to the server is essential until we
     *  receive a response containing a server-generated clientId; otherwise the server
     *  will treat each message as if it was sent by a different, "new" MessageAgent instance.
     */
    private var _clientIdWaitQueue:Array;

    /**
     *  @private
     * Flag being set to true denotes that we should skip remaining fault
     * processing logic because the fault has already been handled.
     * Currently used during an automatic resend of a faulted message if the fault
     * was due to a server session timeout and is authentication/authorization related.
     */
    protected var _ignoreFault:Boolean = false;

    /**
     *  @private
     */
    private var resourceManager:IResourceManager =
                                    ResourceManager.getInstance();
    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  authenticated
    //----------------------------------

    /**
     *  @private
     */
    private var _authenticated:Boolean;

    [Bindable(event="propertyChange")]
    /**
     *  Indicates if this MessageAgent is using an authenticated connection to
     *  its destination.
     */
    public function get authenticated():Boolean
    {
        return _authenticated;
    }

    /**
     *  @private
     */
    mx_internal function setAuthenticated(value:Boolean, creds:String):void
    {
        if (_authenticated != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "authenticated", _authenticated, value);
            _authenticated = value;
            dispatchEvent(event);

            if (value)
                assertCredentials(creds);
        }
    }

    //----------------------------------
    //  channelSet
    //----------------------------------

    /**
     *  @private
     */
    private var _channelSet:ChannelSet;

    [Bindable(event="propertyChange")]
    /**
     *  Provides access to the ChannelSet used by the MessageAgent. The
     *  ChannelSet can be manually constructed and assigned, or it will be
     *  dynamically initialized to use the configured Channels for the
     *  destination for this MessageAgent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3           
     */
    public function get channelSet():ChannelSet
    {
        return _channelSet;
    }

    /**
     *  @private
     */
    public function set channelSet(value:ChannelSet):void
    {
        internalSetChannelSet(value);
        _channelSetMode = MANUALLY_ASSIGNED_CHANNELSET;
    }

    /**
     *  @private
     *  This method is called by ChannelSet.connect(agent) to set up the bidirectional
     *  relationship between the MessageAgent and the ChannelSet.
     *  It also handles the case of customer code calling channelSet.connect(agent)
     *  directly rather than assigning the ChannelSet to the MessageAgent's channelSet
     *  property.
     */
    mx_internal function internalSetChannelSet(value:ChannelSet):void
    {
        if (_channelSet != value)
        {
            if (_channelSet != null)
                _channelSet.disconnect(this);

            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "channelSet", _channelSet, value);
            _channelSet = value;

            if (_channelSet != null)
            {
                if (_credentials)
                    _channelSet.setCredentials(_credentials, this, _credentialsCharset);

                _channelSet.connect(this);
            }

            dispatchEvent(event);
        }
    }

    //----------------------------------
    //  clientId
    //----------------------------------

    /**
     *  @private
     */
    private var _clientId:String;

    [Bindable(event="propertyChange")]
    /**
     *  Provides access to the client id for the MessageAgent.
     *  MessageAgents are assigned their client id by the remote destination
     *  and this value is used to route messages from the remote destination to
     *  the proper MessageAgent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3           
     */
    public function get clientId():String
    {
        return _clientId;
    }

    /**
     *  @private
     *  This method is used to assign a server-generated client id to the MessageAgent
     *  in the common scenario.
     *  It may also be used by the framework to sync up cooperating MessageAgents under
     *  a single client id value so that they appear as a single MessageAgent to the server.
     *  Assigning a client id value will flush any messages that have been queued while we
     *  were waiting for a server-generated client id value to be returned.
     *  Queued messages are sent to the server in order.
     */
    mx_internal function setClientId(value:String):void
    {
        if (_clientId != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "clientId", _clientId, value);
            _clientId = value;
            flushClientIdWaitQueue();
            dispatchEvent(event);
        }
    }

    //----------------------------------
    //  connected
    //----------------------------------

    /**
     *  @private
     */
    private var _connected:Boolean = false;

    [Bindable(event="propertyChange")]
    /**
     *  Indicates whether this MessageAgent is currently connected to its
     *  destination via its ChannelSet. The <code>propertyChange</code> event is dispatched when
     *  this property changes.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function get connected():Boolean
    {
        return _connected;
    }

    /**
     *  @private
     */
    protected function setConnected(value:Boolean):void
    {
        if (_connected != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "connected", _connected, value);
            _connected = value;
            dispatchEvent(event);
            setAuthenticated(value && channelSet && channelSet.authenticated, _credentials);
        }
    }

    //----------------------------------
    //  destination
    //----------------------------------

    /**
     *  @private
     */
    private var _destination:String = "";

    [Bindable(event="propertyChange")]
    /**
     *  Provides access to the destination for the MessageAgent.
     *  Changing the destination will disconnect the MessageAgent if it is
     *  currently connected.
     *
     *  @throws mx.messaging.errors.InvalidDestinationError If the destination is null or
     *                                  zero-length.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function get destination():String
    {
        return _destination;
    }

    /**
     *  @private
     */
    public function set destination(value:String):void
    {
        if ((value == null) || value.length == 0)
            return; // empty/null destination is checked in internalSend.

        if (_destination != value)
        {
            // If we're using an automatically configured ChannelSet,
            // disconnect from it and null out our ref so we look up the
            // proper configured ChannelSet for the new destination on our next send().
            if ((_channelSetMode == AUTO_CONFIGURED_CHANNELSET) && (channelSet != null))
            {
                channelSet.disconnect(this);
                channelSet = null;
            }

            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "destination", _destination, value);
            _destination = value;
            dispatchEvent(event);

            if (Log.isInfo())
                _log.info("'{0}' {2} set destination to '{1}'.", id, _destination,  _agentType);
        }
    }

    //----------------------------------
    //  id
    //----------------------------------

    /**
     *  @private
     */
    private var _id:String = UIDUtil.createUID();

    [Bindable(event="propertyChange")]
    /**
     *  @private
     *  The id of this agent.
     */
    public function get id():String
    {
        return _id;
    }

    /**
     *  @private
     */
    public function set id(value:String):void
    {
        if (_id != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "id", _id, value);
            _id = value;
            dispatchEvent(event);
        }
    }

    //----------------------------------
    //  requestTimeout
    //----------------------------------

    /**
     *  @private
     */
    private var _requestTimeout:int = -1;

    [Bindable(event="propertyChange")]
    /**
     *  Provides access to the request timeout in seconds for sent messages.
     *  If an acknowledgement, response or fault is not received from the
     *  remote destination before the timeout is reached the message is faulted on the client.
     *  A value less than or equal to zero prevents request timeout.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3           
     */
    public function get requestTimeout():int
    {
        return _requestTimeout;
    }

    /**
     *  @private
     */
    public function set requestTimeout(value:int):void
    {
        if (_requestTimeout != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "requestTimeout", _requestTimeout, value);
            _requestTimeout = value;
            dispatchEvent(event);
        }
    }

    //--------------------------------------------------------------------------
    //
    // Internal Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  channelSetMode
    //----------------------------------

    /**
     *  @private
     */
    private var _channelSetMode:int = AUTO_CONFIGURED_CHANNELSET;

    mx_internal function get channelSetMode():int
    {
        return _channelSetMode;
    }

    //----------------------------------
    //  configRequested
    //----------------------------------

    /**
     *  @private
     *  Indicates whether the agent has requested configuration from the server.
     */
    mx_internal var configRequested:Boolean = false;

    //----------------------------------
    //  needsConfig
    //----------------------------------

    /**
     * @private
     */
    private var _needsConfig:Boolean;

    /**
     *  Indicates if this MessageAgent needs to request configuration from the
     *  server.
     */
    mx_internal function get needsConfig():Boolean
    {
        return _needsConfig;
    }

    /**
     *  @private
     */
    mx_internal function set needsConfig(value:Boolean):void
    {
        if (_needsConfig == value)
            return;

        _needsConfig = value;
        if (_needsConfig)
        {
            var cs:ChannelSet = channelSet;
            try
            {
                disconnect();
            }
            finally
            {
                internalSetChannelSet(cs);
            }
        }
    }

    //--------------------------------------------------------------------------
    //
    // Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Invoked by a MessageResponder upon receiving a result for a sent
     *  message. Subclasses may override this method if they need to perform
     *  custom acknowledgement processing, but must invoke
     *  <code>super.acknowledge()</code> as well. This method dispatches a
     *  MessageAckEvent.
     *
     *  @param ackMsg The AcknowledgMessage returned.
     *
     *  @param msg The original sent message.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function acknowledge(ackMsg:AcknowledgeMessage, msg:IMessage):void
    {
        if (Log.isInfo())
            _log.info("'{0}' {2} acknowledge of '{1}'.", id, msg.messageId, _agentType);

        if (Log.isDebug() && isCurrentChannelNotNull() && getCurrentChannel().mpiEnabled)
        {
            try
            {
                var mpiutil:MessagePerformanceUtils = new MessagePerformanceUtils(ackMsg);
                _log.debug(mpiutil.prettyPrint());
            }
            catch (e:Error)
            {
                _log.debug("Could not get message performance information for: " + msg.toString());
            }
        }

        if (configRequested)
        {
            configRequested = false;
            ServerConfig.updateServerConfigData(ackMsg.body as ConfigMap);
            needsConfig = false;
            if (_pendingConnectEvent)
                channelConnectHandler(_pendingConnectEvent);

            _pendingConnectEvent = null;
        }

        if (clientId == null)
        {
            if (ackMsg.clientId != null)
                setClientId(ackMsg.clientId); // Triggers a call to flush the clientId wait queue.
            else
                flushClientIdWaitQueue();
        }

        dispatchEvent(MessageAckEvent.createEvent(ackMsg, msg));
        monitorRpcMessage(ackMsg,msg);
    }

    /**
     *  Disconnects the MessageAgent's network connection.
     *  This method does not wait for outstanding network operations to complete.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3       
     */
    public function disconnect():void
    {
        if (!_disconnectBarrier)
        {
            // Ensure wait queue for client id value is destroyed.
            _clientIdWaitQueue = null;

            // Only set the barrier used to discard post-disconnect results/faults
            // if the agent is currently connected (otherwise, if this is invoked before
            // connecting and the client fails to connect to the server, no faults will be
            // dispatched).
            if (connected)
                _disconnectBarrier = true;

            if (_channelSetMode == AUTO_CONFIGURED_CHANNELSET)
                internalSetChannelSet(null);
            else if (_channelSet != null)
                _channelSet.disconnect(this);
        }
    }

    /**
     *  Invoked by a MessageResponder upon receiving a fault for a sent message.
     *  Subclasses may override this method if they need to perform custom fault
     *  processing, but must invoke <code>super.fault()</code> as well. This
     *  method dispatchs a MessageFaultEvent.
     *
     *  @param errMsg The ErrorMessage.
     *
     *  @param msg The original sent message that caused this fault.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function fault(errMsg:ErrorMessage, msg:IMessage):void
    {
        if (Log.isError())
            _log.error("'{0}' {2} fault for '{1}'.", id, msg.messageId, _agentType);

        _ignoreFault = false;
        configRequested = false;

        // Remove retryable hint.
        if (errMsg.headers[ErrorMessage.RETRYABLE_HINT_HEADER])
            delete errMsg.headers[ErrorMessage.RETRYABLE_HINT_HEADER];

        if (clientId == null)
        {
            if (errMsg.clientId != null)
                setClientId(errMsg.clientId); // Triggers a call to flush the clientId wait queue.
            else
                flushClientIdWaitQueue();
        }

        dispatchEvent(MessageFaultEvent.createEvent(errMsg));
        monitorRpcMessage(errMsg,msg);

        handleAuthenticationFault(errMsg, msg);
    }

    /**
     *  Handles a CONNECT ChannelEvent. Subclasses that need to perform custom
     *  processing should override this method, and invoke
     *  <code>super.channelConnectHandler()</code>.
     *
     *  @param event The ChannelEvent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function channelConnectHandler(event:ChannelEvent):void
    {
        _disconnectBarrier = false;
        // If we are waiting on config to come in we can't be connected until
        // we get it. See acknowledge().
        if (needsConfig)
        {
            if (Log.isInfo())
                _log.info("'{0}' {1} waiting for configuration information.", id, _agentType);

            _pendingConnectEvent = event;
        }
        else
        {
            if (Log.isInfo())
                _log.info("'{0}' {1} connected.", id, _agentType);
            setConnected(true);
            dispatchEvent(event);
        }
    }

    /**
     *  Handles a DISCONNECT ChannelEvent. Subclasses that need to perform
     *  custom processing should override this method, and invoke
     *  <code>super.channelDisconnectHandler()</code>.
     *
     *  @param event The ChannelEvent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function channelDisconnectHandler(event:ChannelEvent):void
    {
        if (Log.isWarn())
            _log.warn("'{0}' {1} channel disconnected.", id, _agentType);
        setConnected(false);
        // If we have remoteCredentials we need to send them on reconnect.
        if (_remoteCredentials != null)
        {
            _sendRemoteCredentials = true;
        }
        dispatchEvent(event);
    }

    /**
     *  Handles a ChannelFaultEvent. Subclasses that need to perform custom
     *  processing should override this method, and invoke
     *  <code>super.channelFaultHandler()</code>.
     *
     *  @param The ChannelFaultEvent
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function channelFaultHandler(event:ChannelFaultEvent):void
    {
        if (Log.isWarn())
            _log.warn("'{0}' {1} channel faulted with {2} {3}", id, _agentType, event.faultCode, event.faultDetail);

        if (!event.channel.connected)
        {
            setConnected(false);
            // If we have remoteCredentials we need to send them on reconnect.
            if (_remoteCredentials != null)
            {
                _sendRemoteCredentials = true;
            }
        }
        dispatchEvent(event);
    }

    /**
     *  Called after the implementing object has been created
     *  and all properties specified on the tag have been assigned.
     *
     *  @param document MXML document that created this object.
     *
     *  @param id id used by the document to refer to this object.
     *  If the object is a deep property on the document, id is null.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function initialized(document:Object, id:String):void
    {
        this.id = id;
    }

    /**
     *  Logs the MessageAgent out from its remote destination.
     *  Logging out of a destination applies to everything connected using the same ChannelSet
     *  as specified in the server configuration. For example, if several DataService components
     *  are connected over an RTMP channel and <code>logout()</code> is invoked on one of them,
     *  all other client components that are connected using the same ChannelSet are also logged out.
     *
     *  <p><b>Note:</b> Adobe recommends that you use the mx.messaging.ChannelSet.logout() method
     *  rather than this method. </p>
     *
     *  @see mx.messaging.ChannelSet#logout()
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function logout():void
    {
        _credentials = null;
        if (channelSet)
            channelSet.logout(this);
    }

    /**
     *  Sets the credentials that the MessageAgent uses to authenticate to
     *  destinations.
     *  The credentials are applied to all services connected over the same ChannelSet.
     *
     *  @param username The username.
     *  @param password The password.
     *  @param charset The character set encoding to use while encoding the
     *  credentials. The default is null, which implies the legacy charset of
     *  ISO-Latin-1. The only other supported charset is &quot;UTF-8&quot;.
     *
     *  @throws flash.errors.IllegalOperationError in two situations; if credentials
     *  have already been set and an authentication is in progress with the remote
     *  detination, or if authenticated and the credentials specified don't match
     *  the currently authenticated credentials.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function setCredentials(username:String, password:String, charset:String=null):void
    {
        if (username == null && password == null)
        {
            _credentials = null;
            _credentialsCharset = null;
        }
        else
        {
            var cred:String = username + ":" + password;
            var encoder:Base64Encoder = new Base64Encoder();
            if (charset == Base64Encoder.CHARSET_UTF_8)
                encoder.encodeUTFBytes(cred);
            else
                encoder.encode(cred);
            _credentials = encoder.drain();
            _credentialsCharset = charset;
        }

        if (channelSet != null)
            channelSet.setCredentials(_credentials, this, _credentialsCharset);
    }

    /**
     *  Sets the remote credentials that will be passed through to the remote destination
     *  for authenticating to secondary systems.
     *
     *  @param username The username.
     *  @param password The password.
     *  @param charset The character set encoding to use while encoding the
     *  remote credentials. The default is null, which implies the legacy
     *  charset of ISO-Latin-1. The only other currently supported option is
     *  &quot;UTF-8&quot;.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function setRemoteCredentials(username:String, password:String, charset:String=null):void
    {
        if (username == null && password == null)
        {
            _remoteCredentials = "";
            _remoteCredentialsCharset = null;
        }
        else
        {
            var cred:String = username + ":" + password;
            var encoder:Base64Encoder = new Base64Encoder();
            if (charset == Base64Encoder.CHARSET_UTF_8)
                encoder.encodeUTFBytes(cred);
            else
                encoder.encode(cred);
            _remoteCredentials = encoder.drain();
            _remoteCredentialsCharset = charset;
        }
        _sendRemoteCredentials = true;
    }

    /**
    * Returns true if there are any pending requests for the passed in message.
    * This method should be overriden by subclasses
    *
    * @param msg The message for which the existence of pending requests is checked.
    *
    * @return Returns <code>true</code> if there are any pending requests for the
    * passed in message.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3     
    */
    public function hasPendingRequestForMessage(msg:IMessage):Boolean
    {
        return false;
    }

    //--------------------------------------------------------------------------
    //
    // Internal Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Internal hook for ChannelSet to assign credentials when it has authenticated
     *  successfully via a direct <code>login(...)</code> call to the server or logged
     *  out directly.
     */
    mx_internal function internalSetCredentials(credentials:String):void
    {
        _credentials = credentials;
    }

    //--------------------------------------------------------------------------
    //
    // Protected Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    final protected function assertCredentials(value:String):void
    {
        if (_credentials != null && (_credentials != value))
        {
            var errMsg:ErrorMessage = new ErrorMessage();
            errMsg.faultCode = "Client.Authentication.Error";
            errMsg.faultString = "Credentials specified do not match those used on underlying connection.";
            errMsg.faultDetail = "Channel was authenticated with a different set of credentials than those used for this agent.";
            dispatchEvent(MessageFaultEvent.createEvent(errMsg));
        }
    }

    /**
     *  @private
     *  Utility method to flush any pending queued messages to send once we have
     *  received a clientId from the remote destination.
     */
    final protected function flushClientIdWaitQueue():void
    {
        if (_clientIdWaitQueue != null)
        {
            // If we have a valid clientId, flush all pending messages.
            if (clientId != null)
            {
                while (_clientIdWaitQueue.length > 0)
                {
                    internalSend(_clientIdWaitQueue.shift() as IMessage);
                }
            }

            if (clientId == null)
            {
                // If we still don't have a clientId, remove the first queued message and send it.
                // Leave the queue intact to buffer subsequent sends until we get a response/fault
                // back for this one.
                if (_clientIdWaitQueue.length > 0)
                {
                    var saveQueue:Array = _clientIdWaitQueue;
                    // Make sure we don't just put it back into the queue - we let the first
                    // one through if this is null.
                    _clientIdWaitQueue = null;
                    internalSend(saveQueue.shift() as IMessage);
                    _clientIdWaitQueue = saveQueue;
                }
                else
                {
                    // Regardless of whether the clientId is defined or not, if the wait queue
                    // is empty set it to null to allow the next message to be processed by the
                    // send code path rather than being routed to the queue.
                    _clientIdWaitQueue = null;
                }
            }
        }
    }

    /**
     * Handles the authentication fault on the server. If the authenticated flag is true, 
     * the authentication fault must have been caused by a session expiration on the server.
     * Set the authenticated state to false and if loginAfterDisconnect flag is enabled,
     * resend credentials to the server by disconnecting and resending the message again.
     *
     *  @param errMsg The Error Message.
     *  @param msg The message that caused the fault and should be resent once we have
     *  disconnected/connected causing re-authentication.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    protected function handleAuthenticationFault(errMsg:ErrorMessage, msg:IMessage):void
    {
        if (errMsg.faultCode == "Client.Authentication" && authenticated && isCurrentChannelNotNull())
        {
            var currentChannel:Channel = getCurrentChannel();
            currentChannel.setAuthenticated(false);

            if (currentChannel is PollingChannel && (currentChannel as PollingChannel).loginAfterDisconnect)
            {
                reAuthorize(msg);
                _ignoreFault = true;
            }
        }
    }

    /**
     *  Used to automatically initialize the <code>channelSet</code> property for the
     *  MessageAgent before it connects for the first time.
     *  Subtypes may override to perform custom initialization.
     *
     *  @param message The message that needs to be sent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    protected function initChannelSet(message:IMessage):void
    {
        if (_channelSet == null)
        {
            _channelSetMode = AUTO_CONFIGURED_CHANNELSET;
            internalSetChannelSet(ServerConfig.getChannelSet(destination));
        }

        if (_channelSet.connected && needsConfig && !configRequested)
        {
            message.headers[CommandMessage.NEEDS_CONFIG_HEADER] = true;
            configRequested = true;
        }

        _channelSet.connect(this);

        if (_credentials != null)
            channelSet.setCredentials(_credentials, this, _credentialsCharset);
    }

    /**
     *  Sends a Message from the MessageAgent to its destination using the
     *  agent's ChannelSet. MessageAgent subclasses must use this method to
     *  send their messages.
     *
     *  @param message The message to send.
     *
     *  @param waitForClientId If true the message may be queued until a clientId has been
     *                         assigned to the agent. In general this is the desired behavior.
     *                         For special behavior (automatic reconnect and resubscribe) the
     *                         agent may pass false to override the default queuing behavior.
     *
     *  @throws mx.messaging.errors.InvalidDestinationError If no destination is set.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    protected function internalSend(message:IMessage, waitForClientId:Boolean = true):void
    {
        // If we don't have a client or server assigned clientId, we
        // need to send a single message and then store any subsequent messages
        // in a buffer to be sent once we've gotten back a server-generated
        // clientId. Otherwise, N outbound messages sent before receiving an ack for
        // the first will result in the generation of N different clientIds in the
        // response/fault messages from the server.
        if ((message.clientId == null) && waitForClientId && (clientId == null))
        {
            if (_clientIdWaitQueue == null)
            {
                _clientIdWaitQueue = [];
                // Current message will be sent but subsequent messages sent before
                // its ack/fault will be queued.
            }
            else
            {
                _clientIdWaitQueue.push(message);
                return; // We've queued the message and will send it once we get a clientId or the outstanding send fails.
            }
        }

        if (message.clientId == null)
            message.clientId = clientId;

        if (requestTimeout > 0)
            message.headers[AbstractMessage.REQUEST_TIMEOUT_HEADER] = requestTimeout;

        if (_sendRemoteCredentials)
        {
            if (! ((message is CommandMessage) &&
                    (CommandMessage(message).operation == CommandMessage.TRIGGER_CONNECT_OPERATION)))
            {
                message.headers[AbstractMessage.REMOTE_CREDENTIALS_HEADER] = _remoteCredentials;
                message.headers[AbstractMessage.REMOTE_CREDENTIALS_CHARSET_HEADER] = _remoteCredentialsCharset;
                _sendRemoteCredentials = false;
            }
        }

        if (channelSet != null)
        {
            if (!connected && (_channelSetMode == MANUALLY_ASSIGNED_CHANNELSET))
                _channelSet.connect(this);

            if (channelSet.connected && needsConfig && !configRequested)
            {
                message.headers[CommandMessage.NEEDS_CONFIG_HEADER] = true;
                configRequested = true;
            }

            channelSet.send(this, message);
            monitorRpcMessage(message,message);
        }
        else if (destination != null && destination.length > 0)
        {
            initChannelSet(message);
            if (channelSet != null)
            {
                channelSet.send(this, message);
                monitorRpcMessage(message,message);
            }
        }
        else
        {
            var msg:String = resourceManager.getString(
                "messaging", "destinationNotSet");
            throw new InvalidDestinationError(msg);
        }
    }

    /**
     * This function should be overriden by sublasses to implement reauthentication due to
     * server session time-out behavior specific to them. In general, it should follow disconnect, 
     * connect, resend message pattern.
     *
     *  @param msg The message that caused the fault and should be resent once we have
     *  disconnected/connected causing reauthentication.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    protected function reAuthorize(msg:IMessage):void
    {
        // Disconnect all message agents from the Channel to make sure the Channel
        // is fully disconnected and Channel#internalConnect gets called which 
        // sends the login command to reauthenticate the Channel.
        if (channelSet != null)
            channelSet.disconnectAll();
        internalSend(msg);
    }

    /**
     *  @private
     */
    private function getCurrentChannel():Channel
    {
        return channelSet != null? channelSet.currentChannel : null;
    }

    /**
     *  @private
     */
    private function isCurrentChannelNotNull():Boolean
    {
        return getCurrentChannel() != null;
    }

    /**
     * Monitor a rpc message that is being send
     */
    private function monitorRpcMessage(message:IMessage,actualMessage:IMessage):void
    {
        if (NetworkMonitor.isMonitoring())
        {
            if (message is ErrorMessage)
            {
                NetworkMonitor.monitorFault(actualMessage, MessageFaultEvent.createEvent(ErrorMessage(message)));
            }
            else if (message is AcknowledgeMessage)
            {
                NetworkMonitor.monitorResult(message, MessageEvent.createEvent(MessageEvent.RESULT, actualMessage));
            }
            else
            {
                NetworkMonitor.monitorInvocation(getNetmonId(), message, this);
            }
        }
    }

    /**
     * Return the id for the NetworkMonitor.
     * @private
     */
    mx_internal function getNetmonId():String
    {
        return null;
    }
}

}
