function gp_maps(options) {
	var viewer = $('#viewer');

	viewer.options = options;
	viewer.options.x = null;
	viewer.options.y = null;
	viewer.options.defaultZoom = options.zoom;
	viewer.options.state = 'minimized';
	viewer.options.minimized = {};
	viewer.options.maximized = {};
	viewer.options.mouse = {};

	gp_redraw_viewer(viewer);

	$(window).resize(function() {
			if (viewer.options.state == 'maximized') {
				var t = $(window).scrollTop() + 'px';

				var ww = $(window).width() + 'px';
				var wh = $(window).height() + 'px';

				viewer.css({
						position: 'absolute',
						top: t,
						left: 0,
						width: ww,
						height: wh,
						zIndex: 9000
				});
			}

			gp_redraw_viewer(viewer);
	});

	if ($.browser.msie) {
		$('div.map', viewer).draggable({
			cursor: 'move',
			stop: function(e, ui) {
				var position = $(this).position();
				viewer.options.x = position.left;
				viewer.options.y = position.top;
				gp_redraw_viewer(viewer);
			}
		});

	} else {
		$('div.map', viewer).draggable({
			cursor: 'move',
			stop: function(e, ui) {
				var position = $(this).position();
				viewer.options.x = position.left;
				viewer.options.y = position.top;
				gp_redraw_viewer(viewer);
			},
			drag: function(e, ui) {
				var position = $(this).position();
				viewer.options.x = position.left;
				viewer.options.y = position.top;
				gp_redraw_viewer(viewer);
			}
		});
	}

	$('div.up', viewer).click(function() {
			gp_panview(viewer, 'up', 100);
	});

	$('div.down', viewer).click(function() {
			gp_panview(viewer, 'down', 100);
	});

	$('div.left', viewer).click(function() {
			gp_panview(viewer, 'left', 100);
	});

	$('div.right', viewer).click(function() {
			gp_panview(viewer, 'right', 100);
	});

	$('div.reset', viewer).click(function() {
			viewer.options.zoom = viewer.options.defaultZoom;
			$('div.zoomcontrol', viewer).slider('value', viewer.options.maxZoom - viewer.options.zoom);
			viewer.options.x = null;
			viewer.options.y = null;
			gp_redraw_viewer(viewer);
	});

	$('div.zoomcontrol', viewer).slider({
			steps: viewer.options.maxZoom,
			max: viewer.options.maxZoom,
			value: viewer.options.maxZoom - viewer.options.zoom,
			orientation: 'vertical',
			slide: function(e, ui) {
					var value = Math.round(ui.value);
					var delta = value - viewer.options.zoom;

					var oldZoom = viewer.options.zoom;

					if (delta > 0) {
						viewer.options.zoom += 1;

					} else {
						viewer.options.zoom -= 1;
					}

					if (viewer.options.zoom > viewer.options.maxZoom) {
						viewer.options.zoom = viewer.options.maxZoom;
					}

					if (viewer.options.zoom < 0) {
						viewer.options.zoom = 0;
					}

					if (viewer.options.zoom != oldZoom) {
						if (delta > 0) {
							viewer.options.x = [viewer.options.x * 2] - [viewer.options.width / 2];
							viewer.options.y = [viewer.options.y * 2] - [viewer.options.height / 2];

						} else {
							viewer.options.x = 0 - [[Math.abs(viewer.options.x) - [viewer.options.width / 2]] / 2];
							viewer.options.y = 0 - [[Math.abs(viewer.options.y) - [viewer.options.height / 2]] / 2];
						}

						gp_redraw_viewer(viewer);
					}
			}
	});

	$('.ui-slider-handle').unbind('keydown');

	$('div.odkaz a', viewer).click(function() {
			window.open(this.href);
			return false;
	});

	$('div.maximize', viewer).click(function() {
			var currentCenterX = viewer.options.x - [viewer.options.width / 2];
			var currentCenterY = viewer.options.y - [viewer.options.height / 2];

			var parents = viewer.parents();

			if (viewer.options.state == 'minimized') {
				viewer.options.state = 'maximized';

				// všetci rodičia musia mať position: static
				var positionsTypes = {};
				$.each(parents, function(i) {
						var parent = $(this);
						positionsTypes[i] = parent.css('position');
						parent.css('position', 'static');

				});
				viewer.options.parentsPositionType = positionsTypes;

				viewer.options.minimized.width = viewer.options.width;
				viewer.options.minimized.height = viewer.options.height;

				$('body').css('overflow', 'hidden');

				var t = $(window).scrollTop() + 'px';

				var ww = $(window).width() + 'px';
				var wh = $(window).height() + 'px';

				$(viewer).css({
						position: 'absolute',
						top: t,
						left: 0,
						width: ww,
						height: wh,
						zIndex: 9000
				});

			} else {
				viewer.options.state = 'minimized';

				$('body').css('overflow', 'auto');

				//obnovenie vlastnosti position
				var positionsTypes = viewer.options.parentsPositionType;
				$.each(parents, function(i) {
						$(this).css('position', positionsTypes[i]);
				});

				$(viewer).css({
						position: 'relative',
						top: 0,
						left: 0,
						width: 'auto',
						height: viewer.options.minimized.height,
						zIndex: 'auto'
				});
			}

			var width = viewer.width();
			var height = viewer.height();

			var x = Math.abs(currentCenterX);
			var y = Math.abs(currentCenterY);

			x = x - Math.round(width / 2);
			y = y - Math.round(height / 2);

			viewer.options.x = 0 - x;
			viewer.options.y = 0 - y;

			gp_redraw_viewer(viewer);
	});

	$('div.stylus', viewer).draggable({
			cursor: 'move',
			containment: 'parent',
			stop: function(e, ui) {
				viewer.options.x = (0 - Math.round(ui.position.left * viewer.options.ratioMapMiniMap));
				viewer.options.y = (0 - Math.round(ui.position.top * viewer.options.ratioMapMiniMap));

				gp_redraw_viewer(viewer, true);
			}
	});

	$(document).bind('keydown', function(e) {
			if (e.altKey == false) {
				return;
			}

			var offset = 10;

			if (e.ctrlKey == true) {
				offset *= 5;
			}

			if (e.shiftKey == true) {
				offset *= 10;
			}

			switch(e.keyCode) {
				case 38:
					gp_panview(viewer, 'up', offset);
					break;
				case 40:
					gp_panview(viewer, 'down', offset);
					break;
				case 37:
					gp_panview(viewer, 'left', offset);
					break;
				case 39:
					gp_panview(viewer, 'right', offset);
					break;
			}

			return false;
	});

	$('div.map').mousemove(function(e) {
			if (viewer.state == 'minimized') {
				var mouseX = e.pageX - viewer.offsetLeft - this.offsetLeft;
				var mouseY = e.pageY - viewer.offsetTop - this.offsetTop;

			} else {
				var mouseX = e.pageX - this.offsetLeft;
				var mouseY = e.pageY - this.offsetTop;
			}

			viewer.options.mouse.x = mouseX;
			viewer.options.mouse.y = mouseY;
	});

	$(viewer).mousewheel(function(event, delta) {
			var oldZoom = viewer.options.zoom;

			if (delta > 0) {
				viewer.options.zoom += 1;

			} else {
				viewer.options.zoom -= 1;
			}

			if (viewer.options.zoom > viewer.options.maxZoom) {
				viewer.options.zoom = viewer.options.maxZoom;
			}

			if (viewer.options.zoom < 0) {
				viewer.options.zoom = 0;
			}

			if (viewer.options.zoom != oldZoom) {
				if (delta > 0) {
					viewer.options.x = [viewer.options.x * 2] - [viewer.options.width / 2];
					viewer.options.y = [viewer.options.y * 2] - [viewer.options.height / 2];

				} else {
					viewer.options.x = 0 - [[Math.abs(viewer.options.x) - [viewer.options.width / 2]] / 2];
					viewer.options.y = 0 - [[Math.abs(viewer.options.y) - [viewer.options.height / 2]] / 2];
				}

				$('div.zoomcontrol', viewer).slider('value', viewer.options.zoom);
				gp_redraw_viewer(viewer);
			}

			event.stopPropagation();
			event.preventDefault();
	});
}

function gp_redraw_viewer(viewer, animate) {
	var options = viewer.options;

	options.width = viewer.innerWidth();
	options.height = viewer.innerHeight();

	$('div.navigation img', viewer).attr('src', options.path + 'mini.png');

	// výpočet veľkosti mapy, veľkosť v dieloch je 2^zoom, zoom sa počíta od 0
	var mapSizeInTiles = Math.pow(2, options.zoom);
	var mapSizeInPixels = mapSizeInTiles * options.tileSize;

	// výpočet maximálneho posunu v jednostlivých súradniciach
	// počíta sa záporná hodnota
	var maxX = 0 - (mapSizeInPixels - options.width);
	var maxY = 0 - (mapSizeInPixels - options.height);

	// kontrola a korekcia medzných hodnôt pozície
	if (options.x > 0) {options.x = 0}
	if (options.x < maxX) {options.x = maxX}
	if (options.y > 0) {options.y = 0}
	if (options.y < maxY) {options.y = maxY}

	// výpočet veľkosti prehliadača v dieloch
	var viewerWidthInTiles = Math.floor(options.width / options.tileSize) + 2;
	var viewerHeightInTiles = Math.floor(options.height / options.tileSize) + 2;

	// korekcia veľkosti, pri výpočte veľkosti vrstvy v dieloch sa veľkosť
	// zvyšuje o dva, preto sa môže stať že vyjde veľkosť väčšia ako celá mapa
	if (mapSizeInTiles < viewerWidthInTiles) {
		var viewerWidthInTiles = mapSizeInTiles;
	}

	if (mapSizeInTiles < viewerHeightInTiles) {
		var viewerHeightInTiles = mapSizeInTiles;
	}

	// ak sú súradnice nastavené na null, vycentruj mapu
	if (options.x == null) {
		options.x = 0 - Math.floor([mapSizeInPixels / 2] - [options.width / 2]);
	}

	if (options.y == null) {
		options.y = 0 - Math.floor([mapSizeInPixels / 2] - [options.height / 2]);
	}

	// výpočet pomeru veľkosti mapy a náhľadu
	var ratioMapMiniMap = mapSizeInPixels / 96;
	options.ratioMapMiniMap = ratioMapMiniMap;
	// výpočet pomeru strán prehliadača
	var viewerRatio = options.width / options.height;

	// korekcie minimálnej a maximálnej veľkosti ukazovateľa polohy
	var stylusWidth = Math.round(options.width / ratioMapMiniMap);
	if (stylusWidth < 16) {
		stylusWidth = 16;
	}
	var stylusHeight = Math.round(stylusWidth / viewerRatio);

	if (stylusWidth > 96) {
		stylusWidth = 96;
	};

	if (stylusHeight > 96) {
		stylusHeight = 96;
	};

	// výpočet pozície v dieloch
	var startTileX = Math.floor(Math.abs(options.x) / options.tileSize);
	var startTileY = Math.floor(Math.abs(options.y) / options.tileSize);

	// korekcie ak je mapa menšia ako prehliadač
	if (mapSizeInPixels < options.width) {
		options.x = Math.floor((options.width - mapSizeInPixels) / 2);
		stylusWidth = 96;
		startTileX = 0;
	}

	if (mapSizeInPixels < options.height) {
		options.y = Math.floor((options.height - mapSizeInPixels) / 2);
		stylusHeight = 96;
		startTileY = 0;
	}

	// výpočet pozície ukazovateľa
	var stylusPositionX = Math.abs(options.x / ratioMapMiniMap);
	var stylusPositionY = Math.abs(options.y / ratioMapMiniMap);

	// ak je ukazovaeľ veľký ako náhľad bude zobrazený na pozícii 0 0
	if (stylusWidth == 96) {
		stylusPositionX = 0;
	}

	if (stylusHeight == 96) {
		stylusPositionY = 0;
	}

	// zobrazenie ukazovateľa
	var stylus = $('div.stylus', viewer);
	stylus.css({
		position: 'absolute',
		display: 'block',
		cursor: 'move',
		top: stylusPositionY + 'px',
		left: stylusPositionX + 'px',
		width: stylusWidth + 'px',
		height: stylusHeight + 'px'
	});

	var map = $('div.map', viewer);

	//označiť staré diely
	$('img', map).addClass('old');

	// vykreslenie mapy
	for (y = 0; y < viewerHeightInTiles; y++) {
		for (x = 0; x < viewerWidthInTiles; x++) {
			var cssClass = 'tile-' + options.zoom + '-' + (x + startTileX) + '-' + (y + startTileY);

			// test či diel už je v mape alebo nie
			var tile = $('img.' + cssClass);
			// ak je, zrušiť označenie že je starý
			if (tile.length > 0) {
				tile.removeClass('old');

			} else {
				// ak nie je ešte v mape tak ho je treba vložiť do mapy
				var tile = new Image();
				tile.width = options.tileSize;
				tile.height = options.tileSize;
				tile.src = options.path + options.zoom + '-' + (x + startTileX) + '-' + (y + startTileY) + '.png';

				$(tile).css({
						position: 'absolute',
						top: ((y + startTileY) * options.tileSize) + 'px',
						left: ((x + startTileX) * options.tileSize) + 'px'
				})

				$(tile).addClass(cssClass);

				map.append(tile);
			}
		}
	}

	// zmazať staré diely
	$('img.old', map).remove();

	map.css({
		position: 'absolute',
		width: mapSizeInPixels + 'px',
		height: mapSizeInPixels + 'px',
		cursor: 'move'
	});

	if (animate == true) {
		map.animate({
			left: options.x + 'px',
			top: options.y + 'px'
		});

	} else {
		map.css({
			left: options.x + 'px',
			top: options.y + 'px'
		});
	}

	viewer.options = options;
};

function gp_panview(viewer, direction, offset) {
	var x = viewer.options.x;
	var y = viewer.options.y;

	switch(direction) {
		case 'left':
			x = x + offset;
			break;

		case 'up':
			y = y + offset;
			break;

		case 'right':
			x = x - offset;
			break;

		case 'down':
			y = y - offset;
			break;
	}

	$('div.map', viewer).animate({
		left: x + 'px',
		top: y + 'px'
	});

	viewer.options.x = x;
	viewer.options.y = y;
	gp_redraw_viewer(viewer, true);
}
