var RectMapPiece = function(rect){
    this.rect = rect;
};

RectMapPiece.prototype.draw = function(){
    ctx.strokeRect(this.rect[0], this.rect[1], this.rect[2], this.rect[3]);
};

var TriangleMapPiece = function(rect){
    this.rect = rect;
};

TriangleMapPiece.prototype.draw = function(){
    ctx.beginPath();
    ctx.moveTo(this.rect[0] + this.rect[2] / 2, this.rect[1]);
    ctx.lineTo(this.rect[0], this.rect[1] + this.rect[3]);
    ctx.lineTo(this.rect[0] + this.rect[2], this.rect[1] + this.rect[3]);
    ctx.lineTo(this.rect[0] + this.rect[2] / 2, this.rect[1]);
    ctx.stroke();
};

var RhombusMapPiece = function(rect){
    this.rect = rect;
};

RhombusMapPiece.prototype.draw = function(){
    ctx.beginPath();
    ctx.moveTo(this.rect[0] + this.rect[2] / 2, this.rect[1]);
    ctx.lineTo(this.rect[0], this.rect[1] + this.rect[3] / 2);
    ctx.lineTo(this.rect[0] + this.rect[2] / 2, this.rect[1] + this.rect[3]);
    ctx.lineTo(this.rect[0] + this.rect[2], this.rect[1] + this.rect[3] / 2);
    ctx.lineTo(this.rect[0] + this.rect[2] / 2, this.rect[1]);
    ctx.stroke();
};

var EllipsePiece = function(rect){
    this.rect = rect;
};

EllipsePiece.prototype.draw = function(){
    ctx.beginPath();
    ctx.moveTo(this.rect[0] + this.rect[2] / 2, this.rect[1]);
    ctx.bezierCurveTo(this.rect[0] + this.rect[2], this.rect[1],
                      this.rect[0] + this.rect[2], this.rect[1] + this.rect[3],
                      this.rect[0] + this.rect[2] / 2, this.rect[1] + this.rect[3]);
    ctx.bezierCurveTo(this.rect[0], this.rect[1] + this.rect[3],
                      this.rect[0], this.rect[1],
                      this.rect[0] + this.rect[2] / 2, this.rect[1]);
    ctx.stroke();
};

var Link = function(start, end, direction, sectorHeight, sectorWidth){
    this.start = start;
    this.end = end;

    var endPos, y, x;

    if (Math.random() < 1.5){
        if (direction[1] < 0){
            y = Math.floor(start.rect[1] / sectorHeight) * sectorHeight;
            this.startPos = [start.rect[0] + start.rect[2] / 2, start.rect[1]];
            endPos = [end.rect[0] + end.rect[2] / 2, end.rect[1] + end.rect[3]];
        }
        else{
            y = Math.ceil(start.rect[1] / sectorHeight) * sectorHeight;
            this.startPos = [start.rect[0] + start.rect[2] / 2, start.rect[1] + start.rect[3]];
            if (direction[1] == 0){
                endPos = [end.rect[0] + end.rect[2] / 2, end.rect[1] + end.rect[3]];
            }
            else{
                endPos = [end.rect[0] + end.rect[2] / 2, end.rect[1]];
            }
        }
        
        this.points = [
            [this.startPos[0], y],
            [endPos[0], y],
            endPos
        ];
    }
    else{
        if (direction[0] < 0){
            x = Math.floor(start.rect[0] / sectorWidth) * sectorWidth;
            this.startPos = [start.rect[0], start.rect[1] + start.rect[3] / 2];
            endPos = [start.rect[0] + start.rect[2], start.rect[1] + start.rect[3] / 2];
            this.points = [
                [x, this.startPos[1]],
                [x, endPos[1]],
                endPos
            ];
        }
        else{
            this.startPos = [0, 0];
            this.points = [[0, 0]];
        }
    }
};

Link.prototype.draw = function(){
    ctx.beginPath();
    ctx.moveTo(this.startPos[0], this.startPos[1]);
    _.each(this.points, point => ctx.lineTo(point[0], point[1]));
    ctx.stroke();
};

var MapBackground = function(){
    this.strokeColor = '#221130';
    this.rects = [];
    this.links = [];

    this.pieceStyles = [
        RectMapPiece,
        RhombusMapPiece,
        EllipsePiece
    ];

    var gameHeight = height - 90;

    var xCount = 14;
    var yCount = 10;

    var sectorWidth = width / xCount;
    var sectorHeight = gameHeight / yCount;
    
    var i, j, k;

    for (i = 0; i < xCount; i++){
        var startX = i * sectorWidth;
        for (j = 0; j < yCount; j++){
            var startY = j * sectorHeight;
            var newWidth = Math.random() * sectorWidth / 3 + sectorWidth / 2;
            var newHeight = Math.random() * sectorHeight / 3 + sectorHeight / 3;
            var rect = [Math.random() * (sectorWidth - newWidth) + startX,
                        Math.random() * (sectorHeight - newHeight - 40) + startY + 20,
                        newWidth, newHeight];
            var style = _.sample(this.pieceStyles);
            
            this.rects.push(new style(rect));
        }
    }

    for (i = 0; i < xCount; i++){
        for (j = 0; j < yCount; j++){
            for (k = 0; k < 2; k++){
                var direction = [Math.floor(Math.random() * 3) - 1, Math.floor(Math.random() * 3) - 1];
                
                if (!direction[0] && !direction[1]){
                    continue;
                }
                if (i + direction[0] < 0 || i + direction[0] >= xCount){
                    direction[0] *= -1;
                }
                if (j + direction[1] < 0 || j + direction[1] >= yCount){
                    direction[1] *= -1;
                }

                var start = this.rects[i * yCount + j];
                var end = this.rects[(i + direction[0]) * yCount + j + direction[1]];
                
                this.links.push(new Link(start, end, direction, sectorHeight, sectorWidth));
            }
        }
    }
};

MapBackground.prototype.draw = function(){
    ctx.drawImage(getImage('backImage'), 0, 0);
    ctx.strokeStyle = this.strokeColor;
    _.each(this.rects, rect => rect.draw());
    _.each(this.links, link => link.draw());
};

MapBackground.prototype.update = function(){

};

var RectBackground = function(){
    this.colors = ['#110000', '#222200', '#000022', '#111111'];
    this.lineColor = '#000000';
    this.rectWidth = 95;
    this.lineWidth = 5;

    this.timeToChange = 1;
    this.changing = [];

    var squareWidth = this.rectWidth + this.lineWidth;

    var map = [];
    this.rects = {};
    _.each(this.colors, color => { this.rects[color] = []; });
        
    var i, j;

    for (i = 0; i < width / squareWidth; i++){
        map.push([]);
        for (j = 0; j < height; j += squareWidth){
            map[i].push(false);
        }
    }

    for (i = 0; i < map.length; i++){
        var row = map[i];
        for (j = 0; j < row.length; j++){
            if (row[j]){
                continue;
            }
            
            var color = _.sample(this.colors);

            var rectWidth, rectHeight;
            var xoff, yoff;

            var chk = true;

            for (var k = 0; k < 5; k++){
                rectWidth = Math.floor(1 + Math.random() * 3);
                rectHeight = Math.floor(1 + Math.random() * 3);
                
                for (xoff = 0; xoff < rectWidth; xoff++){
                    for (yoff = 0; yoff < rectHeight; yoff++){
                        if (i + xoff < map.length && j + yoff < map[i + xoff].length && map[i + xoff][j + yoff]){
                            chk = false;
                            break;
                        }
                    }
                    if (!chk){
                        break;
                    }
                }

                if (chk){
                    break;
                }
            }

            if (!chk){
                rectWidth = 1;
                rectHeight = 1;
            }

            for (xoff = 0; xoff < rectWidth; xoff++){
                for (yoff = 0; yoff < rectHeight; yoff++){
                    if (i + xoff < map.length && j + yoff < map[i + xoff].length){
                        map[i + xoff][j + yoff] = true;
                    }
                }
            }

            var rect = [i * squareWidth,
                        j * squareWidth,
                        rectWidth * squareWidth - this.lineWidth, 
                        rectHeight * squareWidth - this.lineWidth];

            this.rects[color].push(rect);
        }
    }
};

RectBackground.prototype.draw = function(){
    ctx.fillStyle = this.lineColor;
    ctx.fillRect(0, 0, width, height);

    
    _.each(this.rects, (rects, color) => {
        ctx.fillStyle = color;
        _.each(rects, rect => ctxFillRect(rect));
    });

    _.each(this.changing, (changeRect) => {
        var newColor = interpolateColor(changeRect.color, changeRect.newColor, 1 - changeRect.time / changeRect.fullTime);
        ctx.fillStyle = newColor;
        ctxFillRect(changeRect.rect);
    });
};

RectBackground.prototype.update = function(interval){
    this.timeToChange -= interval;
    
    if (this.timeToChange < 0){
        this.timeToChange = Math.random(6) + 6;
        var key = _.sample(Object.keys(this.rects));
        var rects = this.rects[key];

        if (rects.length > 0){
            var index = Math.floor(Math.random() * rects.length);
            var changeRect = rects[index];
            rects.splice(index, 1);

            var newColors = _.clone(this.colors);
            newColors.splice(newColors.indexOf(key), 1);
            var newColor = _.sample(newColors);

            this.changing.push({
                rect: changeRect,
                color: key,
                time: 6,
                fullTime: 6,
                newColor: newColor
            });
        }
    }
    
    for (var i = this.changing.length - 1; i >= 0; i--){
        var changingRect = this.changing[i];
        changingRect.time -= interval;
        if (changingRect.time <= 0){
            this.changing.splice(i, 1);
            this.rects[changingRect.newColor].push(changingRect.rect);
        }
    }
};
