package de.dtele.data {
  
  import de.dtele.net.Connection;
  
  import flash.events.EventDispatcher;
  
  import mx.collections.ArrayCollection;
  import mx.collections.ListCollectionView;
  import mx.events.PropertyChangeEvent;
  import mx.utils.ObjectProxy;
  
  /**
   * An implementation of the ISource interface, represents source objets
   * 
   * @author Mathias Brodala
   */
  public class Source extends EventDispatcher implements ISource {
    
    /* Properties */
    private var _url:String;
    /**
     * The URL of this source
     */
    [Bindable]public function get url():String {
      return _url;
    }
    private function set url(url:String):void {
      
      var changeEvent:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(
        this, "url", this._url, url);
      
      this._url = url;
      this.dispatchEvent(changeEvent);
    }

    private var _resources:ListCollectionView = new ArrayCollection();
    [Bindable]public function get resources():ListCollectionView { return this._resources; }
    protected function set resources(resources:ListCollectionView):void {
      
      this._resources = resources;
    }
    
    private var _properties:ObjectProxy = new ObjectProxy({
      title: null
    }, "sourceProperties");
    /**
     * Properties of this source
     */
    [Bindable]public function get properties():ObjectProxy {
      return _properties;
    }
    protected function set properties(properties:ObjectProxy):void {
      this._properties = properties;
    }
    
    private var _allowed:ObjectProxy = new ObjectProxy({}, "allowed");
    /**
     * Map of allowed request types
     */
    public function get allowed():ObjectProxy { return this._allowed; }
    
    private var _restricted:ObjectProxy = new ObjectProxy({}, "restricted");
    /**
     * Map of restricted request types
     */
    public function get restricted():ObjectProxy { return this._restricted; }
    
    private var _credentials:ObjectProxy = new ObjectProxy({}, "credentials");
    /**
     * Map of credentials for restricted request types
     */
    public function get credentials():ObjectProxy { return this._credentials; }
    
    /**
     * The connection of this source
     */
    private var _connection:Connection;
    public function get connection():Connection {
      return _connection;
    }
    public function set connection(connection:Connection):void {
      _connection = connection;
    }
    
    /* Methods */
    /**
     * Creates a new source
     * 
     * @param url The URL of the source
     * @param info Optional initial information
     */
    public function Source(url:String, info:Object=null) {
      
      this.url = url;
      
      if (info) {
        
        for (var property:String in this.properties) {
          
          var value:Object = info[property];
          
          if (value) {
            
            this.properties[property] = value;
          }
        }
        
        // Turn ["type1", ...] into { type1: true } for easier checking
        if ("allowed" in info) {
          
          info.allowed.forEach(function(type:String, ...a):void {
            
            this.allowed[type] = true;
          }, this);
        }
        
        if ("restricted" in info) {
          
          info.restricted.forEach(function(type:String, ...a):void {
            
            this.restricted[type] = true;
          }, this);
        }
        
        if (!this.properties.title) {
          
          this.properties.title = this.url;
        }
      }
    }
    
    public function requiresCredentials(requestType:String):Boolean {
      
      var restricted:Boolean = requestType in this.restricted;
      var credentialsExist:Boolean = requestType in this.credentials;
      
      return (restricted && !credentialsExist);
    }
    
    public override function toString():String {
      
      return this.properties.title;
    }
  }
}