L.TileLayer.GoogleBase = L.TileLayer.extend({
    getTileUrl: function (coords) {
        return '/Menggu/GetMap?type=47626774&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y);
    }
});

L.TileLayer.GoogleDetail = L.TileLayer.extend({
    getTileUrl: function (coords) {
        return '/Menggu/GetMap?type=1024577166&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y);
    }
});

L.tileLayer.googleBase = function () {
    return new L.TileLayer.GoogleBase();
};

L.tileLayer.googleDetail = function () {
    return new L.TileLayer.GoogleDetail();
};

var Map = function (parent) {
    this.Parent = parent;
    this.WindTemplate = null;
    this.MultiLayers = false;

    this.Startup = function () {
        this.CreateMap();
        this.InitCapture();
        this.LoadWindTemplate();
        $('#particle-switch a').on('click', this.OnParticleButtonClick.bind(this));
        $('#label-switch a').on('click', this.OnRemoveMarkersButtonClick.bind(this));
    };

    this.CreateMap = function () {
        this.map = L.map('map', {
            zoomControl: false,
            minZoom: 4,
            maxZoom: 16,
            zoomDelta: 0.05
        }).setView([40.854662, 111.746303], 7);

        L.tileLayer.googleBase().addTo(this.map);
        L.tileLayer.googleDetail().addTo(this.map);
        $('.leaflet-control-attribution').hide();
    };

    this.OnParticleButtonClick = function () {
        // Toggle switch on/off
        var parent = $(event.target).parent();
        parent.toggleClass('switch-on');

        // Hide wind layer
        if (!parent.hasClass('switch-on')) {
            this.HideWindLayer();
            return;
        }

        // Add wind layer
        var url = 'http://{0}/bj/getwind/{1}'.format(Config.ApiRoot, this.GetWindFileName());
        $.getJSON(url).done(function (data) {
            this.WindTemplate[0].data = [];
            this.WindTemplate[1].data = [];

            $(data).each(function (index, item) {
                this.WindTemplate[0].data.push(item.u);
                this.WindTemplate[1].data.push(item.v);
            }.bind(this));

            this.ShowWindLayer(this.WindTemplate);
        }.bind(this)).fail(function (xhr, status, error) {
            var message = "Json文件加载失败: Status={0}, Error={1}".format(status, error);
            this.MessageBox("error", message);
        }.bind(this));
    };

    this.OnRemoveMarkersButtonClick = function () {
        var parent = $(event.target).parent();
        parent.toggleClass('switch-on');

        if (!parent.hasClass('switch-on')) {
            $('.point').hide();
            $('.time-label').hide();
        } else {
            $('.point').show();
            $('.time-label').show();
        }
    };

    this.GetWindFileName = function () {
        var value = $('#release-date').datebox('getValue');
        var time = moment(value, 'YYYY/MM/DD HH:mm');

        var hour = time.format('YYYY-MM-DD_HH');
        var minute = Math.floor(time.minutes() / 10) * 10;
        return '{0}_{1}.json'.format(hour, minute === 0 ? '00' : minute);
    };

    this.LoadWindTemplate = function () {
        $.getJSON('/Content/scripts/menggu/wind-template.json', function (data) {
            this.WindTemplate = data;
        }.bind(this));
    };

    this.RemoveLayer = function (name) {
        this.map.eachLayer(function (layer) {
            if (layer.name === name)
                this.map.removeLayer(layer);
        }.bind(this));
    };

    this.ClearLayers = function () {
        this.map.eachLayer(function (layer) {
            if (layer.name !== undefined)
                this.map.removeLayer(layer);
        }.bind(this));
    };

    this.LoadAverageData = function (name, param, result) {
        if (this.MultiLayers)
            this.RemoveLayer(name);
        else
            this.ClearLayers();

        var layer = this.CreateAverageLayer(name, param, result);
        this.map.addLayer(layer);
        this.BindCloseButtons();
    };

    this.BindCloseButtons = function () {
        $('.close-button').on('click', function (event) {
            $('.{0}'.format($(event.target).next().attr('lng'))).hide();
            $(event.target).parent().hide();
        });
    };

    this.LoadDetailData = function (name, values) {
        this.ClearLayers();
        var layer = this.CreateDetailLayer(name, values);
        this.map.addLayer(layer);
    };

    this.CreateDetailLayer = function (name, values) {
        var features = new L.FeatureGroup();
        features.name = name;

        this.AddData(features, values);
        return features;
    };

    this.CreateAverageLayer = function (name, param, result) {
        var features = new L.FeatureGroup();
        features.name = name;

        this.AddData(features, result.backward.average);
        this.AddData(features, result.forward.average);

        this.AddPolyline(features, result.backward.points);
        this.AddPolyline(features, result.forward.points);

        this.AddCenter(features, param);
        this.AddPoints(features, result.backward.points);
        this.AddPoints(features, result.forward.points);

        this.AddLabels(features, result.backward.points);
        this.AddLabels(features, result.forward.points);
        return features;
    };

    this.AddData = function (features, values) {
        $(values).each(function (index, value) {
            var color = this.GetPointsColor(value[2]);
            var bounds = [[value[1] - 0.01, value[0] - 0.01], [value[1] + 0.01, value[0] + 0.01]];
            L.rectangle(bounds, {
                color: color,
                fillColor: color,
                fillOpacity: 0.75,
                weight: 0
            }).addTo(features);
        }.bind(this));
    };

    this.AddPolyline = function (features, points) {
        var polyline = [];
        $(points).each(function (index, point) {
            polyline.push([point[1], point[0]]);
        });
        L.polyline(polyline, {
            fillColor: '#1c9099',
            color: 'white',
            weight: 2
        }).addTo(features);
    };

    this.AddCenter = function (features, param) {
        var latlng = [param.Latitude, param.Longitude];
        L.circleMarker(latlng, {
            opacity: 1,
            weight: 0.5,
            color: 'black',
            fillColor: 'yellow',
            fillOpacity: 0.5,
            radius: 6
        }).addTo(features);

        L.marker(latlng, {
            icon: L.divIcon({
                className: 'center-label',
                html: this.GetCenterLabel(param)
            })
        }).addTo(features);
    };

    this.AddPoints = function (features, points) {
        $(points).each(function (index, point) {
            L.circleMarker([point[1], point[0]], {
                opacity: 1,
                weight: 0.5,
                color: 'black',
                fillColor: '#fff',
                fillOpacity: 1,
                radius: 4,
                className: 'point point{0}'.format(point[1].toString().split(".").join(""))
            }).addTo(features);
        }.bind(this));
    };

    this.AddLabels = function (features, points) {
        $(points).each(function (index, point) {
            L.marker([point[1], point[0]], {
                icon: L.divIcon({
                    className: 'time-label',
                    html: this.NormalizeTime(point[1], point[2])
                })
            }).addTo(features);
        }.bind(this));
    };

    this.GetCenterLabel = function (param) {
        var pattern = '<p>经度:{0}</p><p>纬度:{1}</p><p>高度:{2}米</p><p>释放时间:{3}</p>';
        return pattern.format(param.Longitude, param.Latitude, param.Height, moment(param.ReleaseTime).format("MM/DD HH:mm"));
    };

    this.NormalizeTime = function (lng, time) {
        var attr = lng.toString().split(".").join("");
        var value = moment(time, "YYYYMMDD_HHmmss");
        return '<a href="javascript:;" class="close-button" title="关闭"></a><span lng="point{0}">{1}</span>'.format(attr, value.format("MM/DD HH:mm"));
    };

    this.ShowWindLayer = function (data) {
        this.WindLayer = L.velocityLayer({
            displayValues: false,
            displayOptions: {
                velocityType: 'GBR Wind',
                displayPosition: 'bottomleft',
                displayEmptyString: 'No wind data'
            },
            data: data,
            maxVelocity: 15
        });
        this.map.addLayer(this.WindLayer);
    };

    this.HideWindLayer = function () {
        if (this.map.hasLayer(this.WindLayer))
            this.map.removeLayer(this.WindLayer);
    };

    this.InitCapture = function () {
        Init();
        $('#capture-button').on('click', function () {
            var returned = Capture();
            if (returned === emCaptureFailed || returned == emCaptureUnknown) {
                $('#capture-button').hide();
                $('#download-button').show();
            }
        });
    };

    this.GetPointsColor = function (value) {
        if (value <= 0.0001)
            return 'rgb(255,255,255)';
        if (value <= 0.001)
            return 'rgb(178, 226, 249)';
        if (value <= 0.01)
            return 'rgb(93, 160, 213)';
        if (value <= 0.1)
            return 'rgb(73, 170, 106)';
        if (value <= 1)
            return 'rgb(159, 206, 81)';
        if (value <= 10)
            return 'rgb(248, 171, 67)';
        if (value <= 100)
            return 'rgb(239, 94, 41)';
        if (value <= 1000)
            return 'rgb(192, 28, 36)';
    };
};