var tc = {

    count : 0,
    minFrame : {},
    commentActive : 0,
    
    obj : {},
    
    mode : 'startup',

    buildTc : function() {
        tc.obj.wrapper = $('#tcsurf');
        
        // build main wrappers
        tc.obj.overlay = $('<div id="tcsurf-overlay" class="splashscreen"></div>').appendTo( tc.obj.wrapper );
        tc.obj.bg = $('<div id="tcsurf-bg"></div>').appendTo( tc.obj.wrapper );
        tc.obj.dude = $('<div id="tcsurf-dude"></div>').appendTo( tc.obj.wrapper );
        tc.obj.ui = $('<div id="tcsurf-ui"></div>').appendTo( tc.obj.wrapper );
        
        // build stage
        tc.obj.stage = $('<ul id="tcsurf-stage" class="tcsurf-num"></ul>').appendTo( tc.obj.ui );
        tc.obj.stage.append( $('<li class="num0"></li>') );
        tc.obj.stageDigits = $('<li id="the-stage" class="num6"></li>').appendTo( tc.obj.stage );
        
        //build clock
        tc.obj.clock = $('<ul id="tcsurf-clock" class="tcsurf-num"></ul>').appendTo( tc.obj.ui );
        tc.obj.digits = [];
        tc.obj.digits.push( $('<li id="tcsurf-mins"></li>').appendTo( tc.obj.clock ) );
        tc.obj.digits.push( $('<li id="tcsurf-secs1"></li>').appendTo( tc.obj.clock ) );
        tc.obj.digits.push( $('<li id="tcsurf-secs2"></li>').appendTo( tc.obj.clock ) );
        tc.obj.digits.push( $('<li id="tcsurf-msecs"></li>').appendTo( tc.obj.clock ) );
        
        // build life 
        tc.obj.life = $('<ul id="tcsurf-life"></ul>').appendTo( tc.obj.ui );
        
        tc.init();
        
        tc.obj.overlay.click(function() {
            if (tc.mode == 'startup') tc.gameStart();
            else if (tc.mode == 'gameover') tc.reset();
        });
        
        if ( jQuery.browser.mozilla ) $(document).keypress(tc.surfControls);
        else $(document).keydown(tc.surfControls);
    },

    init : function() {
        tc.left  = 0;
        tc.posX  = 0;
        tc.stage = 7;
        tc.time  = 1050;
        
        tc.life   = 0;
        tc.obj.life.children('LI').remove();
        tc.addLife(4);
    },

    gameStart : function() {
        tc.top    = 240;
        tc.posY   = 7;
        tc.speed  = 5;
        tc.active = 1;
        tc.skate  = 1;
    
        tc.newSprite(tc.obj.overlay, 'gamestart', 600, skateOrDie);
        tc.obj.overlay.removeClass('splashscreen gameover congrats');
        
        // move skater
        function skateOrDie() {
            if (tc.skate) {
                tc.left -= tc.speed;
                if (!tc.checkPos()) {    
                    tc.count++;
                    if (tc.count == 4) {
                        tc.count = 0;
                        
                        // if life maxed out, clock stops like in game
                        if ( tc.life < 8 ) tc.clock();
                    }
                    
                    tc.obj.bg.animate({left: tc.left}, 20, skateOrDie);
                }
            }
        }
    },

    reset : function() {

        // if just a crash
        if (tc.mode != 'gameover') {
            tc.obj.dude.css( {left: 200, top: 240 } ).removeClass('tcFall tcCrash');
            
            // if you still have life
            if (tc.life > 0) {
                tc.posX -= 20;
                
                validReset();
                
                var newLeft = -(32 * tc.posX);
                if ( newLeft > 0 ) newLeft = 0;
                
                tc.gameStart();
                
                tc.left  = newLeft;
            }
            else tc.gameOver();
        }
        else {
            tc.obj.dude.removeClass('tcVictory');
            
            tc.init();
            tc.gameStart();
        }
        
        function validReset() {
            if ( tc.collision( tc.PosX, 7 ) ) {
                tc.PosX -= 6;
            }
            else if ( tc.collision( tc.PosX + 1, 7 ) ) {
                tc.posX -= 5;
            }
            else if ( tc.collision( tc.PosX + 2, 7 ) ) {
                tc.posX -= 4;
            }
            else if ( tc.collision( tc.PosX + 3, 7 ) ) {
                tc.posX -= 3;
            }
            else if ( tc.collision( tc.PosX + 4, 7 ) ) {
                tc.posX -= 2;
            }
            else {
                if ( tc.collision( tc.PosX + 5, 7 ) ) tc.posX -= 1;
                
                return true;
            }
            
            validReset();
        }
    },
    
    
    
    // a is horizontal vs vertical
    checkPos : function(a) {
        if ( tc.active ) {
            switch(a) {
                case 'y':                
                    var y = tc.convertPosY( tc.top );
                    if ( y != tc.posY ) {
                        tc.posY = y;
                        if ( tc.collision(tc.posX, tc.posY) ) tc.crash();
                    }
                break;
                
                default :
                    var x = tc.convertPosX( tc.left );
                    if ( x != tc.posX ) {
                        if (x > 375) {
                            tc.victory();
                            return true;
                        }
                        tc.posX = x;
                        
                        // if stage changes
                        if (-tc.left > (8 - tc.stage) * 1792) {
                            tc.stage--;
                            
                            tc.obj.stageDigits.removeClass().addClass('num' + tc.stage);
                            tc.obj.stage.css({left : 572 }).animate({left : -80}, 5000 - ( tc.speed * 300 ));
                            
                            tc.addLife(1);
                        }
                        if (parseInt(x/2) == x/2) tc.obj.dude.toggleClass('tcIdle');
                        if ( tc.collision(tc.posX, tc.posY) ) tc.crash();
                    }
            }
        }
    },
    
    victory : function() {
        tc.obj.dude.addClass('tcVictory').animate({ left : 512 }, 1000, function() {
            tc.obj.dude.css({ top : 240})
                .animate({ left : 200}, 1200, function() {
                    setTimeout(function() {
                        tc.obj.overlay.addClass('congrats gameover');
                        
                        tc.mode = 'gameover';
                    }, 1000);
                });
        }); 
    },
        
    convertPosX : function(pos) {
        return parseInt( (268 - pos) / 32);
    },
    
    convertPosY : function(pos) {
        return parseInt( (pos + 4) / 32);
    },

    collision : function(posX, posY) { 
        var x = 'x' + posX;
        if ( posY > 8) return true;
        else if ( typeof(Tc[x]) == 'object' ) {
        
            var min = typeof(Tc[x].min) == 'number' ? Tc[x].min : 5;
            
            if (posY < min) return true;
            
            else if ( typeof(Tc[x]['y' + posY]) == 'number') return true;
        }
        else if (posY < 5) return true;
        
        return false;
    },

    crash : function() {
        tc.newSprite(tc.obj.dude, "tcImpact", 100, 0);
        tc.obj.dude.addClass('tcCrash');
        loseLife(2);
        
        tc.jump(100,1000);
        
        function loseLife(x) {
            if (x > 0) {
                if (tc.life == 0) return false;
                tc.life--;
                
                toggleLife(tc.obj.life.children('LI:last'),0,x);
            }
            
            function toggleLife (obj,x,y) {
                if (x < 20) {
                    obj.animate({opacity: ( parseInt(x/2) == x/2) ? 0 : 1}, 40, function() {
                        toggleLife(obj, x+1, y);
                    });
                }
                else {
                    obj.remove();
                    loseLife( y-1 );
                }
            }
        }
    },
    
    surfControls : function(ev) {
        switch( ev.charCode || ev.keyCode ) {
            // spacebar
            case 32:
                if ( !tc.commentActive ) {
                    if (ev.preventDefault) ev.preventDefault();
                    if (ev.returnValue) ev.returnValue = false;
                    
                    if ( tc.active && tc.posX < 365) {
                        tc.obj.dude.addClass('tcJump');
                        tc.jump(80,600);
                    }
                }
            break;
            
            // left arrow
            case 37:
                if (tc.speed > 1 && tc.active)
                    tc.speed -= 1;
            break;
            
            // up arrow
            case 38:
                if (ev.preventDefault) ev.preventDefault();
                if (ev.returnValue) ev.returnValue=false; 
                
                if ( tc.active ) {
                    tc.top -= 9;
                    tc.newSprite(tc.obj.dude, "tcUp", 200, 0);
                    tc.obj.dude.animate( { top: tc.top}, 30, function() {
                        tc.checkPos('y');
                    });
                }
            break;
            
            // right arrow
            case 39:
                if ( tc.active ) {
                    tc.newSprite(tc.obj.dude, "tcPedal", 100, 0);
                    if (tc.speed < 10)
                        tc.speed += 1;
                }
            break;
            
            // down arrow
            case 40:
                if (ev.preventDefault) ev.preventDefault();
                if (ev.returnValue) ev.returnValue=false;
                
                if ( tc.active ) {
                    tc.top += 10;
                    tc.newSprite(tc.obj.dude, "tcDown", 200, 0);
                    tc.obj.dude.animate( { top: tc.top}, 30, function() {
                        tc.checkPos('y')
                    });
                }
            break;
        }
    },
    
    jump : function(x,y) {
        tc.active = 0;
        
        tc.obj.dude.animate({ top : (tc.top - x)}, y).animate({top : tc.top}, y, function() {
            // if a crash
            if (x == 100) {
                tc.obj.dude.addClass('tcFall')
                    .animate({ left : -100}, 1200, function() {
                        tc.speed = 0;
                        tc.skate = 0;
                        tc.reset();
                    });
                    
            }
            else {
                tc.active = 1;
                tc.obj.dude.removeClass('tcJump');
                tc.checkPos(x);
            }
        });
    },
    
    gameOver : function() {
        tc.active = 0;
        tc.skate  = 0;
        tc.obj.overlay.addClass('gameover');
        
        tc.mode = 'gameover';
    },
    
    addLife : function(x) {
        for (i=0; i < x; i++) {
            if(tc.life < 8) {
                tc.obj.life.append('<li></li>');
                tc.life++;
            }
        }
    },
    
    newSprite : function(theNode, theClass, theTime, theCallback) {
        theNode.addClass(theClass);
        
        clearTimeout( tc.minFrame[theClass] );
        
        tc.minFrame[theClass] = setTimeout(function() {
            theNode.removeClass(theClass);
            if (theCallback) theCallback.call();
        }, theTime);
    },
    
    clock : function() {
       if (tc.time == 0) {
            tc.gameOver();
            return false;
       }
       
       if ( parseInt(tc.time/1000) == tc.time/1000 ) tc.time -= 401;
       else tc.time -= 1;
       
       var timeStr = tc.time.toString();
       
       for (i = 0; i < 4 - timeStr.length; i++) timeStr = '0' + timeStr;
       
       for(i = timeStr.charAt(4) == 9 ? 3 : 0; i < 4; i++) tc.obj.digits[i].removeClass().addClass( 'num' + timeStr.charAt(i));
    }
}

$(function() {
    tc.buildTc();
    
    $('#comment').focus(function() {
        tc.commentActive = 1;
    });
    $('#comment').blur(function() {
        tc.commentActive = 0;
    });
});