var application = function () {
	var aimToPoint;
	var sw_x, sw_y, ne_x, ne_y;
	
	var editMode = false;
	var showTipyNaVylet = false;
	
	return {
		aimTo : function (point) {
			aimToPoint = point;
		},
		setViewPort : function (psw_x, psw_y, pne_x, pne_y) {
			sw_x = psw_x;
			sw_y = psw_y;
			ne_x = pne_x;
			ne_y = pne_y;
		},
		setEditMode : function () {
			editMode = true;
		},
		showTipyNaVylet : function () {
			showTipyNaVylet = true;
		},
		/**
		 * Sestaveni objektu cele aplikace dohromady. Metoda vraci Launcher, nad kterym staci
		 * jiz zavolat jen metodu run.
		 */
		getLauncher : function () {			
			var searchModel = vyletnik.search.Model();
			var filterModel = vyletnik.filter.Model();
	
			var filterFactory = vyletnik.filter.Factory(filterModel);
			var filterPointShowingFactory = vyletnik.filter.PointShowingFactory();
			var filterPointShower = filterPointShowingFactory.getPointShower();
			var filterPointsClearedReporter = filterPointShowingFactory.getPointsClearedReporter();
			var filterPointsSettedReporter = filterPointShowingFactory.getPointsSettedReporter();
			
			var searchPointShowingFactory = vyletnik.search.PointShowingFactory();
			var searchPointShower = searchPointShowingFactory.getPointShower();
			var searchPointsClearedReporter = searchPointShowingFactory.getPointsClearedReporter();
			var searchPointsSettedReporter = searchPointShowingFactory.getPointsSettedReporter();	
				
			var mapEngine = vyletnik.map.google.MapEngine(vyletnik.urlControl.getPositionUrlSetter());	
			var detailZoomer = mapEngine.getDetailZoomer();
			var pointDetailGetter = vyletnik.PointDetailGetter(detailZoomer);
			var focalizer = mapEngine.getFocalizer();
			var focalizerWhichDontSetUrl = mapEngine.getFocalizerWhichDontSetUrl();
			var mapInitializer = mapEngine.getInitializer(filterFactory.getViewPortCriteriaModifier());
			var pointsHandlingAgent = mapEngine.getPointsHandlingAgent(pointDetailGetter);
			var infoWindowShower = mapEngine.getInfoWindowShower(pointDetailGetter);
			var okoliBoundsGetter = mapEngine.getOkoliBoundsGetter();
			
			pointsHandlingAgent.addPointsSettedReporter(filterPointsSettedReporter, 'filter');
			pointsHandlingAgent.addPointsSettedReporter(searchPointsSettedReporter, 'search');
			pointsHandlingAgent.addPointsClearedReporter(filterPointsClearedReporter, 'filter');
			pointsHandlingAgent.addPointsClearedReporter(searchPointsClearedReporter, 'search');
			
			var loadingBar = vyletnik.ui.LoadingBar();	
			var layerManager = vyletnik.ui.LayerManager();
			var findedResultModel = vyletnik.search.ResultModel(searchPointShower);
	
			var focalizerByModel = vyletnik.search.FocalizerByModel(focalizer, searchModel);
			
			var searchUrlStore = vyletnik.urlControl.getSearchUrlStore();
			var tabPageUrlStore = vyletnik.urlControl.getTabPageUrlStore();
			
			var popuper = vyletnik.ui.Popuper();
			
			var searchFailedPopup = popuper.getPopup('Hledané slovo je příliš krátké. Zadejte 3 a více znaků ...');

			var topicsPanel = vyletnik.TopicsPanel();

			var nextPointInvokerAgent = vyletnik.search.NextPointInvokerAgent(findedResultModel);
			var boundsDrawer = mapEngine.getBoundsDrawer();
			var okoliSearchFailedPopup = popuper.getPopup('Vyberte prosím druhy vyhledávaných inormací v okolí a akci opakujte.');
			var okoliSearchInvoker = vyletnik.search.vokoli.Invoker(findedResultModel, loadingBar, nextPointInvokerAgent, tabPageUrlStore, okoliBoundsGetter, boundsDrawer, okoliSearchFailedPopup);
			
			var okoliUrlStore = vyletnik.urlControl.getHledaniOkoliUrlsSetter(searchUrlStore);
			var okoliPanel = vyletnik.search.vokoli.Panel(okoliSearchInvoker, okoliUrlStore, okoliBoundsGetter, topicsPanel, layerManager);
			
			var filterInvoker = vyletnik.filter.Invoker(loadingBar, filterPointShower);
			
			var filterabilityPopup = popuper.getPopup('Pro zobrazení bodů na mapě je nutné mít větší přiblížení');
				
			var mapPanel = vyletnik.MapPanel('#mapPanel', mapInitializer);
			var mainForm = vyletnik.MainForm(mapPanel);

			var turistickeCileTopicsCategories = vyletnik.ui.Categories(layerManager);
			var sluzbyTopicsCategories = vyletnik.ui.Categories(layerManager);
			var turistickeCileTopicsPanel = vyletnik.filter.TuristickeCilePanel(
					turistickeCileTopicsCategories,
					topicsPanel,
					filterFactory.getTuristickeCileTopicsCriteriaModifier(),
					filterModel.getTuristickeCileSerializeGetter(),
					vyletnik.urlControl.getTuristickeCileFilterUrlSetter());
			var sluzbyTopicsPanel = vyletnik.filter.SluzbyPanel(
					sluzbyTopicsCategories,
					topicsPanel,
					filterFactory.getSluzbyTopicsCriteriaModifier(),
					filterModel.getSluzbySerializeGetter(),
					vyletnik.urlControl.getSluzbyFilterUrlSetter());

			var filterResetor = vyletnik.filter.Resetor(turistickeCileTopicsPanel, sluzbyTopicsPanel);
			var searchInvoker = vyletnik.search.Invoker(searchModel, findedResultModel, searchFailedPopup, loadingBar, filterResetor, nextPointInvokerAgent, tabPageUrlStore, focalizerWhichDontSetUrl, infoWindowShower);

			var phraseControl = vyletnik.search.PhraseControl(searchModel, searchInvoker, searchUrlStore, searchModel);
			var locationSelectControl = vyletnik.search.LocationSelectsControl(searchModel, focalizerByModel);

			var rejstrikCategories = vyletnik.search.RejstrikMistCategories(vyletnik.ui.Categories(), searchModel);
			var sluzbyCategories = vyletnik.search.SluzbyCategories(vyletnik.ui.Categories(), searchModel);
			var turistickeInfoCategories = vyletnik.search.TuristickeInfoCategories(vyletnik.ui.Categories(), searchModel);
			var adresyCategory = vyletnik.search.AdresyCategory(searchModel);
			
			var finderPanel = vyletnik.search.CriteriaPanel(
				mainForm,
				phraseControl,
				locationSelectControl,
				rejstrikCategories,
				sluzbyCategories,
				turistickeInfoCategories);
			
			mainForm.setFinderPanel(finderPanel);
						
			var findedResultPanel = vyletnik.search.ResultPanel(findedResultModel, layerManager, infoWindowShower);	
			
			var napovedaPopup = vyletnik.ui.NapovedaPopup();
			var napovedaButton = vyletnik.ui.NapovedaButton(napovedaPopup);
			var suggestContentLoader = vyletnik.ui.suggest.ContentLoader();
			var suggestPanel = vyletnik.ui.Suggest('#fulltext_pharse', suggestContentLoader);
			var initializer = vyletnik.ui.Initializer([mapPanel,
			                                           finderPanel,
			                                           findedResultPanel,
			                                           turistickeCileTopicsPanel,
			                                           sluzbyTopicsPanel,
			                                           loadingBar,
			                                           popuper,
			                                           napovedaButton,
			                                           vyletnik.DetailInMapPanel(),
			                                           okoliPanel,
			                                           suggestPanel,
			                                           adresyCategory]);
	
			vyletnik.FocalizationAgent(locationSelectControl, focalizerByModel).run();
			vyletnik.filter.FilterabilityPopupAgent(filterFactory.getFilterabilityChangeReporter(), filterabilityPopup).run();
			vyletnik.filter.InvokerAgent(filterFactory.getFilteringReporter(), filterInvoker).run();
						
			nextPointInvokerAgent.run();
			
			searchHistoryChangeListener = vyletnik.search.HistoryChangeListener(phraseControl, locationSelectControl, rejstrikCategories, sluzbyCategories, turistickeInfoCategories, adresyCategory, searchInvoker);				
			vokoliSearchChangeListener = vyletnik.search.vokoli.HistoryChangeListener(okoliSearchInvoker);
			var historyChangeListener = [searchHistoryChangeListener,
			                             mapEngine.getHistoryChangeListener(),
			                             turistickeCileTopicsPanel.getHistoryChangeListener(),
			                             sluzbyTopicsPanel.getHistoryChangeListener(),
			                             vokoliSearchChangeListener];
			vyletnik.urlControl.getUrlRequestAgent(historyChangeListener).run();
			
			//definice pluginu, ktere se spousti ihned po incializaci mapy
			var plugins = [];
			if (aimToPoint) {
				plugins[plugins.length] = {
					run : function () {
						if (!aimToPoint.id) {
							aimToPoint.detailGetter = vyletnik.adhoc.PointDetailGetter(aimToPoint, detailZoomer);
						}
						//zobrazit bod na mape
						pointsHandlingAgent.addPointsSettedReporter({
							registerListener : function (listener) {
								listener([aimToPoint]);
							}
						}, 'detail');
						//zacilit na nej mapu
						mapEngine.getDetailZoomerWhichDontSetUrl().zoomTo(aimToPoint, 14);
						infoWindowShower.show(aimToPoint);
					}
				};
			}
			if (sw_x) {
				plugins[plugins.length] = {
					run : function () {
						focalizerWhichDontSetUrl.focalize(sw_x, sw_y, ne_x, ne_y);
					}
				};				
			}
			if (editMode === true) {
				plugins[plugins.length] = {
					run : function () {
						var mapClickReporter = mapEngine.getClickReporter();
						var pointEditer = vyletnik.PointEditer();
						mapClickReporter.addListener(function (event) {
							pointEditer.setLatLng(event.lat, event.lng);
						});
					}
				};				
			}
			if (showTipyNaVylet === true) {
				//zaskrtnout tipy na vylet
				plugins[plugins.length] = {
					run : function () {					
						var openingFiltering = vyletnik.filter.OpeningFiltering(turistickeCileTopicsPanel);
						openingFiltering.filter();
					}
				};	
			}
			return vyletnik.Launcher(initializer, plugins);
		}
	};
}();

