function objMetromap() {
    var stations = [];
    var regions = [];
    var points = [];
    var markers = [];
    var underlines = [];
    var lineMarkers = [];
    var bullits = [];
    var container = null;
    var pointsMap = null;
    var mainDiv = null;
    var callbackSubmit = null;
    var callbackChangePoints = null;
    this.setStations = function(fstations) {
        stations = fstations;
        return this;
    }
    this.setRegions = function(fregions) {
        regions = fregions;
        return this;
    }
    this.setContainer = function(fcontainer) {
        container = fcontainer;
        return this;
    }
    this.setCallbackSubmit = function(callback) {
        callbackSubmit = callback;
        return this;
    }
    this.setCallbackChangePoints = function(callback) {
        callbackChangePoints = callback;
        return this;
    }
    this.load = function(points) {
        for(i in points) addCheckbox(points[i]);
        return this;
    }
    function makePoints() {
	stations.sort(function(a,b){return a[0]-b[0]});
	for(var i = 0; i < stations.length; i++) {
            if (points[stations[i][0]] == null) {
		points[stations[i][0]] = new Array();
		points[stations[i][0]].push(0);
            }
            points[stations[i][0]].push(i);
	}
    }
    function drawStations() {
	for(var i = 0; i < stations.length; i++) {
            markers[i] = $('<img>')
                .attr({src: '/images/dot.gif', number: i})
                .css({position: 'absolute', left: stations[i][2]+'px', top: stations[i][3]+'px'})
                .click(function() {switchCheckbox(stations[$(this).attr('number')][0])})
            ;
            underlines[i] = $('<div>')
                .addClass('underline')
                .css({left:stations[i][4], top:stations[i][7], width:stations[i][6] - stations[i][4]})
            ;
            var a = $('<area>')
                .attr({
                    shape: 'rect',
                    title: stations[i][1],
                    coords: stations[i][4] + ',' + stations[i][5] + ',' + stations[i][6] + ',' + stations[i][7],
                    number: i
                })
                .click(function() {switchCheckbox(stations[$(this).attr('number')][0])})
                .mouseover(function() {mainDiv.append(underlines[$(this).attr('number')]);})
                .mouseout(function() {underlines[$(this).attr('number')].remove();})
            ;
            pointsMap.append(a);
	}
    }
    function switchCheckbox(num) {
	if (points[num] != null)
	{
		if (points[num][0] == 0)
			addCheckbox(num);
		else
			removeCheckbox(num);
	}
	updateSample();
    }
    function addCheckbox(n) {
        if (typeof(points[n])!='undefined') {
            points[n][0] = 1;
            for(var i = 1; i < points[n].length; i++)
                    mainDiv.append(markers[points[n][i]]);
            if (callbackChangePoints) callbackChangePoints(getSelectedPoints());
        }
    }
    function removeCheckbox(n) {
	points[n][0] = 0;
	for(var i = 1; i < points[n].length; i++){
            markers[points[n][i]].remove();
	}
        if (callbackChangePoints) callbackChangePoints(getSelectedPoints());
    }
    function switchRegion(num) {
	if (regions[num] != null)
	{
		if (regions[num][0] == 0)
		{
			addRegion(num);
			if (num == 2)
				addRegion(1);
		}
		else
		{
			removeRegion(num);
			if (num == 2)
				removeRegion(1);
		}
	}
	updateSample();
    }


    function addRegion(n) {
	if (lineMarkers[n] != null)
		mainDiv.append(lineMarkers[n]);
	if (bullits[n] != null)
		bullits[n].css({visibility: 'visible'});
	regions[n][0] = 1;
	for(var i = 2; i < regions[n].length; i++)
		addCheckbox(regions[n][i]);
    }


    function removeRegion(n) {
	if (lineMarkers[n] != null)
		lineMarkers[n].remove();
	if (bullits[n] != null)
		bullits[n].css({visibility: 'hidden'});
	regions[n][0] = 0;
	for(var i = 2; i < regions[n].length; i++)
		removeCheckbox(regions[n][i]);
    }

    function drawLineMarkers() {
	var lm = [
		[3,173,86,186,99,'a1',172,86],
		[4,188,7,201,20,'a1',187,7],
		[5,313,7,326,20,'a1',312,7],
		[6,387,7,400,20,'a1',386,7],
		[7,487,7,500,20,'a1',486,7],
		[8,506,116,519,129,'a1',505,116],
		[9,506,216,519,229,'a1',505,216],
		[10,487,646,500,659,'a2',486,645],
		[11,404,606,417,619,'a2',403,605],
		[12,387,659,400,672,'a2',386,658],
		[13,287,670,300,683,'a2',286,669],
		[14,188,636,201,649,'a2',187,635],
		[15,84,626,97,639,'a2',83,625],
		[16,14,134,27,147,'a1',13,134],
		[17,0,221,13,234,'a3',0,220],
		[18,275,714,288,727,'a2',274,713]
	]
	for(var i = 0; i < lm.length; i++){
		var a = document.createElement('AREA');
		a.shape = 'rect';
		a.title = regions[lm[i][0]][1];
		a.coords = lm[i][1] + ',' + lm[i][2] + ',' + lm[i][3] + ',' + lm[i][4];
		a.onclick = new Function('switchRegion(' + lm[i][0] + ')');
		pointsMap.append(a);

		lineMarkers[lm[i][0]] = $('<img>')
                    .attr({src: '/images/' + lm[i][5] + '.gif', number: i})
                    .css({position: 'absolute', left: lm[i][6], top: lm[i][7]})
                    .click(function(){switchRegion(lm[$(this).attr('number')][0])})
                ;
	}
    }
    function initMapButtons() {
	var r = document.getElementById('regions')
	for (var i in regions){
		var n = document.createTextNode(regions[i][1])
                var d = $('<div>')
                    .attr({id: 'n'+i, number: i})
                    .click(function(){switchRegion($(this).attr('number'))})
                ;
		$(r).append(d);
		bullits[i] = $('<img>')
                    .attr({src: '/images/bullit.gif'})
                    .addClass('bullit');
                ;
		d.append(bullits[i]);
		d.append($(n));
	}
    }
    function clearPoints() {
            for(var j in regions){
                    if(regions[j][0] == 1)
                            removeRegion(j);
            }
            for(var i in points){
                    if(points[i][0] == 1)
                            removeCheckbox(i);
            }
    }
    function loadSelection() {
//            var l = maskToList(stationMask.value);
            var l = maskToList('');
            for(var i = 0; i < l.length; i++){
                    if(points[l[i]] != null)
                            addCheckbox(l[i]);
            }
            updateSample();
    }
    function updateSample() {
	var s = new Array();
	for(var i in points){
		if(points[i][0] == 1)
			s.push(i);
	}
    }
    function listToMask(l) {
	var mask = '';
	var bb = new Array(); // массив с номерами byte и bit
	var maxByte = 0;
	for(var i in l)
	{
		bb[i] = new Array();
		maxByte = bb[i][0] = Math.floor((l[i] - 1) / 8) + 1;
		bb[i][1] = Math.pow(2,(((l[i] % 8)==0) ? 8 : (l[i] % 8))-1);
	}
	for(var j = 1; j <= maxByte; j++)
	{
		var t = new Array();
		for(var k in bb)
		{
			if (bb[k][0] == j)
				t.push(bb[k][1]);
			if (bb[k][0] > j)
				break;
		}
		mask = bit(t) + mask;
	}
	return mask;
    }

    function getSelectedPoints() {
        var selectedPoints = [];
	for(var i in points) if(points[i][0] == 1) selectedPoints.push(i);
        return selectedPoints;
    }
    function inArray(value, arr) {
        for(var i in arr) if(arr[i]==value) return true;
        return false;
    }
    this.getSelectedStations = function() {
        var points = getSelectedPoints();
        var selectedStations = [];
        for(var i in stations) {
            if (inArray(stations[i][0], points)) selectedStations.push(stations[i][1]);
        }
        return selectedStations;
    }
    function bit(a) {
	var r = '00'
	if (a.length > 0)
	{
		var n = 0;
		for(var i in a)
		{
			if (a[i] != 0)
				n = n + a[i];
		}
		r = n.toString(16);
		if (r.length == 1)
			r = '0' + r;
	}
	return r;
    }


    function maskToList(m) {
	var list = new Array();
	if (m.length >= 2)
	{
		var pieces = new Array();
		for(var i = 0; i < m.length; i += 2)
			pieces.push(m.substr(i,2));
		pieces.reverse();
		for(var j in pieces)
			list = list.concat(bbToInt(j,parseInt(('0x' + pieces[j]),16)));
	}
	return list;
    }


    function bbToInt(byte,bit) {
	var numbers = new Array();
	var i = 1;
	while(bit > 0)
	{
		if ((bit & 1) == 1)
			numbers.push((i + byte*8));
		bit = (bit >> 1);
		i++;
	}
	return numbers;
    }
    function submit() {
        
    }
    this.create = function() {
	var code = '<div id="metro_">';
	code += '<img src="/images/map.gif" usemap="#metromap" style="border:0px">';
	code += '<map name="metromap" id="map"></map>';
	code += '<div class="rside"><div id="regions"></div></div>';
	code += '<div style="font-size:12px;position:absolute;top:9px;right:0px;">';
	code += '<input type="reset" value="Очистить всё" style="padding:3px;">';
	code += '<input type="submit" value="Выбрать" style="padding:3px;">';
	code += '<input type="submit" value="Закрыть" style="padding:3px;"></div>';
	code += '</div>';
	code += '</div>';
        $(container).html(code);
        mainDiv = $('#metro_');
        pointsMap = $('#map');
        $('#metro_ input[type=reset]').click(function(){clearPoints();updateSample();return false;});
        $('#metro_ input[type=submit]')
            .click(function(){
                if (callbackSubmit) callbackSubmit(getSelectedPoints());
            })
        ;

/*
        mainDiv = $('<div>').attr('id', 'metro');
        var metroImage = $('<img>').attr({src:'/images/map.gif', usemap: '#metromap'}).css('border', '0px');
        pointsMap = $('<map>').attr({name: 'metromap', id:'map'});
        var rside = $('<div class="rside"><div id="regions"></div></div>');
        var divRegions = $('<div id="regions">');
        var inputReset = $('<input type="reset">')
            .css({margin: '10px'})
            .val('Очистить всё')
            .click(function(){clearPoints();updateSample();return false;})
        ;
        var inputSubmit = $('<input type="submit" value="Сохранить и закрыть" style="position:absolute;bottom:10px;right:10px">')
            .click(function(){
                if (callbackSubmit) callbackSubmit(getSelectedPoints());
            })
        ;

        rside.append(divRegions).append(inputReset);
        mainDiv.append(metroImage).append(pointsMap).append(rside).append(inputSubmit);
        $(container).html(mainDiv);
*/
        makePoints();
        drawStations();
	drawLineMarkers();
	initMapButtons();
	clearPoints();
	loadSelection()
	updateSample();
        return this;
    }

}
