
(function($,CryptoJS){
    var DEBUG_MODE = false;
    // temporary debugging proxy
    // local
    // var apiURL = 'proxy.php?url=CommunicationService.svc';
    var apiURL = 'http://gra.archipelagmatematyki.pl/CommunicationService.svc';
    var sessionIdRegexResult = location.search.match(/[\d\w]{8}-[\d\w]{4}-[\d\w]{4}-[\d\w]{4}-[\d\w]{12}/);
    var sessionId = null;
    if(sessionIdRegexResult){
      sessionId = sessionIdRegexResult[0];
    }
    if(location.search.match(/debug/)){
      DEBUG_MODE = true;
    }
    var APIHelper = function(){
        return {
            saveResult:function(score, percent, callback){
                if(!sessionId) {
                  // offline mode. abandon ship!
                  return false;
                }
                var hash = CryptoJS.MD5(sessionId+score+percent).toString();
                var ajaxURL = [apiURL,'saveresult', sessionId, score,percent].join('/');
                $.ajax({
                    
                    url:ajaxURL+'?hash='+hash,
                    success:callback
                });
            },
            getHighscores:function(callback){
                if(!sessionId) {
                  // offline mode. abandon ship! (and send false hope to callback function)
                  callback(false);
                  return false;
                }
                var ajaxURL = [apiURL,'gettopscores', sessionId].join('/');
                $.ajax({
                    url:ajaxURL,
                    success:callback
                });
            }            
        }
    }
    var UIHelper = function(){
        return {
            elements:[],
            app:{},
            backgroundColors:[
              '#fffcb7',
              '#ffffff',
              //'#ff3c3c',
              '#60ed93',
              '#c2e0f5',
              '#ecc5f1'
            ],
            createColorSelector:function(){
              var $ui = this;
              $.each(this.backgroundColors, function(i){
                var $innerDot = $('<div />').addClass('dot');
                var $outerDot = $('<div />').addClass('outer-dot').append($innerDot);
                if(i==0){
                  $outerDot.addClass('first');
                }
                if(i==$ui.backgroundColors.length-1){
                  $outerDot.addClass('last');
                }
                $innerDot.css({
                  background:this
                });
                $outerDot.on('click', function(){
                  
                  $('#app-container').css({
                    backgroundColor:$(this).find('.dot').css('backgroundColor')
                  });
                });
                $('#color-selector').append($outerDot);
              })
            },
            buildButton:function(label, onClick,audioId){
                var $button = $('<button />').attr({
                    type:'button'
                });
                $button.addClass('ui-button');
                $button.html(label);
                $button.data('onClick',$.proxy(onClick,$button));
                var $app = this.app;
                if(audioId !== undefined){
                    $button.on('click',function(){
                        $(this).data('onClick')();
                        $app.playSound(audioId);
                    });
                } else {
                    $button.on('click',onClick);
                }
                
                return $button;
            },
            titledContainer:function(title){
                var $container = $('<div />').addClass('ui-container ui-window');
                var $title = $('<h1 />').html(title);
                var $content = $('<div />').addClass('ui-content');
                $container.append($title, $content);
                return $container;
            },
            killPopups:function(){
                while(this.elements.length){
                    var $element = this.elements.pop();
                    $element.remove();
                }
                
            },
            popupWindow:function(content,onClose){
                // append overlay
                var $overlay = $('<div />').css({
                    opacity:0.5,
                    background:'#000',
                    width:800,
                    height:600,
                    position:'absolute',
                    left:0,
                    top:0,
                    zIndex:500
                });
                content.css({
                    position:'absolute',
                    zIndex:501
                });
                this.container.append($overlay);
                this.container.append(content);
                this.container.width();
                content.addClass('popup-window');
                content.css({
                    left:(this.container.width()-content.outerWidth())/2,
                    top:(this.container.height()-content.outerHeight())/2,
                });
                
                if(onClose){
                    var $ui = this;
                    
                    var $closeButton = $('<div></div>').addClass('close-button');
                    $closeButton.on('click', function(){
                        
                        app.playSound('click2');
                        $ui.killPopups();
                        if(typeof onClose == 'function'){
                          onClose();
                        }
                    });
                    content.append($closeButton);
                }
                this.elements.push($overlay,content);
            }
        }
    }
    var App = function(){
        return {
            maxScore:20,
            penalty:2,
            levels:{
                1:{
                    label:'Etap 1',
                    board:190,
                    objectsToBuild:5,
                    minimumWaste:10,
                    score:22,
                    object:{
                      parts:[{
                        width:40,
                        count:2
                      },{
                        width:70,
                        count:1
                      }]
                    }
                },
                2:{
                    label:'Etap 2',
                    board:200,
                    objectsToBuild:8,
                    minimumWaste:40,
                    score:33,
                    object:{
                      parts:[{
                        width:30,
                        count:2
                      },{
                        width:50,
                        count:2
                      },{
                        width:70,
                        count:1
                      }]
                    }
                },
                3:{
                    label:'Etap 3',
                    board:150,
                    objectsToBuild:3,
                    minimumWaste:0,
                    score:45,
                    object:{
                      parts:[{
                        width:15,
                        count:3
                      },{
                        width:35,
                        count:3
                      },{
                        width:75,
                        count:2
                      },{
                        width:100,
                        count:1
                      }]
                    }
                }
            },
            testLevels:{
                1:{
                    label:'Etap 1',
                    board:100,
                    objectsToBuild:1,
                    minimumWaste:0,
                    score:22,
                    object:{
                      parts:[{
                        width:30,
                        count:1
                      },{
                        width:70,
                        count:1
                      }]
                    }
                },
                2:{
                    label:'Etap 2',
                    board:100,
                    objectsToBuild:1,
                    minimumWaste:40,
                    score:33,
                    object:{
                      parts:[{
                        width:60,
                        count:1
                      }]
                    }
                },
                3:{
                    label:'Etap 3',
                    board:100,
                    objectsToBuild:1,
                    minimumWaste:20,
                    score:45,
                    object:{
                      parts:[{
                        width:30,
                        count:1
                      },{
                        width:50,
                        count:1
                      }]
                    }
                },
            },

            maxPoints:0,
            currentSettings:{},
            progressSessionVariableName:'gamestate-'+sessionId,
            loadSession:function(){
              if(sessionId){
                sessionData = $.cookie(this.progressSessionVariableName);
                if(sessionData){
                  this.gameProgress = $.parseJSON(sessionData);
                }
              }
            },
            checkWinningCondition:function(){
                if(this.gameState.completeObjects == this.currentSettings.currentLevel.objectsToBuild){
                  var $app = this;
                  
                  
                  this.gameState.waste += this.gameState.boardLength;
                  // add unused parts to waste too
                  $.each(this.gameState.partsBin, function(width){
                    $app.gameState.waste += width*this;
                    $app.gameState.partsBin[width] = 0;
                  });
                  // calculate score so far
                  // penalty waste

                  this.updateStatus();
                  this.levelComplete();
                }
                
            },
            levelComplete:function(){
              var level = this.currentSettings.currentLevel;
              this.gameState.levelComplete = true;
              var partsList = [];
              var $app = this;
              var penalty = -(($app.currentSettings.currentLevel.minimumWaste-$app.gameState.waste)/10)*$app.penalty;
              var levelScore = Math.max(0,$app.currentSettings.currentLevel.score-penalty);
              $app.gameState.score.percent += levelScore;
              var levelScoreText = 'Zdobyte punkty za etap: '+levelScore+'%';
              if(penalty != 0){
                levelScoreText += ' (-'+penalty+'% za zmarnowany materiał)';
              }
              var $titledContainer = this.ui.titledContainer('Etap zakończony!');
              // construct hiscore table
              var $description = $('<div />').append([
                'Udało ci się zbudować wszystkie potrzebne półki!',
                '',
                'Ilość niewykorzystanego materiału: '+this.gameState.waste+' cm',
                levelScoreText,
                'Punktów w sumie: '+$app.gameState.score.percent+' %'
              ].join('<br />'));
              $titledContainer.find('.ui-content').append($description);
              $app.playSound('level_win');
              this.ui.popupWindow($titledContainer,function(){
                // get next level and start
                var skipLoop = false;
                $.each($app.levels, function(i){
                  if(skipLoop){
                    return;
                  }
                  if(this == $app.currentSettings.currentLevel){
                    skipLoop = true;
                    if(i<Object.keys($app.levels).length){
                      
                      // we've got next level!
                      // carry on
                      $app.currentSettings.currentLevel = $app.levels[parseInt(i)+1];
                      $app.startLevel();
                    } else {
                      // game finished!
                      $app.gameWon();
                    }
                  }
                });
              });
            },
            playSound:function(soundId){
              if(this.gameOptions.sound){
                this.sounds[soundId].currentTime=0;
                this.sounds[soundId].play();
              }
            },
            gameWon:function(){
                this.ui.killPopups();
                this.playSound('win');
                
                var $titledContainer = this.ui.titledContainer('Gratulacje! Zwyciężyłeś!');
                $titledContainer.attr('id','won-box');
                var percentScore = this.gameState.score.percent;
                var totalPoints = Math.round((percentScore/100)*this.maxScore);
                this.gameState.score.points = totalPoints;
                // add some score info
                var scoreContainer = $('<div />').addClass('score');
                var scoreContent = [
                  'Zdobyte punkty: '+percentScore+'% - '+totalPoints+' pkt.',
                ].join('<br />');
                scoreContainer.html(scoreContent);                
                
                $titledContainer.append($('<div />').addClass('cup'));
                $titledContainer.append(scoreContainer);
                var $app = this;
                this.ui.popupWindow($titledContainer,function(){
                    $app.newGame();
                });
                //this.updateProgress();
                this.postScore();
            },
            gameOptions:{
              sound:1
            },
            gameState:{
                moves:0,
                boardLength:0,
                hasValidCuts:false,
                levelStarted:false,
                partsBin:{},
                completeObjects:0,
                activePart:false,
                waste:0,
                score:{
                  percent:0,
                  points:0
                }
            },
           
            container:null,
            statusBox:null,
            progressBox:null,
            updateStatus:function(){
              $('#waste .value').html(this.gameState.waste);
              $('#built .value').html(
                this.gameState.completeObjects+' / '+this.currentSettings.currentLevel.objectsToBuild
              );

            },
            showNewLevelInfo:function(){
              var partsList = [];
              var level = this.currentSettings.currentLevel;
              $.each(this.currentSettings.buildedObject.parts, function(){
                partsList.push(this.width+' cm - '+this.count+' szt.');
              });
              var $titledContainer = this.ui.titledContainer(level.label);
              $titledContainer.attr('id','highscore-box');
              // construct hiscore table
              var $description = $('<div />').append([
                'W tym etapie budujesz półkę złożoną z części:',
                partsList.join('<br />'),
                '',
                'Liczba półek do zbudowania: '+level.objectsToBuild,
                'Długość deski: '+level.board+'cm',
                'Maksimum odpadów: '+level.minimumWaste+' cm'
              ].join('<br />'));
                $titledContainer.find('.ui-content').append($description);
              this.ui.popupWindow($titledContainer,function(){});
            },
            postScore:function(){
                var score = this.gameState.score;
                this.api.saveResult(score.points, score.percent);
            },
            initPlanTable:function(){
              var $planPartsListTable = $('#plan table');
              // clear parts list
              $planPartsListTable.find('tr').not('.header').remove();
              // create new parts list
              // TODO:
              //  first sort by size 
              $.each(this.currentSettings.buildedObject.parts, function(){
                var $partRow = $('<tr />');
                $partRow.append($('<td />').html(this.width+' cm').addClass('part-width'));
                $partRow.append($('<td />').html(0).addClass('bin-count'));
                $partRow.append($('<td />').html(this.count).addClass('need-count'));
                $partRow.data('part', this);
                $planPartsListTable.append($partRow);
              });
            },
            startLevel:function(){
              this.gameState.levelStarted = true;
              this.gameState.levelComplete = false;
              var level = this.currentSettings.currentLevel;
              var $app = this;
              // show info
              this.currentSettings.buildedObject = level.object;
              this.currentSettings.boardLength = level.board;
              this.boardScale = this.boardHtmlWidth/this.currentSettings.boardLength;
              this.showNewLevelInfo();
              this.gameState.moves = 0;
              $.each(this.currentSettings.buildedObject.parts, function(){
                $app.gameState.partsBin[this.width] = 0;
              });
              this.gameState.completeObjects = 0;
              this.gameState.waste = 0;
              this.initPlanTable();
              //this.updateStatus();
              this.updateStatus();
              this.getNewBoard();
            },
            restartGame:function(){
              var $app = this;
              if(!this.gameState.levelStarted){
                  return false;
              }
              this.ui.killPopups();
              this.startLevel();
            },
            newGame:function(){
                this.ui.killPopups();
                this.container.find('#cutting-table').show();
                this.container.find('.splash').hide();
                this.currentSettings.currentLevel = this.levels[1];
                this.gameState.score = {
                  percent:0,
                  points:0
                };
                this.startLevel();
            },
            sounds:[],
            initSound:function(){
                this.sounds['saw'] = new Audio('sound/saw.ogg');
                this.sounds['click'] = new Audio('sound/button_50.ogg');
                this.sounds['click2'] = new Audio('sound/button_30.ogg');
                this.sounds['win'] = new Audio('sound/win.ogg');
                this.sounds['level_win'] = new Audio('sound/level_win.ogg');
                this.sounds['flip'] = new Audio('sound/button_16.ogg');
            },
            createCutMark:function(part){
            
              var $possibleCutMark = $('<div />').addClass('cut-mark possible');
              var $board = $('#board');
              var markOffset = Math.round(part.width*this.boardScale);
              var $markContainer = $('<div />').addClass('cut-mark-wrapper');
              $markContainer.append($possibleCutMark);
              var $markValueLabel = $('<div />').addClass('cut-mark-value').html(part.width+' cm');
              $markContainer.append($markValueLabel);
              $markContainer.css({
                left:markOffset
              });
              $board.append($markContainer);
              // attach html element to part object (used for marking active cut mark on #board mousemove event)
              part.markDiv = $markContainer;
              // set x position
              part.offsetX = markOffset;
              
            },
            drawPossibleMarks:function(){
              var $app = this;
              $.each(this.currentSettings.buildedObject.parts, function(){
                $app.createCutMark(this);
                this.canBeCut = true;
              });
            },
            getNewBoard:function(){
              if(this.gameState.levelComplete){
                return;
              }
              this.trackMouse = false;
              this.gameState.activePart = false;
              // remove any leftover marks/etc.
              $('#board').children().remove();
              // grab new board
              this.drawPossibleMarks();
              var $boardPiece = $('<div />').addClass('board-piece');
              $boardPiece.css({
                width:this.boardHtmlWidth
              });
              var $app = this;
              $('#board').append($boardPiece);
              $('#board').css({
                left:800
              }).animate({
                left:0
              },{duration:1000,complete:function(){$app.trackMouse=true}});
              this.gameState.boardLength = this.currentSettings.boardLength;
              this.updateBoardLengthStatus();
            },
            updateBoardLengthStatus:function(){
              $('#board-left-length span.value').html(this.gameState.boardLength);
            },
            updatePartsBin:function(){
              var $app = this;
              $('#plan table tr').not('.header').each(function(){
                var $row = $(this);
                var partsInBin = $app.gameState.partsBin[$row.data('part').width];
                $row.find('td.bin-count').html(partsInBin);
              });
              var $app = this;
              $('#plan table tr').not('.header').each(function(){
                var $row = $(this);
                var partsInBin = $app.gameState.partsBin[$row.data('part').width];
                $row.find('td.bin-count').html(partsInBin);
              });
            },            
            
            addPartToBin:function(part){
              this.gameState.partsBin[part.width] += 1;
              this.checkBinForCompletedObjects();
              this.updatePartsBin();
              
            },
            checkBinForCompletedObjects:function(){
              var objectComplete = true;
              var $app = this;
              $.each(this.currentSettings.buildedObject.parts, function(){
                if($app.gameState.partsBin[this.width] < this.count){
                  objectComplete = false;
                }
              });
              if(objectComplete){
                // remove parts from bin
                $.each(this.currentSettings.buildedObject.parts, function(){
                  $app.gameState.partsBin[this.width]-=this.count;
                });
                // and add new object
                
                this.gameState.completeObjects++;
                this.updateStatus();
                
                this.checkWinningCondition();
              }
                
            },
            
            onBoardMouseMove:function(e){
              var $app = this;
              var $mouseLayer = $(e.target);
              var $board = $('#board');
              $mouseLayer.mouseX = e.offsetX?e.offsetX:e.originalEvent.layerX;
              if($app.trackMouse == false){
                return;
              }
              $.map($board.data('saw'),function(i){
                i.css({
                  left:$mouseLayer.mouseX
                });
              });
              if(!$app.gameState.activePart){
                $app.gameState.activePart = $app.currentSettings.buildedObject.parts[0];
                $app.gameState.activePart.markDiv.addClass('active');
              }
              var activePartDistance = Math.abs($app.gameState.activePart.offsetX-$mouseLayer.mouseX);
              // check which cut part will be mark as cutting (closest mark to mouse position)
              $.each($app.currentSettings.buildedObject.parts, function(){
                if(!this.canBeCut){
                  return;
                }
                var partDistance = Math.abs(this.offsetX-$mouseLayer.mouseX);
                if(partDistance<activePartDistance){
                  $app.gameState.activePart.markDiv.removeClass('active');
                  $app.gameState.activePart = this;
                  $app.gameState.activePart.markDiv.addClass('active');
                }
              });
            },
            onBoardSplitAnimationComplete:function(){
              // check if we need new board
              var $app = this;
              var firstPart = $app.currentSettings.currentLevel.object.parts[0];
              var onePieceLeft = ($app.gameState.boardLength == firstPart.width);
              if(!$app.gameState.hasValidCuts || onePieceLeft){
                $app.trackMouse = false;
                if($app.gameState.boardLength){ // some waste!
                  if(onePieceLeft){
                    firstPart.markDiv.fadeOut();
                  }
                  $($('#board .board-piece')[0]).animate({
                    top:140
                  },{complete:function(){
                    if(onePieceLeft){
                      $app.gameState.boardLength = 0;
                     
                      $app.addPartToBin($app.currentSettings.currentLevel.object.parts[0]);
                    }
                    $app.getNewBoard();
                  }});
                } else {
                  $app.getNewBoard();
                }
              } else {
                $app.trackMouse = true;
              }
            },
            onBoardCut:function(){
              var $board = $('#board');
              var cutX = this.gameState.activePart.offsetX;
              boardIsSplit = true;
              var restPiece = $($board.find('.board-piece')[0]);
              var $app = this;
              // add newly cut piece
              var newPiece = $('<div />').addClass('board-piece');
              var _backgroundPosition = restPiece.css('background-position').split(" ");
              var backgroundPosition = [];
              $.each(_backgroundPosition, function(i){
                backgroundPosition[i] = parseInt(_backgroundPosition);
              });
              newPiece.css({
                width:cutX,
                backgroundPosition:backgroundPosition[0]+'px 0px'
              });
              $board.append(newPiece);
              // and shorten current
              restPiece.css({
                left:cutX,
                width:restPiece.width()-cutX,
                backgroundPosition:backgroundPosition[0]-cutX+'px 0px'
              });
              restPiece.animate({left:0},{easing:"easeInOutQuart",duration:1000,complete:$.proxy(this.onBoardSplitAnimationComplete,this)});
              newPiece.animate({top:190},{easing:"easeInQuart",duration:1000,complete:function(){this.remove()}});
              // drop down the piece
              // add newly cut piece to parts bin
              this.addPartToBin(this.gameState.activePart);
              
            },
            onBoardMouseClick:function(e){
            
              var $app = this;
              if($app.trackMouse == false){
                return;
              }
              var $board = $('#board');
              // cut the board
              // stop mouse tracking at cutting time
              var activePart = $app.gameState.activePart;
              if(isNaN($app.gameState.activePart.width)){
                return;
              }
              $app.trackMouse = false;
              var cutX = activePart.offsetX;
              var boardIsSplit = false;
              var moveDuration = 300;
              $app.gameState.boardLength -= activePart.width;
              $app.updateBoardLengthStatus();
              
              $app.gameState.hasValidCuts = false;
              // deactivate cut marks longer than left board and check if we have valid cuts
              $.each($app.currentSettings.buildedObject.parts,function(){
                if(this.width>$app.gameState.boardLength){
                  this.canBeCut = false;
                  this.markDiv.fadeOut();
                  if(this == activePart){
                    activePart = false;
                  }                      
                }
                if(this.canBeCut){
                  $app.gameState.hasValidCuts = true;
                }
              });
              if(this.gameState.hasValidCuts == false){
                // no valid cuts.
                // add remaining to waste
                
                $app.gameState.waste+=$app.gameState.boardLength;
                $app.gameState.boardLength = 0;
                $app.updateStatus();
              }
              
              var onBoardCutFired = false; // we need this to prevent double firing on animation end [TODO: rework saw object 2 divs > 1 object]
              $.map($board.data('saw'),function(i){
                // place saw pieces on active cut mark
                i.animate({left:cutX, top:-90},{duration:moveDuration,complete:function(){$app.playSound('saw');}})
                // move down
                 .animate({top:35},{duration:moveDuration,complete:function(){
                 
                   if(!onBoardCutFired){
                     onBoardCutFired = true;
                     $app.onBoardCut();
                   }
                 }})
                // and up
                 .animate({top:-70},{duration:moveDuration});
              });
            },
            initCuttingTable:function(){
              
              var $cuttingTable = $('#cutting-table');
              var $board = $('#board');
              var $mouseLayer = $('<div />');
              $mouseLayer.css({
                width:$board.width(),
                height:$board.height(),
                zIndex:200,
                position:'absolute',
                cursor:'pointer'
              });
              $cuttingTable.append($mouseLayer);
              $board.data('saw',[
                $('#cutting-table #saw-front'),
                $('#cutting-table #saw-back')
              ]);
              $mouseLayer.on('mousemove', $.proxy(this.onBoardMouseMove,this)); // proxy event function so we can reach app object as 'this'
              $mouseLayer.on('click', $.proxy(this.onBoardMouseClick,this)); // as above
            },
            init:function(container){
                if(DEBUG_MODE){
                  this.levels = this.testLevels;
                }
                this.initSound();
                this.initCuttingTable();
                this.ui = new UIHelper();
                this.ui.app = this;
                this.ui.createColorSelector();
                this.api = new APIHelper();
                $('#app-container').css({
                  backgroundColor:this.ui.backgroundColors[0]
                });
                
                this.ui.container = this.container = container;
                var $boardContainer = $('<div />').addClass('board-container');
                this.boardContainer = $boardContainer;
                container.append($boardContainer);
                this.buildMenu();
                container.append(
                    $('<div />').html(
                        $('#app-splash').html()
                    ).addClass('splash')
                );
                this.loadSession();
                // calculate maxPoints (used for calculating percentage progress)
                var $app = this;
                this.container.append(this.progressBox);
                // arm sawing board
                // add empty overlay mouse detection layer
                this.container.find('.splash').hide();
                this.container.find('#cutting-table').hide();
            },
            boardHtmlWidth:672,
            showHighscore:function(){
                var $titledContainer = this.ui.titledContainer('Najlepsi z najlepszych');
                $titledContainer.attr('id','highscore-box');
                // construct hiscore table
                var $scoreTable = $('<table />').addClass('highscores');
                var $scoreTableHeader = $('<tr />').append('<th class=\'nick\'>Nick</th><th class=\'score\'>Wynik</th><th class=\'score\'>Wynik (%)</th>');
                $scoreTable.append($scoreTableHeader);
                var $app = this;
                this.api.getHighscores(function(r){
                    if(r){
                      var results = $(r).find('UserScore');
                      if(results.length){
                          $.each(results, function(){
                              var $scoreRow = $('<tr />');
                              var nick = this.getElementsByTagName('Nick')[0].childNodes[0].nodeValue;
                              var score = this.getElementsByTagName('Result')[0].childNodes[0].nodeValue;
                              var scorePercent = this.getElementsByTagName('ResultPercent')[0].childNodes[0].nodeValue;
                              //var nick = nicks[i%nicks.length];
                              //var score = startScore+i;
                              $scoreRow.append('<td>'+nick+'</td><td>'+score+'</td><td>'+scorePercent+'</td>');
                              $scoreTable.append($scoreRow);
                          });
                      }
                    } else {
                      $scoreRow = $('<tr />').append($('<td>Nie udało się pobrać wyników.</td>').attr({
                        colspan:3,
                        align:'center'
                      }));
                      $scoreTable.append($scoreRow);
                    }
                    $app.ui.popupWindow($titledContainer,function(){});
                });
                
                
                $titledContainer.append($scoreTable);
                // TODO refactor
                // create menu items object in app
                
            },
            showCredits:function(){
                var $titledContainer = this.ui.titledContainer('Twórcy gry');
                $titledContainer.attr('id','credits-box');
                $titledContainer.append($('#app-credits').html());
                // TODO refactor
                // create menu items object in app
                this.ui.popupWindow($titledContainer,true);
            },            
            showHelp:function(){
                var $titledContainer = this.ui.titledContainer('Zasady gry');
                $titledContainer.attr('id','help-box');
                $titledContainer.append($('#app-help').html());
                // TODO refactor
                // create menu items object in app
                this.ui.popupWindow($titledContainer,true);
            },            
            buildMenu:function(){
                var $menuContainer = $('<div />').addClass('menu-container');
                
                var menuItems = [
                    {
                        label:'Pomoc',
                        onClick:$.proxy(this.showHelp,this),
                        css:'help'
                    },
                    {
                        label:'Najlepsi',
                        onClick:$.proxy(this.showHighscore,this),
                        css:'highscore'
                        
                    },
                    {
                        label:'Nowa gra',
                        onClick:$.proxy(this.newGame,this),
                        
                        css:'new-game'
                    },
                    {
                        label:'Restart',
                        onClick:$.proxy(this.restartGame,this),
                        css:'restart'
                    }
                ]
                var $app = this;
                $.each(menuItems, function(){
                    var $menuButton = $app.ui.buildButton(this.label, this.onClick, 'click');
                    if(this.css){
                      $menuButton.addClass(this.css);
                    }
                    $menuContainer.append($menuButton);
                });
                this.container.append($menuContainer);
                this.container.append(this.ui.buildButton("Twórcy", $.proxy(this.showCredits, this), 'click').addClass('small credits'));
            }
            
        }
    }

    $(document).on('ready', function(){
        app = new App();
        app.init($('#app-container'));
    });
}(jQuery,CryptoJS));
