# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base

  # Be sure to include AuthenticationSystem in Application Controller instead
  include AuthenticatedSystem
  

  def initialize
    @dynamic_code = {}
    @onload_js_code = nil
  end

protected

  # Handle controller side of a client-side list
  
  def add_autocomplete_style_code
    if not @dynamic_code[:autocomplete_styling]
      @dynamic_code[:autocomplete_styling] = <<-STYLE_CODE
    		<style>
    		  div.auto_complete {
    	      width: 350px;
    	      background: #fff;
    	    }
    	    div.auto_complete ul {
    	      border:1px solid #888;
    	      margin:0;
    	      padding:0;
    	      width:100%;
    	      list-style-type:none;
    	    }
    	    div.auto_complete ul li {
    	      margin:0;
    	      padding:3px;
    	    }
    	    div.auto_complete ul li.selected { 
    	      background-color: #ffb; 
    	    }
    	    div.auto_complete ul strong.highlight { 
    	      color: #800; 
    	      margin:0;
    	      padding:0;
    		  }
    		</style>
      STYLE_CODE
    end
  end
  
  # Add client-side javascript to locally define the
  # entries in a table
  def add_autocomplete_init_choices( table )
    collection_sym = "@#{table.to_s}".to_sym  # Assumes we use an instance variable that matches table name
    model_class = Object.const_get( Inflector.classify(table) )
    instance_variable_set( collection_sym, model_class.find(:all) )

    code_sym = "#{table.to_s}_define".to_sym
    if not @dynamic_code[code_sym]
      @dynamic_code[code_sym] = <<-JS_CODE
    		<script type="text/javascript">
          var #{table.to_s} = new Array(#{instance_variable_get(collection_sym).length});
      JS_CODE
      instance_variable_get(collection_sym).each_with_index do |entry, index|
        @dynamic_code[code_sym] << table.to_s + "[#{index}]='#{entry.name}'; "
      end
      @dynamic_code[code_sym] << "</script>"
    end
  end
  
  # Add client-side javascript to:
  # (1) redraw the client-side list on load
  # (2) define the selected entries array with given collection
  def add_client_side_init_selected( stem, init_entries )
    @onload_js_code ||= ''
    @onload_js_code << <<-JS_CODE
      csl_show_list(selected_#{stem.to_s}, "#{stem.to_s.singularize}");
    JS_CODE
    
    code_sym = "#{stem.to_s}_inits"
    if not @dynamic_code[code_sym]
        @dynamic_code[code_sym] = <<-JS_CODE
    		<script type="text/javascript">
          var selected_#{stem.to_s} = new Array();
      JS_CODE
      init_entries.each_with_index do |entry, index|
        @dynamic_code[code_sym] << "selected_" + stem.to_s + "[#{index}]='#{entry}'; "
      end
      @dynamic_code[code_sym] << "</script>"
    end
  end
  
  def client_side_list_for( table, *args )
    add_autocomplete_style_code
    add_autocomplete_init_choices( table )
    
    init_entries = args.last[:initialize] if args.last.is_a?(Hash)
    init_entries ||= []
    stem = (args.last.is_a?(Hash) and args.last[:naming]) ? args.last[:naming].to_s : table.to_s.singularize
    add_client_side_init_selected( stem, init_entries )
  end
  
  # Parameters
  # collection => what we sync our list to. We assume each object in the collection has #name
  # :naming => string stem for naming vars, e.g., 'org'
  # :create_entry => true if we will create new classes if lookup by name fails
  def client_side_list_sync( collection, entry_class, *args )
    # Determine the class of the entries from the collection
    # TO DO - then we can drop entry_class parameter, even if collection is empty? (use object and collection symbol instead)
    
    # Read the returned parameters from the form and sync it with the collection
    stem = (args.last.is_a?(Hash) and args.last[:naming]) ? args.last[:naming].to_s : entry_class.to_s.downcase.singularize
    
    selected_sym = "selected_#{stem}".to_sym
    lookup_sym = "#{stem}_lookup".to_sym
    entries = (params[selected_sym] || {})
    entries.merge!( :a => params[lookup_sym] ) if not ( params[lookup_sym].nil? or params[lookup_sym].empty? or entries.has_value?( params[lookup_sym] ) )
    
    collection.clear
    entries.each_value do |entry_name|
      entry_name.tr!("'","")
      entry_object = entry_class.find_by_name( entry_name )      
      entry_object = entry_class.create( :name => entry_name ) if args.last[:create_entry] and entry_object.nil?
      collection << entry_object if entry_object
    end
  end
  
  ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.merge!(
    :default => "%B %d, %Y",
    :iso_8601_date_only => "%Y-%m-%d",
    :iso_8601_time_only => "%H:%M:%S%z",
    :date_time12 => "%m/%d/%Y %I:%M%p",
    :date_time24 => "%m/%d/%Y %H:%M"
  )
end
