package de.dtele.settings {
  
  import de.dtele.settings.events.SettingEvent;
  
  import flash.errors.IllegalOperationError;
  import flash.events.EventDispatcher;
  import flash.net.SharedObject;
  import flash.utils.getQualifiedClassName;
  
  /**
   * Dispatched when an option has been set
   * 
   * @eventType de.dtele.settings.events.SettingEvent.OPTION_SET
   */
  [Event("optionSet", type="de.dtele.settings.events.SettingEvent")]
  
  /**
   * Dispatched when a default value for an option has been set
   * 
   * @eventType de.dtele.settings.events.SettingEvent.DEFAULT_SET
   */
  [Event("defaultSet", type="de.dtele.settings.events.SettingEvent")]
  
  /**
   * Manages settings using a local storage if available.
   * If storage is forbidden, no changes will be stored.
   * 
   * @author Mathias Brodala
   */
  public final class SettingsManager extends EventDispatcher {
    
    /* Properties */
    /**
     * The singleton instance of the settings manager
     */
    private static var _instance:SettingsManager;
    public static function get instance():SettingsManager {
      
      if (_instance == null) {
        
        _instance = new SettingsManager();
      }
      
      return _instance;
    }
    
    /**
     * The local storage for settings
     */
    private var storage:SharedObject = SharedObject.getLocal("settings");
    
    /**
     * Default values for options
     */
    private var defaults:Object = {};
    
    private var watchers:Object = {};
    
    /* Methods */
    public function SettingsManager() {
      
      if (_instance != null) {
        
        throw new IllegalOperationError("Cannot instantiate " + getQualifiedClassName(this) + ". " +
          "Use the singleton instance instead.");
      }
    }
    
    /**
     * Retrieves the value of an option or its default value if registered
     * 
     * @param option The option to retrieve the value for
     * @return The value of the option
     */
    public function get(option:String):Object {
      
      var value:Object = this.storage.data[option];
      
      if (!value) {
        
        value = this.defaults[option];
      }
      
      //trace("[SettingsManager] Getting value for option " + option + ": " + value);
      
      return value;
    }
    
    /**
     * Stores the value of an option
     * 
     * @param option The option to store the value for
     * @param value The value of the option
     */
    public function set(option:String, value:Object):void {
      
      //trace("[SettingsManager] Setting value for option " + option + ": " + value);
      this.storage.data[option] = value;
      this.dispatchEvent(new SettingEvent(SettingEvent.OPTION_SET, option, value));
    }
    
    /**
     * Stores a default value for an option
     * 
     * @param option The option to store the default value for
     * @param value The default value of the option
     */
    public function setDefault(option:String, value:Object):void {
      
      this.defaults[option] = value;
      this.dispatchEvent(new SettingEvent(SettingEvent.DEFAULT_SET, option, value));
    }
  }
}