// Student Unions & Activities
// University of Minnesota

function BadGuy(kind) {
    this.kind = kind;
    
    this.alive = true;
    this.age = 0;
    
    this.width = 50;
    this.height = 50;
    
    this.x = 0;
    this.y = 0;
    this.xv = 0;
    this.yv = 0;
    
    this.speed = 1000;
    
    this.aniCount = 0;
    
    this.avoidKinds = new Array();
    this.attackKinds = new Array();
    this.avoidIndices = new Array();
    this.attackIndices = new Array();
    
    this.points = 0;
    
    this.keyURL = '';
    
    this.gameDiv = $('game');
    
    this.div = document.createElement('div');
    $D.addClass(this.div, 'badguy');
    $D.addClass(this.div, this.kind);
    this.gameDiv.appendChild(this.div);
    
    this.pointsShadowDiv = document.createElement('div');
    $D.addClass(this.pointsShadowDiv, 'pointsShadow');
    this.gameDiv.appendChild(this.pointsShadowDiv);
    
    switch (this.kind) {        
        case 'burger':
            this.points = 500;
            break;

        case 'hotdog':
            this.points = 150;
            break;
            
        case 'drink':
            this.points = 100;
            break;

        case 'pizza':
            this.points = 250;
            break;

        case 'squirrel':
            this.points = 750;
            this.speed = 500;
            break;

        case 'asquirrel':
            this.points = 1000;
            this.speed = 500;
            break;

        case 'bsquirrel':
            this.points = 1000;
            this.speed = 500;
            break;
        
        case 'isquirrel':
            this.points = 2000;
            this.speed = 500;
            break;
        
        case 'book':
        	this.points = 1000;
        	this.speed = 500;
        	break;

        case 'bookworm':
            this.width = 100;
        	this.height = 100;
        	this.points = 1500;
        	this.speed = 750;
        	break;

        case 'guitar':
        	this.height = 100;
        	this.points = 2500;
        	break;

        case 'note':
        	this.points = -750;
        	this.speed = 500;
        	this.move = function (ticks) {
                if (ticks % this.speed == 0) {
                    var xv = this.xv;
                    var yv = this.yv;

                    // Change direction at random
                    var r = Math.random();
                    if (r < 0.25) {
                        xv = (Math.random() < 0.5) ? this.width : -this.width;
                        yv = 0;
                    } else if (r < 0.5) {
                        xv = 0;
                        yv = (Math.random() < 0.5) ? this.height : -this.height;
                    }

                    this.xv = xv;
                    this.yv = yv;

                    this.aniCount = 1;

                    this.setX(this.x + (this.xv * 0.5));
                    this.setY(this.y + (this.yv * 0.5));

                } else if (this.aniCount > 0) {
                    this.aniCount--;

                    this.setX(this.x + (this.xv * 0.5));
                    this.setY(this.y + (this.yv * 0.5));
                    
                    if (this.collidesWith(andy)) {
                        this.kill(true);
                    }
                }
            }
        	break;
        
        case 'manatee':
            this.width = 100;
            this.height = 100;
            this.points = 5000;
            this.speed = 500;
            this.xv = this.width;
            this.move = function (ticks) {
                if (ticks % this.speed == 0) {
                    this.aniCount = 1;
                    this.setX(this.x + (this.xv * 0.50), true);
                } else if (this.aniCount > 0) {
                    this.aniCount--;
                    this.setX(this.x + (this.xv * 0.50), true);
                }
                
                if (this.x <= (0 - (this.width * 4))) {
        		    this.xv = this.width;
        		    $D.setStyle(this.div, 'background-position', 'top left');
        		}
        		if (this.x >= (GAMEWIDTH + (this.width * 4))) {
        		    this.xv = -this.width;
        		    $D.setStyle(this.div, 'background-position', 'top right');
                }
        		if (this.attackKinds.length > 0) {
        		    this.calcAttackIndices();
        		}
            }
            break;
            
        case 'cthulhu':
            this.width = 100;
            this.height = 100;
            this.points = 1000000;
            this.speed = 500;
	        this.avoid('fire');
            this.move = function (ticks) {
                if (ticks % this.speed == 0) {
                    var x = Math.floor(Math.random()*11) * 50;
                    var y = Math.floor(Math.random()*7) * 50;
                    if (!this.willCollideWith(andy, x, y)) {
                        triggerSound('fire');
                        
                        fire = new BadGuy('fire');
                        fire.setX(this.x);
                        fire.setY(this.y);
                        badguys.push(fire);

                        this.setX(x);
                        this.setY(y);
                    }
                }
            }
            break;

        case 'fire':
            this.width = 100;
            this.height = 100;
            this.points = -1000;
	        this.age = 100;
            this.move = function () {
        		if (this.attackKinds.length > 0) {
        		    this.calcAttackIndices();
        		}
        		if (this.alive && 0 > this.age--) {
        		    this.alive = 0.9 < Math.random();
        		}
    	    }
            break;

        case 'manmanatee':
            this.width = 100;
            this.height = 100;
            this.points = 3000;
            this.speed = 1000;
            break;
        
        case 'kelp':
            this.points = 1000;
            this.move = function () {}
            break;
        
        case 'honus':
            this.points = 15000;
            this.speed = 500;
            break;
    
        case 'bowlingpin':
            this.height = 100;
            this.points = 1000;
            this.move = function () {}
            break;
        
        case 'pinguin':
            this.height = 100;
            this.points = 1000;
            this.move = function () {}
            break;
        
        case 'mrbones':
            this.height = 100;
            this.points = 666;
            this.move = function () {}
            break;
        
        case 'tower':
            this.height = 175;
            this.move = function () {}
            break;
    }
    
    
    // Apparently eliminates scope problems in timers/event handlers
    //var self = this;
}

BadGuy.prototype.setX = function (x, anywhere) {
    if (!anywhere) {
        if ( x < 0 ) {
            x = 0;
            this.xv = this.width;
            this.yv = 0;
        } else if ( x > GAMEWIDTH - this.width ) {
            x = GAMEWIDTH - this.width;
            this.xv = -this.width;
            this.yv = 0;
        }
    }

    this.x = x;
    $D.setStyle(this.div, 'left', x+'px');
}

BadGuy.prototype.setY = function (y, anywhere) {
    if (!anywhere) {
        if ( y < 0 ) {
            y = 0;
            this.xv = 0;
            this.yv = this.height;
        } else if ( y > GAMEHEIGHT - this.height ) {
            y = GAMEHEIGHT - this.height;
            this.xv = 0;
            this.yv = -this.height;
        }
    }
    
    this.y = y;
    $D.setStyle(this.div, 'top', y+'px');
}


BadGuy.prototype.avoid = function (kind) {
    this.avoidKinds.push(kind);
}


BadGuy.prototype.attack = function (kind) {
    this.attackKinds.push(kind);
}


BadGuy.prototype.calcAvoidIndices = function () {
    var j;
    var i;
    var kind;
    
    for (j = 0; j < this.avoidKinds.length; j++) {
        kind = this.avoidKinds.pop();
        for (i = 0; i < badguys.length; i++) {
            if (badguys[i].kind == kind) {
                this.avoidIndices.push(i);
            }
        }
    }
}


BadGuy.prototype.calcAttackIndices = function () {
    var j;
    var i;
    var kind;
    
    for (j = 0; j < this.attackKinds.length; j++) {
        kind = this.attackKinds.pop();
        for (i = 0; i < badguys.length; i++) {
            if (badguys[i].kind == kind) {
                this.attackIndices.push(i);
            }
        }
    }
}


BadGuy.prototype.move = function (ticks) {
    if (ticks % this.speed == 0) {
        var xv = this.xv;
        var yv = this.yv;
        
        // Change direction at random
        var r = Math.random();
        if (r < 0.25) {
            xv = (Math.random() < 0.5) ? this.width : -this.width;
            yv = 0;
        } else if (r < 0.5) {
            xv = 0;
            yv = (Math.random() < 0.5) ? this.height : -this.height;
        }

        this.xv = xv;
        this.yv = yv;

        if (this.avoidKinds.length > 0) {
            this.calcAvoidIndices();
        }

        // Change direction to avoid hitting avoid()'ed badguys
        var i;
        for (i = 0; i < this.avoidIndices.length; i++) {
            if (badguys[this.avoidIndices[i]].alive && this.willCollideWith(badguys[this.avoidIndices[i]], this.x + xv, this.y + yv)) {
                this.xv = -xv;
                this.yv = -yv;
            }
        }

        // Change direction to avoid hitting Andy
        // Yes this will override any direction change from avoiding badguys
        // This is a naive aproach, but it is a sacrifice in the name of simplicity at the moment
        // It is more important for the badguys to not commit suicide with Andy
        if (this.willCollideWith(andy, this.x + xv, this.y + yv)) {
            this.xv = -xv;
            this.yv = -yv;
        }

        this.aniCount = 1;

        this.setX(this.x + (this.xv * 0.5));
        this.setY(this.y + (this.yv * 0.5));
    
    } else if (this.aniCount > 0) {
        this.aniCount--;
        
        this.setX(this.x + (this.xv * 0.5));
        this.setY(this.y + (this.yv * 0.5));
        
        if (this.attackKinds.length > 0) {
            this.calcAttackIndices();
        }

        // Kill anything you are attacking that you've collided with
        for (i = 0; i < this.attackIndices.length; i++) {
            if (badguys[this.attackIndices[i]].alive && this.collidesWith(badguys[this.attackIndices[i]])) {
                badguys[this.attackIndices[i]].kill();
            }
        }
    }
}


BadGuy.prototype.collidesWith = function (sprite) {
    //return ( sprite.x + sprite.width > this.x && sprite.x < this.x + this.width && sprite.y + sprite.height > this.y && sprite.y < this.y + this.height );
    return ( sprite.x + sprite.width > this.x + (this.width * 0.25) && sprite.x < this.x + (this.width * 0.75) && sprite.y + sprite.height > this.y + (this.height * 0.25) && sprite.y < this.y + (this.height * 0.75) );
}


BadGuy.prototype.willCollideWith = function (sprite, x, y) {
    return ( sprite.x + sprite.width > x && sprite.x < x + this.width && sprite.y + sprite.height > y && sprite.y < y + this.height );
}


BadGuy.prototype.hasKey = function () {
    return (this.keyURL != '');
}


BadGuy.prototype.kill = function (byAndy) {
    this.alive = false;
    
    $D.setStyle(this.div, 'visibility', 'hidden');
    
    if (byAndy) {
        triggerSound(this.kind + 'death');
        
        this.showPoints(this.points);

        if (this.keyURL != '') {
            ask(this.keyURL);
        }
    } else {
        triggerSound(this.kind + 'deathpeer');
        
        this.showPoints(-this.points);
    }
}


BadGuy.prototype.revive = function () {
    this.alive = true;
    $D.setStyle(this.div, 'visibility', 'visible');
}


BadGuy.prototype.showPoints = function (points, message) {
    if (!message) {
        message = '';
    }
    
    if (points < 0) {
        this.pointsShadowDiv.innerHTML = '<div class="points" style="color: red;">'+points+'<br />'+message+'</div>'+points+'<br />'+message;
    } else {
        this.pointsShadowDiv.innerHTML = '<div class="points">'+points+'<br /><span style="color: yellow;">'+message+'</span></div>'+points+'<br />'+message;
    }
    
    $D.setStyle(this.pointsShadowDiv, 'left', (this.x+1)+'px');
    $D.setStyle(this.pointsShadowDiv, 'top', (this.y+1)+'px');
    $D.setStyle(this.pointsShadowDiv, 'visibility', 'visible');
    
    // Eliminate scoping problem with this
    var self = this;
    var a = new YAHOO.util.Anim(this.pointsShadowDiv, {top: {by: -50}}, 0.5, YAHOO.util.Easing.easeOut);
    a.onComplete.subscribe(function () {$D.setStyle(self.pointsShadowDiv, 'visibility', 'hidden');});
    a.animate();
    
    updateScore(points);
}
