var kupferwerk = kupferwerk || {};
kupferwerk.component = kupferwerk.component || {};
kupferwerk.component.behaviour = kupferwerk.component.behaviour || {};

// ------------------------------------------------------------------------------------------------
// Global Stuff

kupferwerk.auth_token="NOT SET";

kupferwerk.component.behaviour.AbstractBehaviour = Class.create(KWStandard, {
  site_interface: null,
  initialize: function($super, site_int) {
    site_interface = site_int;
		$super();
  },
  adminStart: function(url, options) { return alert('adminStart is abstract.'); },
  adminSubmit: function(form, options) {
		options = options || {};
		
    new Ajax.Request(form.action, {
        method: form.method,
        parameters: $H(form.serialize(true)).merge(options.parameters || {}),
        asynchronous: true,
        evalScripts: true,
        onSuccess: function(response) {
          if(!site_interface.callIfFunction(options.onSuccess, response))
						site_interface.adminDone();
        },
        onFailure: function(response) {
          site_interface.adminFail(response);
        },
				onComplete: function(response) {
					if(!site_interface.behaviour.callIfFunction(options.onComplete, response))
						site_interface.behaviour.afterAdminSubmit();
						
					return false;
				}
      });

    return false;
  },
	
	beforeAdminSubmit: function() {
		new Effect.Fade('edit_popup_save', {
			duration: 0.2,
			afterFinish: function() {
				new Effect.Appear('edit_popup_busy', {
					duration: 0.2
				});
			}
		});
	},
	
	afterAdminSubmit: function() {
		new Effect.Fade('edit_popup_busy', {
			duration: 0.2,
			afterFinish: function() {
				new Effect.Appear('edit_popup_save', {
					duration: 0.2
				});
			}
		});
	},
	
  adminCancel: function() { return alert('adminCancel is abstract.'); },
  adminDone: function() { return alert('adminDone is abstract.'); },
  adminFail: function(response) {
		site_interface.showResponseMessage('failure', {message: response.responseText});
	}
  
});

// ------------------------------------------------------------------------------------------------
// Basic Page Behaviour

kupferwerk.component.behaviour.AdminPage = Class.create(kupferwerk.component.behaviour.AbstractBehaviour, {
  adminStart: function(url, options) {
    document.location.href = url;

		return false;
  },
  adminCancel: function() {
    document.location.href = document.referrer;

		return false;
  },
  adminDone: function() {
    document.location.href = document.referrer;

		return false;
  }
});

// ------------------------------------------------------------------------------------------------
// Basic Popup Behaviour


kupferwerk.component.behaviour.AdminPopup = Class.create(kupferwerk.component.behaviour.AbstractBehaviour, {
  adminStart: function(url, options) {
		instance = this;
		
    default_options = $H({
      width: 800,
      height: 600
    });
    options = options || {};
    options = default_options.merge($H(options)).toObject();
    
    window_options = 'width=' + options.width + ',height=' + options.height + ',status=0,toolbar=0,resizable=0,location=0,menubar=0';
    
    window.open(url , 'admin' + site_interface.component_id.gsub(/[^0-9a-zA-Z]+/,'_'), window_options);

		return false;
  },
  adminCancel: function() {
    window.close();
		return false;
  },
  adminDone: function() {
    new Ajax.Request(site_interface.actionUrl("index"), {
      method: "get",
      onComplete: function(response) {
        old = opener.document.getElementById(site_interface.component_id + "_component");
        $(old).replace(response.responseText);
        window.close();

				return false;    
      }
    });

		return false;
  }
});

// ------------------------------------------------------------------------------------------------
// Popup With Iframe Behaviour

kupferwerk.component.behaviour.AdminPopupIframe = Class.create(kupferwerk.component.behaviour.AdminPopup, {
  initialize: function($super, site_interface) {
    $super(site_interface);
  },
  adminSubmit: function(form, options) {
    $(form).insert({before: '<iframe width=\"0\" height=\"0\" name=\"postiframe\" id=\"postiframe\" style=\"display: none\"></iframe>'});
    $(form).insert({top: '<input type="hidden" name="comp_admin_behaviour" value="AdminPopupIframe" />'});
    form.target = "postiframe";
    form.submit();
    return false;
  }
});

// ------------------------------------------------------------------------------------------------
// Static helper methods


kupferwerk.component.RuntimeInfo = Class.create({
  initialize: function(id, name, type, lang, prefs, messages, parent) {
    this.component_id = id;
    this.component_name = name;
    this.component_view = type;
    this.component_language = lang;
    this.user_prefs = prefs;
    this.messages = messages;
    this.component_parent_id = parent;
  },
  component_id: '',
  component_name: '',
  component_view: '',
  component_language: '',
  component_parent_id: '',
  user_prefs: {},
  messages: {},
  
  componentPack: function() {
    return this.component_name.split(".")[0];
  },
  
  baseName: function() {
    return this.component_name.split(".")[1];
  },
  
  packJsClassName: function() {
    return kupferwerk.component.getPackClass(this.componentPack());
  },
  
  componentJsClassName: function() {
    return kupferwerk.component.getComponentClass(this.component_name);
  },
  
  getDefaultSiteInterface: function() {
    return  this.componentJsClassName() || this.packJsClassName() || kupferwerk.component.SiteInterface;
  },
  
  getComponentBaseUrl: function() {
    return '/comp/' + this.component_name + '/' + this.component_id + '/' + this.component_view + '/' + this.component_language + '/';
  }
});

kupferwerk.component.DefaultBehaviour = kupferwerk.component.behaviour.AdminPopup;

kupferwerk.component.loaded_files = [];

kupferwerk.component.registeredComponents = {};
kupferwerk.component.registeredPackClasses = {};
kupferwerk.component.registeredComponentClasses = {};
kupferwerk.component.interfaceInstances = {};
kupferwerk.component.defaultInterfaceOptions = {};
kupferwerk.component.componentTree = {};

kupferwerk.component.registerComponent = function(runtimeInfo) {
  kupferwerk.component.registeredComponents[runtimeInfo.component_id] = runtimeInfo;
  kupferwerk.component.componentTree[runtimeInfo.component_id] = runtimeInfo.component_parent_id;
};

kupferwerk.component.registerPackClass = function(pack_name, klass) {
  kupferwerk.component.registeredPackClasses[pack_name] = klass;
};

kupferwerk.component.registerComponentClass = function(component_name, klass) {
  kupferwerk.component.registeredComponentClasses[component_name] = klass;
};

kupferwerk.component.getComponentInfo = function(component_id) {
  comp_info = kupferwerk.component.registeredComponents[component_id];
  if(!comp_info && window.opener) {
    comp_info = window.opener.kupferwerk.component.getComponentInfo(component_id);
  }
  if(!comp_info && window.parent && window.parent != window) {
    comp_info = window.parent.kupferwerk.component.getComponentInfo(component_id);
  }
  return comp_info;
};

kupferwerk.component.getPackClass = function(pack_name) {
  return kupferwerk.component.registeredPackClasses[pack_name];
};

kupferwerk.component.getComponentClass = function(component_name) {
  return kupferwerk.component.registeredComponentClasses[component_name];
};

kupferwerk.component.setDefaultInterfaceOptions = function(component_id, options) {
  if(kupferwerk.component.registeredComponentClasses[component_id]) {
    alert("Warning: setDefaultInterfaceOptions won't do shit, 'caus Default Interface for component " + component_id + " is already instantiated.");
  } else {
    kupferwerk.component.defaultInterfaceOptions[component_id] = options;
  }
};

kupferwerk.component.getDefaultInterface = function(component_id) {
  if(!kupferwerk.component.interfaceInstances[component_id]) {
    comp_info = kupferwerk.component.getComponentInfo(component_id);
    if(comp_info) {
      theKlass = comp_info.getDefaultSiteInterface();
      interfaceOptions = kupferwerk.component.defaultInterfaceOptions[component_id] || {};
      kupferwerk.component.interfaceInstances[component_id] = new theKlass(component_id, interfaceOptions);
    }
  }
  return kupferwerk.component.interfaceInstances[component_id];
};

kupferwerk.component.getDummyDefaultInterface = function(component_name, component_view) {
  component_id = '__dummy_' + component_name.gsub(/\./, '_');
  instance = kupferwerk.component.getDefaultInterface(component_id);
  
  if(!instance) {
    kupferwerk.component.registerComponent(new kupferwerk.component.RuntimeInfo(component_id, component_name, (component_view || 'default'), 'ALL_ALL', {}, {}, 'undefined'));
    instance = kupferwerk.component.getDefaultInterface(component_id);
  }
  
  return instance;
};


// ------------------------------------------------------------------------------------------------
// The Site Inteface

/**
 * @class This class is to controll edit behaviour
 *
 * @description creates a new EditPopup instance
 * @param {integer} component_id the id of the item currently in edit mode
 * @param {options} optional parameters besides the 
 * @option {behaviour} class which sets the current  site behaviour
 */
kupferwerk.component.SiteInterface = Class.create(KWStandard, {
  
  initialize: function(component_id, options) {
    this.options = options || {};
    info = kupferwerk.component.getComponentInfo(component_id);
    this.component_name = info.component_name;
    this.component_id = info.component_id;
    this.component_view = info.component_view;
    this.component_language = info.component_language;
    this.component_parent_id = info.component_parent_id;
    this.component_pack = info.componentPack();
    this.component_base_name = info.baseName();
		this.component_element = this.$('component');
		this.component_title_element = this.$('component_title');
		this.component_spinner_element = this.$('component_spinner');
		this.component_content_element = this.$('component_content');
    
    behaviour = options['behaviour'] ||  kupferwerk.component.DefaultBehaviour;
    this.behaviour = new behaviour(this);  
    
    if(this['_initialize_pack_' + this.component_pack]) {
      this['_initialize_pack_' + this.component_pack]();
    }
    
    if(this['_initialize_component_' + this.component_name]) {
      this['_initialize_component_' + this.component_name]();
    }
  },

  /**
   * options hash set through constructor
   */
  options: {},

	/**
	 * the component itself als extended prototype object
	 */
	component_element: 0,
  
	/**
	 * the component title als extended prototype object
	 */
	component_title_element: 0,
	
	/**
	 * the component spinner als extended prototype object
	 */
	component_spinner_element: 0,
	
	/**
	 * the component content als extended prototype object
	 */
	component_content_element: 0,
  
  /**
  * the component name
  * @ignore
  */
  component_name: 0,

  /**
  * the component id
  * @ignore
  */
  component_id: 0,

  /**
  * the view type to display
  * @ignore
  */
  component_view: 0,

  /**
   * the langugae to display
   */
   component_language: '',

   /**
    * the id of the parent in a component tree
    */
   component_parent_id: '',

   /**
    * the pack of the component
    */
   component_pack: '',
   
   /**
    * the base name without pack
    */
   component_base_name: '',
   
  /**
  * the behaviour
  * @ignore
  */
  behaviour: 0,

  actionUrl: function(action_name, additional_args) {
    additional_args = additional_args || '';
		
		if(typeof additional_args == 'object')
			additional_args = Object.toQueryString(additional_args);
		
		if(!additional_args.startsWith('?'))
			additional_args = '?' + additional_args;

		// WORKAROUND: Added timestamp cause of a firefox 3 bug (caches ajax-requests)
    return '/comp/' + this.component_name + '/' + this.component_id + '/' + this.component_view + '/' + this.component_language + '/' + action_name + additional_args + '&' + Date.parse(new Date);
  },
  
  /**
   * returns the interface of the parent of this component or nil
   */
  parentInterface: function() {
    kupferwerk.component.getDefaultInterface(this.component_parent_id);
  },
  
  /**
   * send a message with parameters to the specified component. if component_id is omitted, the parent component is notified
   */
  notifyComponent: function(event_name, parameters, component_id) {
    component_id = component_id || this.component_parent_id;
    iface = kupferwerk.component.getDefaultInterface(component_id);
    if(iface) {
      iface.processNotification(event_name, parameters, this.component_id);
    }
  },
  
  /**
   * receives component notifications. default implementation does nothing.
   * If you override this method, always call super if you dont process a message.
   */
  processNotification: function(event_name, parameters, sender_component_id) {
    
  },

  /**
   * Starts editing the properties of the component.
   * Uses the current behaviour to do this.
   */
  adminStart: function(action, additional_args, options) {
    ret = null;
    if(this.behaviour.beforeAdminStart) { this.behaviour.beforeAdminStart(); }
    if(this.behaviour.adminStart) { ret = this.behaviour.adminStart(this.actionUrl(action, additional_args), options); } else { alert("missing adminStart!"); }
    if(this.behaviour.afterAdminStart) { this.behaviour.afterAdminStart(); }
    return ret;
  },

  /**
   * Submits an admin edit form to the default url
   */
  adminSubmit: function(form, options) {
    ret = null;
    if(this.behaviour.beforeAdminSubmit) { this.behaviour.beforeAdminSubmit(); }
    ret = this.behaviour.adminSubmit(form, options);
    if(this.behaviour.afterAdminSubmit) { this.behaviour.afterAdminSubmit(); }
    return ret;
  },

  /**
   * cancel using the admin form
   */
  adminCancel: function() {
    ret = null;
    if(this.behaviour.beforeAdminCancel) { this.behaviour.beforeAdminCancel(); }
    if(this.behaviour.adminCancel) { ret = this.behaviour.adminCancel(); } else { alert("missing adminCancel!"); }
    if(this.behaviour.afterAdminCancel) { this.behaviour.afterAdminCancel(); }
    return ret;
  },

  /**
   * admin form is completed
   */
  adminDone: function() {
    ret = null;
    if(this.behaviour.beforeAdminDone) { this.behaviour.beforeAdminDone(); }
    if(this.behaviour.adminDone) { ret = this.behaviour.adminDone(); } else { alert("missing adminDone!"); }
    if(this.behaviour.afterAdminDone) { this.behaviour.afterAdminDone(); }
    return ret;
  },
  
  /**
   * admin form is failed
   */
  adminFail: function(response) {
    ret = null;
    if(this.behaviour.beforeAdminFail) { this.behaviour.beforeAdminFail(); }
    if(this.behaviour.adminFail) { ret = this.behaviour.adminFail(response); } else { alert("missing adminFail!"); }
    if(this.behaviour.afterAdminFail) { this.behaviour.afterAdminFail(); }
    return ret;
  },

	$: function(element) {
		if (arguments.length > 1) {
	    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
	      elements.push($(arguments[i]));
	    return elements;
	  }
	  if (Object.isString(element))
	    element = document.getElementById(this.component_id + '_' + element);
	  return Element.extend(element);
	},
	
  $F: function(element) {
    element = this.$(element);
    var method = element.tagName.toLowerCase();
    return Form.Element.Serializers[method](element);
  },

	showResponseMessage: function(message_status, options) {
		options = options || {};
		
		var response_message = null;
		if(options.response_message)
			response_message = options.response_message;
		else if($('response_message'))
			response_message = $('response_message');
		else if($('response_message_box'))
			response_message = $('response_message_box');
		else
			return alert('Please insert a response message container with id="response_message"!');

		$w('information success warning failure').each(function(status) {
			$(response_message).removeClassName('response_message_' + status);
		});
		
		response_message.addClassName('response_message_' + message_status);
		response_message_content = response_message.select('.response_message_content').first() || response_message;
		response_message_content.update(options.message || 'Please wait while your request will be performed…');
		duration = options.duration || (0.2);
		
		var instance = this;
		new Effect.BlindDown(response_message, {
			duration: duration,
			afterFinish: function() {
				response_message.select('a.response_message_close').first().onclick = function() {
					return instance.hideResponseMessage(options);
				};
				response_message.scrollTo();
			}
		});
		
		if(options.hide_after && options.hide_after > 0) {
			new Effect.BlindUp(response_message, {
				duration: duration,
				delay: options.hide_after
			});
		}
		
		return false;
	},
	
	hideResponseMessage: function(options) {
		options = options || {};
		
		var response_message = null;
		if(options.response_message)
			response_message = options.response_message;
		else if($('response_message'))
			response_message = $('response_message');
		else if($('response_message_box'))
			response_message = $('response_message_box');
		else
			return alert('Please insert a response message container with id="response_message"!');
			
		new Effect.BlindUp(response_message, {
			duration: options.duration || 0.2
		});
		
		return false;
	},
	
	switchNavigation: function(element, url) {
		element = $(element);
		list = element.up(1);
		list_element = $(element).up();

		if(!list_element.hasClassName('active')) {
			container = $();

			if(this.ajax_request)
				this.ajax_request.transport.abort();

			this.ajax_request = new Ajax.Request(url, {
				method: 'get',
				onLoading: function(request) {
					new Effect.Fade('edit_popup_save', {
						duration: 0.2,
						afterFinish: function() {
							new Effect.Appear('edit_popup_busy', {
								duration: 0.2
							});
						}
					});
				},
				onSuccess: function(request) {
					$('edit_popup_content_for_component').update(request.responseText);
					list.select('li.active').invoke('removeClassName', 'active');
					list_element.addClassName('active');
				},
				onComplete: function(request) {
					new Effect.Fade('edit_popup_busy', {
						duration: 0.2,
						afterFinish: function() {
							new Effect.Appear('edit_popup_save', {
								duration: 0.2
							});
						}
					});
				}
			});
		}
	}
	
});

// ------------------------------------------------------------------------------------------------
// Easy Subclassing Siteinterface

CreatePackSiteInterface = function(pack_name, obj) {
  if(obj['initialize']) {
    obj['_initialize_pack_' + pack_name] = obj['initialize'];
  }
  
  obj['initialize'] = function($super, component_id, options) {
    $super(component_id, options);
  };

  newClass = Class.create(kupferwerk.component.SiteInterface, obj);

  kupferwerk.component.registerPackClass(pack_name, newClass);

  return newClass;
};

CreateComponentSiteInterface = function(component_name, obj) {
  if(obj['initialize']) {
    obj['_initialize_component_' + component_name] = obj['initialize'];
  }
  
  obj['initialize'] = function($super, component_id, options) {
    $super(component_id, options);
  };
  
  packName = component_name.split(".")[0];
  baseClass = kupferwerk.component.getPackClass(packName) || kupferwerk.component.SiteInterface;

  newClass = Class.create(baseClass, obj);
  
  kupferwerk.component.registerComponentClass(component_name, newClass);
  
  return newClass;
};

// -------------------------------------------------------------------------------------------------

// Applicationspecific Configuration

kupferwerk.component.DefaultBehaviour = kupferwerk.component.behaviour.AdminPopupIframe;


function setDefaultInterfaceOptions(component_id, options) {
  kupferwerk.component.setDefaultInterfaceOptions(component_id, options);
}
