var GMapobj = null;
var Vector1, Vector2;
var SelectCtrl  =null;
var Markers = null;
var NumOfMarkers = null;
var $ = null;

function usertop_main(jquery_rootobj, id_name, lon, lat, zoom) {
    $ = jquery_rootobj;
    var map = new OpenLayers.Map(id_name);
    GMapobj = map;    
    // コントロール（UI）の追加
    // map.addControl( new OpenLayers.Control.OverviewMap() );	// 縮小地図コントロールを追加
    map.addControl( new OpenLayers.Control.ScaleLine() );	// 縮尺距離表示コントロールを作成
    map.addControl( new OpenLayers.Control.Permalink() );	// 地図の状態情報を保持したリンクを作成
    // map.addControl( new OpenLayers.Control.PanZoomBar() );	// ズームスクロールバーを作成
    map.addControl( new OpenLayers.Control.MousePosition() );	// mouse座標を表示するコントロールを追加
    // map.addControl( new OpenLayers.Control.MouseToolbar() );
    map.addControl( new OpenLayers.Control.LayerSwitcher() );	// 地図切り替えのコントロールを追加   

    // Google Mapsを追加
    var gmap = new OpenLayers.Layer.Google("Google Streets",	// the default
					   { numZoomLevels: 20, transitionEffect: 'resize' });
    var ghyb = new OpenLayers.Layer.Google("Google Hybrid",
					   { type: google.maps.MapTypeId.HYBRID, numZoomLevels: 20,
					     transitionEffect: 'resize' });
    map.addLayers([gmap, ghyb]);

    // click event を登録
    OpenLayers.Control.Click = defClickEvt(onClickEvt);
    var click = new OpenLayers.Control.Click();
    map.addControl(click);
    click.activate();

    // 地図の表示位置（中心）と縮尺を指定して表示
    map.setCenter( new OpenLayers.LonLat(lon, lat)
		   .transform( new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject() )
		   , zoom );

    // 登録済みのマーカーを表示
    setMarkerLayers(map);

    // マウスホイールで拡大しないようにする
    /*
    var nav = new OpenLayers.Control.Navigation({'zoomWheelEnabled': false});
    map.addControl(nav);
    nav.activate();
    nav.disableZoomWheel();
    */
    var controls = map.getControlsByClass('OpenLayers.Control.Navigation');
    for(var i = 0; i<controls.length; ++i)
	controls[i].disableZoomWheel(); 

}


/** top.htmlのlightbox設定
 */
function lightbox_main() {
    // $("div#map-rightpain a").lightBox();
    jQuery.superbox();
    jQuery.superbox.settings = {
	boxId: "superbox", // Id attribute of the "superbox" element
	boxClasses: "", // Class of the "superbox" element
	overlayOpacity: .8, // Background opaqueness
	boxWidth: "600", // Default width of the box
	boxHeight: "400", // Default height of the box
	loadTxt: "Loading...", // Loading text
	closeTxt: "Close", // "Close" button text
	prevTxt: "Previous", // "Previous" button text
	nextTxt: "Next" // "Next" button text
    };
}


/** jQueryオブジェクト「$」を作成するメイン関数
 *  これ以後、$をjQueryとして利用できる。
 */
function start_jquery(jquery_rootobj) {
    $ = jquery_rootobj;
}

function onPopCloseEvt(e) {
    SelectCtrl.unselectAll();
}


/** マウスクリックイベントハンドラ
 *  クリックしたポイントにマーカーを表示する。
 */
function onClickEvt(e) {
    var pnt = GMapobj.getLonLatFromViewPortPx(e.xy);
    var marker = new OpenLayers.Feature.Vector( new OpenLayers.Geometry.Point(pnt.lon, pnt.lat)
						.transform(new OpenLayers.Projection("EPSG:4326")) );
    Vector1.addFeatures([marker]);
}


/** data(JSONデータ)を取得し、data.idのIDを持つDIVを書き換える
 */
function setMaker(data, status) {
    alert("div#"+data.id+" :"+data.html);
    $("div#"+data.id).html(data.html);
}


/** OpenLayersの座標系をSRID: 4326座標系に変換する関数。
 */
function trans_point(lon, lat) {
    return new OpenLayers.Geometry.Point(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"));
}


/** 既存のマーカークリック時にコールされるハンドラ
 */
function onMakerSelect(e) {
    var feature = e.feature;
    var divid = feature.id.replace('OpenLayers.Feature.', '');
    var pnt = feature.geometry;
    // $.getJSON("/geo/getaddr/", {"lon": pnt.x, "lat": pnt.y, "id": divid}, setMaker);
    /*
    var html = '<h2> タイトルを入力して下さい </h2> <div id="'
	+ divid + '"> データ取得中 (座標は' + pnt.x + ", " + pnt.y + ")</div>";
    */
    var htmlbase = '<div class="gmap-popup" id="'+divid+'">hogehoge</div>'
    var popup = new OpenLayers.Popup.FramedCloud("chicken",
						 feature.geometry.getBounds().getCenterLonLat(),
						 new OpenLayers.Size(100, 100),
						 htmlbase,
						 null, true, onPopCloseEvt );
    feature.popup = popup;
    GMapobj.addPopup(popup);
    var trans_pnt = trans_point(pnt.x, pnt.y);
    $("div#"+divid).load("/geo/getaddr/", {"lon": trans_pnt.x, "lat": trans_pnt.y, "id": divid});
    // $("div#"+divid).load("/geo/getaddr/", {"lon": pnt.x, "lat": pnt.y, "id": divid});
    // $("div#"+divid).html(json.html);
    $('#status').html(feature.id + "(" + divid + ")がクリックされました。");
    // document.getElementById(divid).innerHTML = "hogehoge";
}


function onMakerUnselect(e) {
    var feature = e.feature;
    if ( feature.popup ) {
	GMapobj.removePopup(feature.popup);
	feature.popup.destroy();
	delete feature.popup;
    }
}


/** マーカーIDを引数に取り、Map右ペイン領域（map-rightpain）に登録フォームを表示する。
 *  右ペインの登録ボタンを押すと、onclickでcreate_place_onclick()が選択される。
 */
function createShopEvt(markerId, lon, lat) {
    $("div#map-rightpain").load("/geo/popup/create_placeform/", {'id': markerId, 'lon': lon, 'lat': lat});
}


/** 既存のマーカークリック時にコールされるハンドラ
 *  dividで検索し、サーバー側で既に登録済みの場合は該当する情報を表示する。
 */
function onMakerSelectOrCreate(e) {
    var feature = e.feature;
    var divid = feature.id.replace('OpenLayers.Feature.', '');
    var pnt = feature.geometry;
    var pkey = 0;
    if ( feature.fid != null )	pkey = feature.fid;
    $('#infomain').html("読み込み中...");
    $('#infomain').load("/geo/popup/getmarker_info/", {"lon": pnt.x, "lat": pnt.y, "id": divid, "pkey": pkey});
}


function defClickEvt(handler) {
    return OpenLayers.Class( OpenLayers.Control, {
	    defaultHanderOptions: {
		'single': true,
		'double': false,
		'pixelTolerance': 0,
		'stopSingle': false,
		'stopDouble': false
	    },
	    initialize: function(options) {
		this.handerOptions = OpenLayers.Util.extend({}, this.defaultHandlerOptions);
		OpenLayers.Control.prototype.initialize.apply(this, arguments);
		this.handler = new OpenLayers.Handler.Click(this, {'click': this.trigger}, this.handerOptions);
	    },
	    // click event handler
	    trigger: handler
	} );
}


function measurement_handler(evt) {
    var geometry = evt.geometry;
    var units = evt.units;
    var order = evt.order;
    var measure = evt.measure;
    var element = document.getElementById('measurement_result');
    var out = "";
    if ( order == 1 ) {
	out += "距離(km): " + measure.toFixed(3) + " (" + units + ")";
    } else {
	out += "距離(km): " + measure.toFixed(3) + " (" + units + "<sup>2</" + "sup>)";
    }
    element.innerHTML = out;
}


function toggleControl(elem) {
    for ( var key in MeasureControls ) {
	var ctrl = MeasureControls[key];
	if ( (elem.value == key) && elem.checked ) {
	    ctrl.activate();
	} else {
	    ctrl.deactivate();
	}
    }
}


function toggleGeodesic(elem) {
    for ( var key in MeasureControls ) {
	var ctrl = MeasureControls[key];
	ctrl.geodesic = elem.checked;
    }
}


var MeasureControls = {}
/** 直線距離とポリゴン領域内の面積を測定するためのコントロールを追加する関数。
 */
function setMeasureControl(mapobj) {
    var sketchSymbolizers = {
	"Point": {
	    pointRadius: 4,
	    graphicName: "square",
	    fillColor: "white",
	    fillOpacity: 1,
	    strokeWidth: 1,
	    strokeOpacity: 1,
	    strokeColor: "#333333"
	},
	"Line": {
	    strokeWidth: 1,
	    strokeOpacity: 1,
	    strokeColor: "#888888",
	    strokeDashstyle: "dash"
	},
	"Polygon": {
	    strokeWidth: 1,
	    strokeOpacity: 1,
	    strokeColor: "#888888",
	    fillColor: "white",
	    fillOpacity: 0.3
	}
    };
    var style = new OpenLayers.Style();
    style.addRules([ new OpenLayers.Rule({symbolizer: sketchSymbolizers}) ]);

    var styleMap = new OpenLayers.StyleMap({"default": style});
    MeasureControls = {
	line: new OpenLayers.Control.Measure(OpenLayers.Handler.Path, {
		persist: true,
		handlerOptions: { layerOptions: {styleMap: styleMap} }
	    }),
	polygon: new OpenLayers.Control.Measure(OpenLayers.Handler.Polygon, {
		persist: true,
		handlerOptions: { layerOptions: {layerOptions: styleMap} }
	    })
    };
    for ( var key in MeasureControls ) {
	var ctrl = MeasureControls[key];
	ctrl.events.on({
		"measure": measurement_handler,
		"measurepartial": measurement_handler
		    });
	mapobj.addControl(ctrl);
    }
}


function createFeatures() {
    var extent = GMapobj.getExtent();
    var features = [];
    for ( var i = 0; i < 10; ++i ) {
	features.push( new OpenLayers.Feature.Vector
		       ( new OpenLayers.Geometry.Point
			 (extent.left + ( extent.right - extent.left) * Math.random(),
			  extent.bottom + (extent.top - extent.bottom) * Math.random()
			  ) ) );
    }
    return features;
}


function markerClickEvt(e) {
    if ( this.popup == null ) {
	this.popup = this.createPopup(this.closeBox);
	map.addPopup(this.popup);
	this.popup.show();
    } else {
	this.popup.toggle();
    }
    OpenLayers.Event.stop(e);
}


/** json形式で取得したマーカー座標、PopUp用のHTML情報を対応付けるハンドラ
 */
function isolateMarkerAndPopup(json, isSuccess) {
    var features = [];
    NumOfMarkers = json.length;

    for ( var i = 0; i < json.length; i++ ) {
	var j = json[i];
	var x_str = json[i].lon;
	var y_str = json[i].lat;
	var x = parseFloat(x_str);
	var y = parseFloat(y_str);
	var lonlat = new OpenLayers.Geometry.Point(x, y)
	    .transform( new OpenLayers.Projection("EPSG:4326"), GMapobj.getProjectionObject() );
	var marker = new OpenLayers.Feature.Vector(lonlat);
	marker.fid = json[i].pkey;

	var htmlbase = '<div class="gmap-popup" style="height: 30px;">'
	    + 'lon: ' + x_str + ' lat: ' + y_str
	    + '</div>';
	var popup = new OpenLayers.Popup.FramedCloud("chicken",
						     marker.geometry.getBounds().getCenterLonLat(),
						     new OpenLayers.Size(100, 100),
						     htmlbase,
						     null, true, onPopCloseEvt );
	
	popup.toggle();
	marker.popup = popup;
	
	GMapobj.addPopup(popup);

	features.push(marker);
    }
    Vector1.addFeatures(features);
    // GMapobj.addLayer(Markers);
}


/** DBに登録されている全マーカーを返す関数。
 *  point（座標）、r（半径）が指定されている場合は、
 *  該当する範囲内でマーカーを検索する。
 *  取得したマーカーはvectorに登録される。
 */
function getMarkers(vector, point, r) {
    var features = [];

    if ( point && r ) {
	// 空間検索
    } else {
	// 全取得
	var url = "/geo/place/markers/";
	$.ajax({
		url: url,
		dataType: 'json',
		type: 'POST',
		data: {},
		success: function(data, isSuccess) {
		    isolateMarkerAndPopup(data, isSuccess);
		}
	    });
    }
}


/** マーカーを表現するレイヤーをマーカー種別ごとに追加する関数
 */
function setMarkerLayers(mapobj) {
    // pointRadius: 15
    /*
				label: "　登録中",
				fontColor: "#ffffff",
				fontSize: "9pt",
				labelAlign: "lb"
    */
    Vector1 = new OpenLayers.Layer.Vector("Vector Layer 1", {
	    styleMap: new OpenLayers.StyleMap({
		    "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
				externalGraphic: "http://maps.google.co.jp/mapfiles/ms/icons/blue.png",
				graphicHeight: 30,
				graphicOpacity: 1,
				graphicYOffset: -30,
				graphicWidth: 30,
				backgroundGraphic: "http://maps.google.co.jp/mapfiles/ms/icons/msmarker.shadow.png",
				backgroundWidth: 30,
				backgroundHeight: 30,
				backgroundXOffset: -6,
				backgroundYOffset: -30,
				rotation: 0,
			    }, OpenLayers.Feature.Vector.style["default"])),
		    "select": new OpenLayers.Style({
			    externalGraphic: "http://maps.google.co.jp/mapfiles/ms/icons/ltblue-dot.png",
			})
		})
	});

    mapobj.addLayers([Vector1]);
    SelectCtrl = new OpenLayers.Control.SelectFeature([Vector1], {
	    clickout: true, toggle: false,
	    multiple: false, hover: false,
	    toggleKey: "altKey",	// alt key removes from selection
	    multipleKey: "shiftKey"	// shift key adds to selection
	});
    mapobj.addControl(SelectCtrl);
    SelectCtrl.activate();

    // マーカークリック時のハンドラを登録
    Vector1.events.on({"featureselected": onMakerSelectOrCreate, "featureunselected": onMakerUnselect});
    // マーカーを取得し表示
    getMarkers(Vector1, null, null);
}


/** 右ペインに表れるPlace登録の「登録」ボタン押下時にコールされるハンドラ
 */
function create_place_onclick() {
    var lon = $("#id_lon").val();
    var lat = $("#id_lat").val();
    var name = $("#id_name").val();
    var zip = $("#id_zipcode").val();
    var addr = $("#id_address").val();
    var draft = $("#id_draft").val();

    var openhours = $("#id_openhours").val();
    var holiday = $("#id_holiday").val();
    var tel = $("#id_tel").val();
    var url = $("#id_url").val();
    var disc = $("#id_disc").val();

    var html_str = '<div id="loading-box" valign="center"><img src="/site_media/static/img/loading.gif"/></div>';
    var divbox = $("div#create-place-box");

    divbox.html(html_str);
    divbox.load("/geo/popup/create_done/",
		{"lon": lon, "lat": lat, "name": name, "address": addr, "zipcode": zip, "draft": draft, 
			"openhours": openhours, "holiday": holiday, "tel": tel, "url": url, "disc": disc});
    // TODO: ここで、マーカーのfid値を格納し、登録済みとする。
    // TODO: Popup内のHTMLも「ここを登録しますか？」から、登録済みPopupと同様の内容に書き換える。
}


/** RDBに対してtweetを非同期で登録し、かつ、タイムラインを更新する。
 */
function post_tweet(action, user, bg_color) {
    var tweet = $("textarea#new_tweet").val();
    var tweet_post = '<div class="tweet-odd">' + tweet + '</div>'
    if ( tweet.length > 0 ) {
	// サーバーにtweetを送信
	$.post(action, {"text": tweet, "sender": user}, function(data) {
		var tl = $("div#tweet-timeline");
		var new_div = $(data);
		tl.prepend(new_div);
		// tl.html(data + tl.html());
		// new_div.effect("highlight", {}, 3000);
		new_div.animate({backgroundColor: bg_color}, 3000);
	    });
    }
}


function likebtn_click(pkey) {
    var loading = '<div id="loading-box" valign="center"><img src="/site_media/static/img/loading.gif"/></div>'
    $("#like-btn").html(loading);
    $("#like-btn").load("/geo/like/", {"pkey": pkey});
}


/** PlaceImageクラスへの非同期アップロードを実現するための関数
 */
function tweet_image_main() {
    var form = $("form#placeimage");		// formオブジェクト
    var f_selector = $("input#id_image");	// form内のinput（画像ファイルセレクタ）
    f_selector.change(function() {
	    var uploaded = $("#image-uploaded");
	    uploaded.append('<img id="loading" src="/site_media/static/img/loading.gif" />');
	    $(this).upload(form.attr("action"), function(res) {
		    $("#loading").remove();
		    uploaded.addClass("uploaded");
		    uploaded.addClass("clearfix");
		    uploaded.append(res);
		}, 'html');
	});
}
