function Radar(canvas) {
    this.canvas = canvas;
    this.ctx = canvas.getContext('2d');
    trackTransforms(this.ctx);
    this.scaledFactor = 1;
    this.mapImage = new Image;
	this.fov = new Image;
	this.teamfov = new Image;
    this.direnfov = new Image;
	this.death = new Image;
	this.hp = new Image;
    this.focusOffset = {
        X: this.canvas.width / 2,
        Y: this.canvas.height / 2
    };
    this.viewPortOffset = {
        X: 0,
        Y: 0
    };
    var self = this;
    window.addEventListener('resize', function () {
        self.focusOffset = {
            X: self.canvas.width / 2,
            Y: self.canvas.height / 2
        };
    });

    // Adds ctx.getTransform() - returns an SVGMatrix
    // Adds ctx.transformedPoint(x,y) - returns an SVGPoint
    function trackTransforms(ctx) {
        var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
        var xform = svg.createSVGMatrix();
        ctx.getTransform = function () {
            return xform;
        };

        var savedTransforms = [];
        var save = ctx.save;
        ctx.save = function () {
            savedTransforms.push(xform.translate(0, 0));
            return save.call(ctx);
        };
        var restore = ctx.restore;
        ctx.restore = function () {
            xform = savedTransforms.pop();
            return restore.call(ctx);
        };

        var scale = ctx.scale;
        ctx.scale = function (sx, sy) {
            xform = xform.scaleNonUniform(sx, sy);
            return scale.call(ctx, sx, sy);
        };
        var rotate = ctx.rotate;
        ctx.rotate = function (radians) {
            xform = xform.rotate(radians * 180 / Math.PI);
            return rotate.call(ctx, radians);
        };
        var translate = ctx.translate;
        ctx.translate = function (dx, dy) {
            xform = xform.translate(dx, dy);
            return translate.call(ctx, dx, dy);
        };
        var transform = ctx.transform;
        ctx.transform = function (a, b, c, d, e, f) {
            var m2 = svg.createSVGMatrix();
            m2.a = a;
            m2.b = b;
            m2.c = c;
            m2.d = d;
            m2.e = e;
            m2.f = f;
            xform = xform.multiply(m2);
            return transform.call(ctx, a, b, c, d, e, f);
        };
        var setTransform = ctx.setTransform;
        ctx.setTransform = function (a, b, c, d, e, f) {
            xform.a = a;
            xform.b = b;
            xform.c = c;
            xform.d = d;
            xform.e = e;
            xform.f = f;
            return setTransform.call(ctx, a, b, c, d, e, f);
        };
        var pt = svg.createSVGPoint();
        ctx.transformedPoint = function (x, y) {
            pt.x = x;
            pt.y = y;
            return pt.matrixTransform(xform.inverse());
        }
    }
}
Radar.prototype.LoadIcon = function () {
    this.fov.src = "icon/fov.png";
	this.teamfov.src = "icon/teamfov.png";
    this.direnfov.src = "icon/direnfov.png";
	this.hp.src = "icon/hp.png";
	this.death.src = "icon/sw.png";
}
Radar.prototype.setMap = function (map) {
    this.mapImage.src = map;
}

Radar.prototype.map = function (angle) {
	this.xz(angle);
    this.ctx.drawImage(this.mapImage, 0,0);
	this.ctx.restore()
}
Radar.prototype.restore = function() {
    this.ctx.restore()
}
Radar.prototype.clear = function () {
    var p1 = this.ctx.transformedPoint(0, 0);
    var p2 = this.ctx.transformedPoint(this.canvas.width, this.canvas.height);
    this.ctx.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
}

Radar.prototype.translate = function (offsetX, offsetY) {
    this.ctx.translate(offsetX, offsetY);
    this.viewPortOffset.X += offsetX;
    this.viewPortOffset.Y += offsetY;
}

Radar.prototype.setZoom = function (scale) {
    var pt = this.ctx.transformedPoint(this.canvas.width / 2, this.canvas.height / 2);
    this.scaledFactor *= scale;
    this.ctx.translate(pt.x, pt.y);
    this.ctx.scale(scale, scale);
    this.ctx.translate(-pt.x, -pt.y);
	this.clear()
}

Radar.prototype.setMove = function (offsetX, offsetY, angel) {
    offsetX = offsetX / this.scaledFactor;
    offsetY = offsetY / this.scaledFactor;
   if (angel < 0 && angel > -180) {
        this.translate(offsetX, offsetY)
    }
    if (angel > 0 && angel < 180) {
        this.translate(-offsetX, -offsetY)
    }
}

Radar.prototype.setFocus = function (x, y) {
    var pos = this.coords2Pos(x, y);
    this.translate(this.focusOffset.X - pos.X, this.focusOffset.Y - pos.Y);
    this.focusOffset = pos;
}
Radar.prototype.xz = function(angel) {
    this.ctx.save();
    var pt = this.ctx.transformedPoint(this.canvas.width / 2, this.canvas.height / 2);
    this.ctx.translate(pt.x, pt.y);
    this.ctx.rotate((angel - 90) * Math.PI / 180);
    this.ctx.translate(-pt.x, -pt.y)
}
Radar.prototype.isLookatU = function(x0, y0, x1, y1, angle) {
    var isLookU = false;
    var ang = Math.abs(angle);
    var distance = this.game2Pix(Math.sqrt(Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2)));
    if (ang > 90) ang = 180 - ang;
    var disCalcu = this.game2Pix(Math.abs(Math.abs(x0) - Math.abs(x1)) / Math.cos(ang / 180 * Math.PI));
    if (Math.abs(disCalcu - distance) < 20 && distance < 600) {
        isLookU = true
    }
    if ((x1 != x0) && (y1 == y0) && ((angle > (-135)) || (angle < -135))) {
        isLookU = false
    }
    if ((x1 == x0) && (y1 != y0) && ((angle > (135)) || (angle < 45))) {
        isLookU = false
    }
    if ((x1 < x0) && (y1 > y0) && ((angle > 0) || (angle < -90))) {
        isLookU = false
    }
    if ((x1 > x0) && (y1 > y0) && (angle > -90)) {
        isLookU = false
    }
    if ((x1 > x0) && (y1 < y0) && ((angle > -180) && (angle < 90))) {
        isLookU = false
    }
    if ((x1 <= x0) && (y1 <= y0) && ((angle > 90) || (angle < 0))) {
        isLookU = false
    }
    return isLookU
}
// translates game coords to overlay coords
Radar.prototype.game2Pix = function (p) {
    return p * (8130 / 813000)
}

Radar.prototype.coords2Pos = function (x, y) {
    return {
        X: this.game2Pix(x),
        Y: this.game2Pix(y)
    }
}
Radar.prototype.dot = function(x, y, color, color1) {
    var pos = this.coords2Pos(x, y);
    this.ctx.beginPath();
    var radius = 8 / this.scaledFactor;
    this.ctx.arc(pos.X, pos.Y, radius, 0, 2 * Math.PI, false);
    this.ctx.lineWidth = 5;
    this.ctx.fillStyle = color || 'red';
    this.ctx.fill();
    this.ctx.beginPath();
    var radius1 = 5 / this.scaledFactor;
    this.ctx.arc(pos.X + (0.1 / this.scaledFactor), pos.Y + (-0.1 / this.scaledFactor), radius1, 0, 2 * Math.PI, false);
    this.ctx.lineWidth = 5;
    this.ctx.fillStyle = color1 || 'red';
    this.ctx.fill()
}
/* Radar.prototype.dot = function (x, y, color, width) {
    var pos = this.coords2Pos(x, y);
    var radius = 7 / this.scaledFactor;
    this.ctx.beginPath();
    this.ctx.arc(pos.X, pos.Y, radius, 0, 2 * Math.PI, false);
    this.ctx.lineWidth = width || 5;
    this.ctx.fillStyle = color || 'red';
    this.ctx.fill();
} */

Radar.prototype.pieChart = function (x, y, percent, color) {
    var pos = this.coords2Pos(x, y);
    var radius = 7 / this.scaledFactor;
    var startAngle = 1.5 * Math.PI;
    var endAngle = (percent * 2 * Math.PI) + 1.5 * Math.PI;

    // 扇形
    this.ctx.fillStyle = color || 'gray';
    this.ctx.beginPath();
    this.ctx.moveTo(pos.X, pos.Y);
    this.ctx.arc(pos.X, pos.Y, radius, startAngle, endAngle, false);
    this.ctx.closePath();
    this.ctx.fill();
}

Radar.prototype.text = function (x, y, content, color) {
    var pos = this.coords2Pos(x, y);
    this.ctx.font = '' + 8 / this.scaledFactor + 'pt Calibri';
    this.ctx.fillStyle = color || 'white';
    this.ctx.textAlign = 'center';
    this.ctx.fillText(content, pos.X, pos.Y + (3 / this.scaledFactor));
}
Radar.prototype.myx = function(x, y, angle, pic) {
    var pos = this.coords2Pos(x, y);
    this.ctx.save();
    this.ctx.translate(pos.X, pos.Y);
    this.ctx.rotate(-(angle - 90) * Math.PI / 180);
    this.ctx.translate(-(pos.X), -(pos.Y));
    this.ctx.globalAlpha = 1;
    var dx = 35;
    var dxx = dx / 2;
    if (pic == 1)
        this.ctx.drawImage(this.fov, pos.X - (30 / this.scaledFactor), pos.Y - (35 / this.scaledFactor), 60 / this.scaledFactor, 60 / this.scaledFactor)
    this.ctx.restore()
}
Radar.prototype.teamx = function(x, y, angle, pic) {
    var pos = this.coords2Pos(x, y);
    this.ctx.save();
    this.ctx.translate(pos.X, pos.Y);
    this.ctx.rotate(-(angle - 90) * Math.PI / 180);
    this.ctx.translate(-(pos.X), -(pos.Y));
    this.ctx.globalAlpha = 1;
    var dx = 35;
    var dxx = dx / 2;
    if (pic == 1) 
        this.ctx.drawImage(this.teamfov, pos.X - (30 / this.scaledFactor), pos.Y - (35 / this.scaledFactor), 60 / this.scaledFactor, 60 / this.scaledFactor)
    this.ctx.restore()
}
Radar.prototype.direnx = function(x, y, angle, pic, teammode) {
    var pos = this.coords2Pos(x, y);
    this.ctx.save();
    this.ctx.translate(pos.X, pos.Y);
    this.ctx.rotate(-(angle - 90) * Math.PI / 180);
    this.ctx.translate(-(pos.X), -(pos.Y));
    this.ctx.globalAlpha = 1;
    var dx = 35;
    var dxx = dx / 2;
    if (pic == 1) 
        this.ctx.drawImage(this.direnfov, pos.X - (30 / this.scaledFactor), pos.Y - (35 / this.scaledFactor), 60 / this.scaledFactor, 60 / this.scaledFactor)
    this.ctx.restore()
}
Radar.prototype.hpx = function(x, y, angle) {
    var pos = this.coords2Pos(x, y);
    this.ctx.save();
    this.ctx.translate(pos.X, pos.Y);
    this.ctx.rotate(-(angle - 90) * Math.PI / 180);
    this.ctx.translate(-(pos.X), -(pos.Y));
    this.ctx.globalAlpha = 1;
    var dx = 35;
    var dxx = dx / 2;
    this.ctx.drawImage(this.hp, pos.X - (dxx / this.scaledFactor), pos.Y - (dxx / this.scaledFactor), dx / this.scaledFactor, dx / this.scaledFactor);
    this.ctx.restore()
}
Radar.prototype.deathx = function(x, y, angle) {
    var pos = this.coords2Pos(x, y);
    this.ctx.save();
    this.ctx.translate(pos.X, pos.Y);
    this.ctx.rotate(-(angle - 90) * Math.PI / 180);
    this.ctx.translate(-(pos.X), -(pos.Y));
    this.ctx.globalAlpha = 1;
    var dx = 35;
    var dxx = dx / 2;
    this.ctx.drawImage(this.death, pos.X - (dxx / this.scaledFactor), pos.Y - (dxx / this.scaledFactor), dx / this.scaledFactor, dx / this.scaledFactor);
    this.ctx.restore()
}
// useless
// Radar.prototype.floatText = function (posX, posY, content, color) {
//     this.ctx.font = '' + 8 / this.scaledFactor + 'pt Calibri';
//     this.ctx.fillStyle = color || 'lightgreen';
//     this.ctx.textAlign = 'left';
//     this.ctx.fillText(content, posX - this.viewPortOffset.X, posY - this.viewPortOffset.Y);
// }

// from https://github.com/jerrytang67/helloworld
Radar.prototype.lineWithAngle = function (x, y, length, width, angle, color) {
    var pos = this.coords2Pos(x, y);
    var anX = 5 * Math.cos(Math.PI * angle / 180.0);
    var anY = 5 * Math.sin(Math.PI * angle / 180.0);

    var x1 = pos.X + anX;
    var y1 = pos.Y + anY;

    var circle1 = {
        x: pos.X,
        y: pos.Y,
        r: 5
    };
    var circle2 = {
        x: x1,
        y: y1,
        r: 0
    };

    var arrow = {
        h: width / this.scaledFactor,
        w: length / this.scaledFactor
    };

    drawArrow(this.ctx, arrow, circle1, circle2, color);

    //draw arrow -- uuaing
    function drawArrow(canvasContext, arrow, ptArrow, endPt, color) {
        var angleInDegrees = getAngleBetweenPoints(ptArrow, endPt);
        var endPt = getPointOnCircle(endPt.r, ptArrow, endPt);
        // first save the untranslated/unrotated context
        canvasContext.save();

        // move the rotation point to the center of the rect    
        canvasContext.translate(endPt.x, endPt.y);
        // rotate the rect
        canvasContext.rotate(angleInDegrees * Math.PI / 180);
        canvasContext.beginPath();
        canvasContext.moveTo(0, 0);

        canvasContext.lineTo(0, -arrow.h);
        canvasContext.lineTo(arrow.w, 0);
        canvasContext.lineTo(0, +arrow.h);
        canvasContext.closePath();
        canvasContext.fillStyle = color;
        canvasContext.lineWidth = 0;
        //canvasContext.stroke();
        canvasContext.fill();

        // restore the context to its untranslated/unrotated state
        canvasContext.restore();
    }

    function getPointOnCircle(radius, originPt, endPt) {
        var angleInDegrees = getAngleBetweenPoints(originPt, endPt);
        // Convert from degrees to radians via multiplication by PI/180        
        var x = radius * Math.cos(angleInDegrees * Math.PI / 180) + originPt.x;
        var y = radius * Math.sin(angleInDegrees * Math.PI / 180) + originPt.y;
        return {
            x: x,
            y: y
        };
    }

    function getAngleBetweenPoints(originPt, endPt) {
        var interPt = {
            x: endPt.x - originPt.x,
            y: endPt.y - originPt.y
        };
        return Math.atan2(interPt.y, interPt.x) * 180 / Math.PI;
    }
}
