package de.dtele.messages {
  
  import de.dtele.messages.events.MessageResponseEvent;
  
  import flash.events.EventDispatcher;
  
  import mx.collections.ArrayCollection;
  
  /**
   * Dispatched when this message's origin was successfully completed
   * 
   * @eventType flash.events.Event
   */
  [Event("complete", type="flash.events.Event")]
  
  /**
   * Dispatched when progress occurs on this message's origin
   * 
   * @eventType flash.events.ProgressEvent
   */
  [Event("progress", type="flash.events.ProgressEvent")]
  
  /**
   * Dispatched when a response to one of this message's action has been triggered
   * 
   * @eventType de.dtele.messages.events.MessageResponseEvent
   */
  [Event("response", type="de.dtele.messages.events.MessageResponseEvent")]
  
  /**
   * Represents a generic message of differing types
   * 
   * @author Mathias Brodala
   */
  public class Message extends EventDispatcher {
    
    /* Constants */
    /**
     * Regular notice
     */
    public static const INFO:String = "info";
    /**
     * Progress indication
     */
    public static const PROGRESS:String = "progress";
    /**
     * Confirmation
     */
    public static const QUESTION:String = "question";
    /**
     * Recoverable error
     */
    public static const WARNING:String = "warning";
    /**
     * Non-recoverable error
     */
    public static const ERROR:String = "error";
    
    /* Properties */
    private var _title:String = "";
    /**
     * Short title describing the message
     */
    [Bindable]public function get title():String { return this._title; }
    public function set title(title:String):void { this._title = title; }
    
    private var _text:String = "";
    /**
     * Long text describing the message
     */
    [Bindable]public function get text():String { return this._text; }
    public function set text(text:String):void { this._text = text; }
    
    private var _type:String;
    /**
     * The type of this message
     */
    [Bindable]public function get type():String { return this._type; }
    public function set type(type:String):void { this._type = type; }
    
    private var _actions:ArrayCollection = new ArrayCollection();
    [Bindable]
    /**
     * Possible ways of interaction with the message and responses
     */
    public function get actions():ArrayCollection { return this._actions; }
    /**
     * Attaches actions to a message
     * 
     * @param actions The actions to attach to a message
     */
    public function set actions(actions:ArrayCollection):void { this._actions = actions; }
    
    private var _response:MessageResponse;
    /**
     * The response to this message, may only be changed once.
     * Further attempts at setting this will be ignored.
     */
    public function get response():MessageResponse { return this._response; }
    /**
     * @private
     */
    public function set response(value:MessageResponse):void {

      if (!this._response) {
        
        this._response = value;
        this.dispatchEvent(new MessageResponseEvent(MessageResponseEvent.RESPONSE, value));
      }
    }


    /* Methods */
    /**
     * Sets up the message
     * 
     * @param title The short title describing the message
     * @param text The long text describing the message
     * @param type The type of the message
     * @param actions Possible actions for the message
     */
    public function Message(title:String, text:String = null, type:String = Message.INFO, actions:Object = null) {
      
      this._title = title;
      this._text = text;
      this._type = type;
      
      if (actions) {
        
        // Make sure to copy action-response pairs instead of blindly assigning
        for (var action:String in actions) {
          
          this.actions[action] = actions[action];
        }
      } else {
        
        switch (this.type) {
          
          case Message.QUESTION:
            
            this.actions.addItem(new MessageAction(MessageAction.OK, new MessageResponse(MessageResponse.OK)));
            this.actions.addItem(new MessageAction(MessageAction.CANCEL, new MessageResponse(MessageResponse.CANCEL)));
            break;
          
          case Message.PROGRESS:
            
            this.actions.addItem(new MessageAction(MessageAction.CANCEL, new MessageResponse(MessageResponse.CANCEL)));
            break;
        }
      }
    }
  }
}