define("bdmapTool", ["jquery", "bdmap"], function ($, BMap) {
    function bdmapTool(ops) {
        var me = this;
        this.map = {};
        this.box = {};
        this.searchTmpl = null;
        this.linetype = "";
        this.ops = {
            boxTitle:"地图",
            tmpl: "",
            mapContent: "#dmap",
            searchInfoTmpl: null,
            searchInfoTmplBtn:null,
            pointInfoTmpl: null,
            pointInfoTmplBtn: null,
            city: "南宁",
            left: 280,
            right: 600,
            height: 700,
            searchpanel: "seekpanel",
            linepanel: "divline",
            linetype:"",
            defCursor: "",
            point: null,
            pointLabel: "标注在此点！",
            pointInfoTitle: "标注地图位置",
            pstart: null,
            pend: null,
            pointStart: null,
            pointEnd:null,
            address: null,
            level: 13,
            pointCallBack: null,
            searchCallBack: null,
            onGetLocalBefor: null,
            onGetLocalAfter: null,
            onPolylinesSet:null
        }
        this.setOps = function (ops) {
            if (!ops) return this.ops;
            this.ops = $.extend(true, this.ops, ops);
            if (searchvm) searchvm.setOps(ops);
            return this.ops;
        }
        var ops = this.setOps(ops);
        var map = this.map;
        avalon.vmodels["msmap"] = null;
        var searchvm = avalon.define("msmap", function (vm) {
            vm.pointAddr = { address: "" };
            vm.left = me.ops.left;
            vm.right = me.ops.right;
            vm.height = me.ops.height;
            vm.keyword = "";
            vm.setOps = function (mops) {
                "left,right,height".split(",").forEach(function (key) {
                    if (mops[key]) searchvm[key] = mops[key];
                });
            }
            vm.pointMap = function () {
                ops.onGetLocalBefor = function () {
                    vm.pointAddr.address = "正在查询地址";
                }
                ops.onGetLocalAfter = function (result) {
                    vm.pointAddr.address = result.address;
                }
                me.pointMap();
            }
            vm.searchMap = function () {
                me.searchMap(vm.keyword);
            }
            vm.keyenter = function (e) {
                if (e.keyCode == 13) vm.searchMap();
            }
        });
        avalon.vmodels["msmapline"] = null;
        var linevm = avalon.define("msmapline", function (vm) {
            vm.linetype = "bus";
            vm.navType = "end";
            vm.pstart = "";
            vm.pend = "";
            vm.$pointStart = null;
            vm.$pointEnd = null;
            vm.customer = {};
            vm.company = {};
            vm.mapwidth = $(window).width() - 200;
            vm.mapheight = $(window).height() - 100;
            vm.$marker = null;
            vm.plans = [];
            vm.moreResultsUrl = "";
            vm.curLineIndex = "";
            vm.$lineRet = null;
            vm.showLeftTab = false;
            vm.leftTabToggle = function () {
                linevm.showLeftTab = !linevm.showLeftTab;
                if (!linevm.showLeftTab) linevm.mapwidth += 311;
                else linevm.mapwidth -= 311;
            }
            /*到这里去/从这里出发*/
            vm.navType = "start";
            vm.navTypeChange = function (navType) {
                linevm.navType = navType;
            }

            /*起点和终点交换*/
            vm.navTypeExchange = function () {
                var t = linevm.pstart;
                linevm.pstart = linevm.pend;
                linevm.pend = t;
                linevm.navType = linevm.navType == "start" ? "end" : "start";
                if (linevm.$pointStart && linevm.$pointEnd) linevm.lineSearch(linevm.linetype);
            }
            vm.setLinetype = function (type) {
                vm.linetype = type;
            }
            //查看客户详情
            vm.viewCustomer = function (id) {
                me.closeCustomOverlayInfo();
                var url = "/Customer/DetailCustomer/" + id;
                goto(url, true);
            }
            vm.lineSearch = function (linetype, marker) {
                if (!linevm.showLeftTab) linevm.leftTabToggle();
                linevm.plans = [];
                linevm.moreResultsUrl = "";
                linevm.curLineIndex = "";
                linevm.linetype = linetype;
                if (linevm.$pointStart == null) {
                    messageBox.error("请先在系统设置里标注本公司地址");
                    return;
                }
                if (linevm.$pointEnd == null) {
                    messageBox.error("请选择一个目的地");
                    return;
                }
                if (linevm.linetype == "bus") me.ops.linepanel = "";
                else me.ops.linepanel = "divline";
                if (linevm.navType == "start") me.lineMap(linevm.$pointStart, linevm.$pointEnd, linevm.linetype);
                else me.lineMap(linevm.$pointEnd, linevm.$pointStart, linevm.linetype);
                me.closeCustomOverlayInfo();
            }
            vm.lineClick = function (index) {
                linevm.curLineIndex = linevm.curLineIndex == index ? "" : index;
                if (linevm.curLineIndex) {
                    me.drawLine(index - 1, linevm.$lineRet);
                }
            }
        });
        this.initMap = function (callback) {
            map = this.map = new BMap.Map($(ops.mapContent)[0]);
            //if (me.ops.city == null || me.ops.city == "") me.ops.city = "南宁";
            if (me.ops.point && me.ops.point.lng > 0) map.centerAndZoom(me.ops.point, me.ops.level);
            else map.centerAndZoom(me.ops.city, me.ops.level);
            map.enableScrollWheelZoom();
            if (me.ops.tmpl == "line" || me.ops.tmpl == "search") {
                map.addControl(new BMap.NavigationControl());
            }
            if (callback) {
                callback.call(map,map);
            }
        }
        this.removeMap=function(){
            map.clearOverlays();
            $(".bluebt").remove();
            //$(me.box.content()).remove();
            //me.box = {};
            map = null;
        }
        this.openMap = function (callback) {
            var boxops = {
                title: me.ops.boxTitle,
                //width: me.ops.left+ me.ops.right,
                //height: me.ops.height,
                content: "",
                close: function () {
                    me.removeMap();
                }
            };
            if (me.ops.tmpl == "search") {
                me.ops.mapContent = "#dmap";
                me.ops.pointInfoTmpl = "#pointinfotmpl";
                me.ops.pointInfoTmplBtn = ".btn";
                me.ops.searchInfoTmpl = "#searchinfotmpl";
                me.ops.searchInfoTmplBtn = ".btn";
                if (this.searchTmpl) {
                    _showSearchmap(this.searchTmpl);
                }
                else {
                    $.get("/Content/Themes/Base/Template/Customer/MapSearch.html", function (d) {
                        me.searchTmpl = d;
                        _showSearchmap(d);
                    });
                }
                function _showSearchmap(html) {
                    boxops.width += 10;
                    boxops.content = html;
                    me.box = art.dialog($.extend({}, boxops));
                    var content = $(me.box.content()).css("padding","0px");
                    avalon.scan(content[0], searchvm);
                    ops.mapContent = content.find(ops.mapContent);
                    me.initMap(callback);
                }
            } else if (me.ops.tmpl == "line") {
                me.ops.mapContent = "#dmap";
                me.ops.linepanel = me.ops.linepanel || "divline";
                linevm.pstart = me.ops.pstart;
                linevm.pend = me.ops.pend;
                linevm.$pointStart = me.ops.pointStart;
                linevm.$pointEnd = me.ops.pointEnd;
                if (me.ops.customer) {
                    linevm.customer = me.ops.customer || {};
                }
                if (me.ops.company) {
                    linevm.company = me.ops.company || {};
                }

                me.ops.onSearchComplete = function (ret) {
                    linevm.$lineRet = ret;
                    if (linevm.linetype == "bus") {
                        var planobj = me.getPlan(ret);
                        linevm.plans = planobj.plans;
                        linevm.moreResultsUrl = planobj.moreResultsUrl;
                    }
                    else {
                        linevm.plans = [];
                        linevm.moreResultsUrl = "";
                    }
                }

                if (this.lineTmpl) {
                    _showLinemap(this.lineTmpl);
                }
                else {
                    $.get("/Content/Themes/Base/Template/Customer/MapLineSearch.html?_v=3", function (d) {
                        me.lineTmpl = d;
                        me.customerOverlayTmpl = $(d).filter("#customerOverlayTmpl").text();
                        me.customerInfoTmpl = $(d).filter("#customerInfoTmpl").text();
                        _showLinemap(d);
                    });
                }
                function _showLinemap(html) {
                    boxops.content = html;
                    boxops.width = linevm.mapwidth;
                    boxops.height = linevm.mapheight;
                    me.box = art.dialog($.extend({}, boxops));
                    var content = $(me.box.content()).css("padding", "0px");
                    avalon.scan(content[0], linevm);
                    ops.mapContent = content.find(ops.mapContent);
                    me.initMap(function () {
                        if (linevm.customer.Id && linevm.$pointEnd) {
                            var marker = me.addCustomOverlay(linevm.$pointEnd, {
                                title: linevm.customer.Name,
                                domEvents: {
                                    click: function () {
                                        var infow = this.openInfoWindow(me.customerInfoTmpl);
                                        avalon.scan(infow[0], linevm);
                                    }
                                }
                            });
                            marker.Id = linevm.customer.Id;
                            marker.addClass("yellowbt").removeClass("bluebt");
                        }
                        if (linevm.company.Id && linevm.$pointStart) {
                            var marker2 = me.addCustomOverlay(linevm.$pointStart, {
                                title: linevm.company.CompanyName
                            });
                            marker2.Id = linevm.company.Id;
                        }
                        if (callback) callback.call(me, map);
                    });
                }
            }else {
                var div = $("<div></div>").width(boxops.width).height(boxops.height);
                boxops.content = div[0];
                me.box = art.dialog($.extend({}, boxops));
                var content = $(me.box.content()).css("padding", "0px");
                ops.mapContent = div;
                this.initMap(callback);
            }
        }
        this.addMarker = function (point, label, info,icon) {
            var marker = new BMap.Marker(point, { icon: icon });
            map.addOverlay(marker);
            if (label) {
                var l = new BMap.Label(label, { offset: new BMap.Size(20, -10) });
                marker.setLabel(l);
            }
            function _showinfo(e) {
                var infow = new BMap.InfoWindow(info.html, info.ops);
                marker._infow = infow;
                if (e || info.show != false) marker.openInfoWindow(infow);
            }
            if (info) {
                Event.bind(marker, "click", _showinfo);
                _showinfo();
            }
            return marker;
        }
        this.addCustomOverlay= function (point,ops) {
            var overlay = new CustomOverlay(point, ops);
            map.addOverlay(overlay);
            return overlay;
        }
        //自定义覆盖物
        this.closeCustomOverlayInfo = function () {
            var infow = CustomOverlay.infow;
            if (infow) {
                infow.remove();
                infow = null;
            }
        }
        this.isOpenCustomOverlayInfo = function () {
            return CustomOverlay.infow != null;
        }
        function CustomOverlay(point, ops) {
            ops = ops || {};
            html = ops.html;
            if (!html) {
                html = '<table border="0" class="bluebt" border="0" cellspacing="0" cellpadding="0">'
                html += '<tr><td class="tleft">&nbsp;</td><td class="tcenter">#title#</td><td class="tright">&nbsp;</td></tr>'
                html += '<tr><td colspan="3" class="tfoot">&nbsp;</td></tr>'
                html += '</table>';
            }
            this.point = point;
            this.ops = ops;
            this.div = $(html.replace("#title#", ops.title || ""))[0];
            this.infow = null;
        }
        CustomOverlay.infow = null;
        CustomOverlay.topZindex = 1;
        CustomOverlay.prototype = new BMap.Overlay();
        CustomOverlay.prototype.initialize = function (map) {
            var that = this;
            var ops = this.ops;
            this.map = map;
            var div = $(this.div);
            this.zIndex = BMap.Overlay.getZIndex(this.point.lat);
            div.css({ "position": "absolute", "z-index":  this.zIndex+1});
            div.attr("id", "overlay_" + Math.random());
            var info = ops.info;
            var events = ops.domEvents;
            if (info) {
                div.click(function (e) {
                    if (info) that.openInfoWindow(info.html);
                });
            }
            if (events) {
                $.each(events, function (key, event) {
                    if (typeof (event) == "function") {
                        div[key](function (e) {
                            event.call(that, e);
                        });
                    }
                });
            }
            map.getPanes().labelPane.appendChild(div[0]);
            return div[0];
        }
        CustomOverlay.prototype.draw = function () {
            var map = this.map,_ops=this.ops;
            var pixel = map.pointToOverlayPixel(this.point);
            var l = pixel.x - 10;
            var t = pixel.y - 30;
            var offset = _ops.offset;
            if (offset) {
                l += offset.left;
                t += offset.top;
            }
            this.div.style.left = l + "px";
            this.div.style.top = t + "px";
        }
        CustomOverlay.prototype.openInfoWindow = function (html) {
            var that = this, infow = CustomOverlay.infow, _ops = this.ops, map = this.map;
            if (infow) infow.remove();
            CustomOverlay.infow = this.infow = infow = $(html).appendTo(document.body);
            map.panTo(this.point);
            Event.bindOnce(map, "moveend", function () {
                var pixel = map.pointToPixel(that.point);
                var offset = $(ops.mapContent).offset(), l, t;
                l = pixel.x - infow.width() + offset.left;
                t = pixel.y - infow.height() + offset.top;
                if (l < 0) l = 0;
                if (t < 0) t = 0;
                var cssdata = {
                    position: "absolute",
                    "z-index": 99999,
                    left: l + "px",
                    top: t + "px"
                };
                infow.css(cssdata).show();
            });
            infow.find(".close").click(function () {
                that.closeInfoWindow();
            });
            if (_ops.onOpenInfoWindow) _ops.onOpenInfoWindow.call(this, infow);
            return infow;
        }
        CustomOverlay.prototype.closeInfoWindow = function () {
            var infow = CustomOverlay.infow, ops = this.ops;;
            if (infow) {
                infow.remove();
                CustomOverlay.infow = infow = null;
                if (ops.onCloseInfoWindow) ops.onCloseInfoWindow.call(this);
            }
        }
        CustomOverlay.prototype.addClass = function (className) {
            $(this.div).addClass(className);
            return this;
        }
        CustomOverlay.prototype.removeClass = function (className) {
            $(this.div).removeClass(className);
            return this;
        }
        CustomOverlay.prototype.setTop = function (b) {
            if (b) $(this.div).css({ "z-index": CustomOverlay.topZindex++ });
            else $(this.div).css({ "z-index": this.zIndex });
        }

        this.getMarkerLocal = function (marker, callback) {
            var gc = new BMap.Geocoder();
            marker.local = null;
            if (ops.onGetLocalBefor) ops.onGetLocalBefor.call(marker);
            gc.getLocation(marker.getPosition(), function (result) {
                marker.local = result;
                $.extend(marker.local, marker.local.addressComponents);//把addressComponents属性暴露到local
                if (ops.onGetLocalAfter) ops.onGetLocalAfter.call(marker,result);
                if (callback) return callback(result);
            });
        }
        this.pointMap = function () {
            if (ops.defCursor == "") ops.defCursor = map.getDefaultCursor();
            map.setDefaultCursor("url(http://api0.map.bdimg.com/images/marker_red_sprite.png) 8 8,default");
            Event.bindOnce(map, "mousedown", _mapdown);
            var obj = $(ops.pointInfoTmpl), btn = obj.find(ops.pointInfoTmplBtn);
            function _mapdown(e) {
                map.setDefaultCursor(ops.defCursor);
                var marker = me.addMarker(e.point, ops.pointLabel);
                marker.enableDragging();
                Event.bindOnce(marker, "click", _showInfo);
                Event.bind(marker, "dragend", _showInfo);
                _showInfo({ target: marker });
            }
            function _btn_click(marker) {
                marker.closeInfoWindow();
                if (ops.pointCallBack) ops.pointCallBack.call(marker, marker.local, me.box);
            }
            function _showInfo(e) {
                me.getMarkerLocal(e.target);
                var infow = new BMap.InfoWindow(obj.show()[0], { title: ops.pointInfoTitle, width: 250, height: 120 });//
                e.target.openInfoWindow(infow);
                btn.unbind("click").click(function () {
                    _btn_click(e.target);
                });
            }
        }
        this.searchMap = function (keyword) {
            map.clearOverlays();
            searchvm.keyword = keyword;
            var panel = $("#" + ops.searchpanel).empty().html("loading...");
            var local = new BMap.LocalSearch(map, {
                pageCapacity: 5,
                renderOptions: {
                    map: map,
                    panel: ops.searchpanel,
                    selectFirstResult: false
                },
                onSearchComplete: function (result) {
                    var isok=local.getStatus() == BMAP_STATUS_SUCCESS;
                    if (isok) {
                        panel.empty();
                    } else {
                        //console.log(result);
                        if (keyword == "") panel.html("请输入查询关键词");
                        else panel.empty();
                    }
                    if (ops.onSearchComplete) ops.onSearchComplete.call(me, result,isok);
                },
                onInfoHtmlSet: function (poi, d) {
                    if (!ops.searchInfoTmpl) return;
                    var btn = $(ops.searchInfoTmpl).clone().appendTo(d);
                    btn.find(ops.searchInfoTmplBtn).click(function () {
                        if (ops.searchCallBack) ops.searchCallBack.call(poi, poi, me.box);
                    });
                }
            });
            local.search(keyword);
        }
        this.lineMap = function (point1, point2, type) {
            type = type || ops.linetype;
            this.linetype = type;
            var that = this;
            this.clearOverlays();
            var win = art.dialog({
                width: 300,
                height: 100,
                title: "地图搜索中……",
                content: "<img src='/Content/Themes/Base/images/loading2.gif' />"
            });
            var panel = $("#" + me.ops.linepanel).empty().html("loading...");
            if (type == "car") {
                var driving = new BMap.DrivingRoute(map, {
                    renderOptions: { map: map, autoViewport: true, panel: me.ops.linepanel },
                    onSearchComplete: onSearchComplete
                });
                driving.search(point1, point2);
                return driving;
            } else {
                var transit = new BMap.TransitRoute(map, {
                    renderOptions: {
                        map: map, panel: me.ops.linepanel,
                        enableDragging: true,
                        highlightMode: BMAP_HIGHLIGHT_ROUTE
                    },
                    onSearchComplete: onSearchComplete,
                    /*onPolylinesSet: onPolylinesSet,*/
                });
                transit.setPolylinesSetCallback(onPolylinesSet);
                transit.search(point1, point2);
                return transit;
            }
            /*
            BMAP_HIGHLIGHT_STEP	驾车结果展现中点击列表后的展现点步骤。
            BMAP_HIGHLIGHT_ROUTE	驾车结果展现中点击列表后的展现路段。
            */
            function onSearchComplete(result) {
                if (win) win.close();
                if (result.getNumPlans() == 0) {
                    panel.html($("<div>没有可用线路</div>").css({"padding":"10px"}));
                }
                var status = type == "car" ? driving.getStatus() : transit.getStatus();
                if (ops.onSearchComplete) ops.onSearchComplete.call(me, result, status == BMAP_STATUS_SUCCESS);
            }
            /*
            设置添加路线后的回调函数。
            参数： lines: Array<Line>，公交线路数组。 routes: Array<Route>，步行线路数组，通过Route.getPolyline()方法可得到对应的折线覆盖物
           */
            function onPolylinesSet(lines, routes) {
                if (me.ops.onPolylinesSet) me.ops.onPolylinesSet.call(me, lines, routes);
            }
        }
        this.getPlan = function (ret) {
            var plans = [], n = ret.getNumPlans();
            for (var i = 0; i < n; i++) {
                plans.push(this.parsePlan(i + 1, ret.getPlan(i), ret));
            }
            var planobj = {
                city: ret.city,
                plans: plans,
                moreResultsUrl: ret.moreResultsUrl
            };
            return planobj;
        }
        this.parsePlan = function (index, plan,ret) {
            var d = plan.getDistance(false) / 1000;
            var titles = [], n = 0;
            var pobj = {
                index: index,
                start: ret.getStart().title,
                end: ret.getEnd().title,
                distance: d.toFixed(1),
                duration: plan.getDuration()
            }, steps = [];
            var m = 0;
            switch (me.linetype) {
                case "bus":
                    for (var i = 0, l = plan.getNumLines() ; i < l; i++) {
                        var line = plan.getLine(i);
                        var route = plan.getRoute(i);
                        var lineNum = line.title.split("(")[0];
                        titles.push(lineNum);
                        if (route && route.getDistance(false) != "0") {
                            steps.push({ type: "route", lineNum: lineNum, pointName: line.getGetOnStop().title, numdsc: route.getDistance() });
                        }
                        steps.push({ type: "bus", lineNum: lineNum, pointName: line.getGetOffStop().title, numdsc: line.getNumViaStops() + "站" });
                        if (i == l - 1) {
                            route = plan.getRoute(i + 1);
                            if (route && route.getDistance(false) != "0") {
                                steps.push({ type: "route", pointName: pobj.end, numdsc: route.getDistance() });
                            }
                        }
                    };
                    pobj.title = titles.join("→");
                    pobj.steps = steps;
                    break

                case "car":

                    break;
            }
            return pobj;
        }
        this.drawLine = function (index, ret,color,isSetViewport) {
            color = color || {};
            this.clearOverlays();
            var plan = ret.getPlan(index);
            var bounds = [];
            //绘制起点终点
            this.addBdIcon(ret.getStart().point, 1, 0);
            this.addBdIcon(ret.getEnd().point, 1, 1);
            // 绘制步行线路
            for (var i = 0; i < plan.getNumRoutes() ; i++) {
                var walk = plan.getRoute(i);
                if (walk.getDistance(false) > 0) {
                    map.addOverlay(new BMap.Polyline(walk.getPath(), { strokeStyle: "dashed", strokeColor:color.route || "#30a208", strokeOpacity: 0.75, strokeWeight: 4, enableMassClear: true }));
                }
            }
            // 绘制公交线路
            for (i = 0; i < plan.getNumLines() ; i++) {
                var line = plan.getLine(i), points = line.getPath(),
                pon = line.getGetOnStop(), poff = line.getGetOffStop();
                bounds = bounds.concat(points);
                //上车、下车
                this.addBdIcon(pon.point, 2, 2, pon.title);
                this.addBdIcon(poff.point, 2, 2, poff.title);
                map.addOverlay(new BMap.Polyline(points), { strokeColor: color.car || "#0030ff", strokeOpacity: 0.45, strokeWeight: 6, enableMassClear: true });
            }
            if (isSetViewport == null || isSetViewport) {
                map.setViewport(bounds);
            }
        }
        this.addBdIcon = function (point,iconType,index,title) {
            var url = "http://map.baidu.com/image/dest_markers.png", width = 42, height = 34, myIcon;
            //icontType:1为起点和终点，2为过程的图形
            if (iconType == 1) {
                myIcon = new BMap.Icon(url, new BMap.Size(width, height),
                    { offset: new BMap.Size(14, 32), imageOffset: new BMap.Size(0, 0 - index * height) });
            } else {
                url = "http://map.baidu.com/image/trans_icons.png";
                width = 22;
                height = 25;
                var d = 25, cha = 0, jia = 0;
                if (index == 2) {
                    d = 21;
                    cha = 5;
                    jia = 1;
                }
                myIcon = new BMap.Icon(url, new BMap.Size(width, height),
                    { offset: new BMap.Size(10, (11 + jia)), imageOffset: new BMap.Size(0, 0 - index * height - cha) });
            }
            var marker = new BMap.Marker(point, { icon: myIcon });
            if (title) marker.setTitle(title);
            if (iconType == 1) marker.setTop(true);
            map.addOverlay(marker);
            return marker;
        }
        this.clearOverlays = function () {
            map.clearOverlays();
        }
        var Event = {
            bind: function (o, type, handler) {
                o.addEventListener(type, handler);
            },
            bindOnce: function (o, type, handler) {
                this.bind(o, type, _fn);
                function _fn() {
                    handler.apply(this, arguments);
                    o.removeEventListener(type, _fn);
                }
            },
            unbind: function (o, type, handler) {
                o.removeEventListener(type, handler);
            }
        }
        bdmapTool.Event = Event;
    }
    
    return bdmapTool;
});