/*
 * Copyright (c)  2006-2007 Maskat Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
maskat.lang.Class.declare("maskat.event.EventDispatcher", {

	initialize: function(){
		this.url = null;
		this.headers = null;
		this.handlers = {};
		this.controller = null;
		this.layout = null;
		this.logger = maskat.log.LogFactory.getLog("maskat.event");
	},

	setController: function(controller){
		this.controller = controller;
	},

	setLayout: function(layout){
		/* レイアウトのイベントハンドラを登録 */
		this.handlers[layout.getWidgetId()] = this.events;

		var widget;
		var handler;
		for (var widgetId in this.handlers) {
			/*
			 * 参照整合性チェック:
			 *
			 * イベント定義 XML に記述されたマスカット部品がレイアウトに
			 * 存在しない場合には警告メッセージを出力する
			 */
			widget = layout.getWidget(widgetId) || layout.getVariable(widgetId);
			if (typeof(widget) == "undefined") {
				this.logger.warn(maskat.util.Message.format("MISSING_WIDGET", {
					layoutId: layout.getWidgetId(),
					widgetId: widgetId
				}));
			}

			/* イベントハンドラの参照を解決する */
			for (var eventType in this.handlers[widgetId]) {
				handler = this.handlers[widgetId][eventType];
				handler.setDispatcher(this);
				if (handler.ref) {
					this.resolveHandlerReference(handler);
				}
			}
		}
	},

	resolveHandlerReference: function(handler){
		var eventRef = this.eventRefs[handler.ref];

		if (eventRef.headers) {
			handler.headers = eventRef.headers.concat(handler.headers || []);
		}

		if (!handler.marshaller) {
			handler.marshaller = eventRef.marshaller;
		}

		if (!handler.unmarshaller) {
			handler.unmarshaller = eventRef.unmarshaller;
		}
	},

	handleEvent: function(event){
		if (event.widget == event.layout && event.type == "onload") {
			this.setLayout(event.layout);
		}

		var handler = maskat.lang.Object.find([event.widgetId, event.type],
			this.handlers);
			
		if (handler) {
			try {
				handler.startHandle(event);
			} catch (e) {
				event.cancel = true;
				if (e instanceof maskat.lang.InterruptedError) {
					var msg = e.getMessages ? e.getMessages().join("\n") : e.message;
					this.logger.info(msg);
				} else {
					this.logger.error(e.message);
				}
			}
		}
	},

	finishHandle: function(event) {
		if (!event.cancel && this.controller) {
			this.controller.handleEvent(event);
		}
	}

});
