/************************************************************/
/* Array extensions *****************************************/
/************************************************************/

Object.extend(Array.prototype, {

    swap: function(index1, index2) {
        var swap = this[index1];
        
        this[index1] = this[index2];
        this[index2] = swap;
        
        return this;
    },
	
    shuffle: function(inline, times) {
        var list = (inline != false ? this : this.clone());
        
        for(var i = 0, len = list.length * (times || 4); i < len; i++) {
            list.swap((Math.random() * list.length).floor(),(Math.random() * list.length).floor());
        }
        
        return list;
    },
	
    randomDraw: function(items) {
        items = Number(items) || 1;
        
        var list = this.shuffle(false);
        
        if (items >= list.length) {
            return list;
        }
        
        var sample = [];
        
        for(var i = 1; i <= items; i++) {
            if(list.length > 0) {
                sample.push(list.shift());
            } else {
                return sample;
            }
        }
        
        return sample;
    },

	compare: function(testArr) {
		if (this.length != testArr.length) return false;
		
		for (var i = 0; i < testArr.length; i++) {
			if (this[i].compare) { 
				if (!this[i].compare(testArr[i])) return false;
			}
			if (this[i] !== testArr[i]) return false;
		}
		
		return true;
	}
});

/************************************************************/
/* Base class for all game objects **************************/
/************************************************************/

var GameObject = Class.create();

GameObject.prototype = {
	
	initialize: function(name)	{
		this.name = name;
		this.state = null;
		this.timers = [];
	},
	
	setState: function(state) {
		this.state = state;
	},
	
	scheduleAction: function(method, param, interval, repeat) {
		data = param || {};
		
		data.action = {
			callback	: eval('this.'+method+'.bind(this)'),
			interval	: interval,
			repeat		: repeat
		}
		
		var timer = new PeriodicalExecuter(function(pe) { 
						this.action.timer = pe;
						this.action.callback(this);
					}.bind(data), interval);
		
		this.timers.push(timer);
		
		return timer;
	},
	
	cancelAction: function(timer) {
		this.timers = this.timers.without(timer);
		timer.stop();
	},
	
	cancelAll: function() {
		this.timers.map(function(timer) {
			timer.stop();
		})
		this.timers.clear();
	}
}

/************************************************************/
/* Bird class ***********************************************/
/************************************************************/

var Bird = Class.create(GameObject, {
	ballOffsetLeft: 20,
	ballOffsetTop: -95,
	
	initialize: function($super, index, cssClass, map, app) {
		$super('bird_'+index);
		
		this.app = app;
		this.index = index;
		this.element = this.createElement(this.name, cssClass);
		this.imageMap = this.createImagemap(map);
	},
	
	createElement: function(name, cssClass) {
		var element = document.createElement('DIV');
		element.id = name;
		element.className = 'bird '+cssClass;
		Element.hide(element);
		
		document.body.appendChild(element);
		
		return element;
	},
	
	createImagemap: function(map) {
		if (document.all && navigator.userAgent.indexOf("opera") == -1) {
			var birdMap = document.createElement('<MAP name="'+this.name + '_map'+'">');
			birdMap.innerHTML = map.innerHTML;
		}
		else {
			var birdMap = map.cloneNode(true);
			birdMap.name = this.name + '_map';
		}
		birdMap.onclick = birdMap.onClickEvent = this.onClickEvent.bind(this);
		this.element.appendChild(birdMap);
		
		var picture = document.createElement('IMG');
		picture.border = 0;
		picture.src = '/themes/roulette/i/spacer.gif';
		picture.width = parseInt(this.element.getWidth());
		picture.height = parseInt(this.element.getHeight());
		picture.useMap = '#'+birdMap.name;
		this.element.appendChild(picture);

		return birdMap;
	},
	
	show: function(pe) {
		Element.show(this.element);
		this.setState('visible');
	},
	
	hide: function() {
		Element.hide(this.element);
		this.setState('invisible');
	},
	
	move: function(data) {
		Element.setStyle(this.element, {
			'left': data.left + 'px',
			'top':  data.top  + 'px'
			});
	},
	
	moveRandom: function(data) {
		//console.debug(data.action);
		//console.debug(data.action.timer);
		//console.debug(data.action.repeat);
		if (data.action && data.action.timer && !data.action.repeat) {
			this.cancelAction(data.action.timer);
		}
		
		!this.ball || this.ball.setState('vacant');
		
		this.ball = this.app.getRandomBall();
		
		//console.debug(this.ball);
		var position = this.ball.getPosition();
		//console.debug(this.ball.getPosition());
		//console.debug(123);
		//console.debug(position);
		//alert(1);
		//alert(getBounds(this.ball));
		
		position.left += this.ballOffsetLeft;
		position.top  += this.ballOffsetTop;
		
		this.move(position);
		
		this.ball.setState('occupied');
	},
	
	messUp: function() {
		this.ball.createShit();
	},
	
	die: function() {
		this.cancelAll();
		this.hide();
		this.element.remove();
		this.setState(null);
		
		this.ball.setState('vacant');
	},
	
	onClickEvent: function(event) {
		this.die();
		this.app.killBird(this);
	}
});

/************************************************************/
/* Ball class ***********************************************/
/************************************************************/

var Ball = Class.create(GameObject, {
	
	initialize: function($super, cssClass, number, parent, app) {
		$super('ball_'+number);
		
		this.app = app;
		this.number = number;
		this.shit = null;
		this.element = this.createElement(parent, cssClass);
	},
	
	createElement: function(parent, cssClass) {
		var element = document.createElement('DIV');
		
		element.id = this.name;
		element.className = 'ball '+cssClass;
		element.onclick = this.onClickEvent.bind(this);
		
		$(parent).appendChild(element);
		
		return element;
	},
	
	createShit: function() {
		if (!this.shit) {
			var position = this.getPosition();
			this.shit = document.createElement('DIV');
			this.shit.className = 'shit';
			Element.setStyle(this.shit, {
				left		: position.left+'px',
				top			: position.top+'px'
			});
			
			this.element.appendChild(this.shit);
			
			this.app.decCleanBalls();
		}
	},
	
	getPosition: function() {
		/*console.debug(this.element.cumulativeOffset());*/
		/*return this.element.cumulativeOffset();*/
		return this.getCumulativeOffset(this.element);
	},
	
	getCumulativeOffset: function(element)
	{
		var left = element.offsetLeft;
		var top = element.offsetTop;
		for (var parent = element.offsetParent; parent; parent = parent.offsetParent)
		{
			left += parent.offsetLeft - parent.scrollLeft;
			top += parent.offsetTop - parent.scrollTop
		}
		return {left: left, top: top, width: element.offsetWidth, height: element.offsetHeight};
	},
	
	getSize: function() {
		return {width: this.element.getWidth(), height: this.element.getHeight()};
	},
	
	onClickEvent: function(event) {
		this.app.updateUserQueue(this);
	}
});

/************************************************************/
/* Application class ****************************************/
/************************************************************/

var GameApp = Class.create(GameObject, {
	killScore: 10,
	
	levelTable: [
		{score: 0,		moveInterval: 1,   lifeTime: 5, incBirds: false	},
		{score: 50,		moveInterval: 0.9, lifeTime: 5, incBirds: false	},
		{score: 100,	moveInterval: 0.8, lifeTime: 4, incBirds: true	},
		{score: 150,	moveInterval: 0.7, lifeTime: 4, incBirds: false	},
		{score: 200,	moveInterval: 0.6, lifeTime: 3, incBirds: true	},
		{score: 300,	moveInterval: 0.5, lifeTime: 3, incBirds: true	}
	],
	
	numBalls: 5,
	minBallNumber: 0,
	maxBallNumber: 36,
	minCleanBalls: 2,
	
	birdStyles: $H({
		bird_1: [1,61,24,60,38,43,31,37,37,28,38,13,49,2,75,2,87,12,88,27,96,33,88,37,100,42,92,53,86,76,67,89,43,90,21,82],//[91,24,76,0,53,0,26,43,  0,47,35,75,66,75,86,61,92,34,102,28],
		bird_2: [9,49,14,75,29,89,62,91,82,79,99,62,77,60,64,43,70,38,64,29,63,11,51,2,25,2,14,11,13,26,4,33,15,36,2,43],//[11,22,22,1,49,1,75,45,100,48,62,76,37,77,17,65, 8,34,  1,27],
		bird_3: [1,61,24,60,38,43,31,37,37,28,38,13,49,2,75,2,87,12,88,27,96,33,88,37,100,42,92,53,86,76,67,89,43,90,21,82],
		bird_4: [9,49,14,75,29,89,62,91,82,79,99,62,77,60,64,43,70,38,64,29,63,11,51,2,25,2,14,11,13,26,4,33,15,36,2,43],
		bird_5: [1,61,24,60,38,43,31,37,37,28,38,13,49,2,75,2,87,12,88,27,96,33,88,37,100,42,92,53,86,76,67,89,43,90,21,82],
		bird_6: [9,49,14,75,29,89,62,91,82,79,99,62,77,60,64,43,70,38,64,29,63,11,51,2,25,2,14,11,13,26,4,33,15,36,2,43],
		bird_7: [1,61,24,60,38,43,31,37,37,28,38,13,49,2,75,2,87,12,88,27,96,33,88,37,100,42,92,53,86,76,67,89,43,90,21,82],
		bird_8: [9,49,14,75,29,89,62,91,82,79,99,62,77,60,64,43,70,38,64,29,63,11,51,2,25,2,14,11,13,26,4,33,15,36,2,43]
	}),
	
	initialize: function($super, name, parent) {
		
		$super(name);
		
		this.imageMaps = this.createImagemaps();

		this.element = this.createElement(parent, name);
		
		this.userScore = 0,
		this.levelIndex = 0,
		this.level = this.levelTable[this.levelIndex];
		this.moveInterval = this.level.moveInterval;
		this.birdLifeTime = this.level.lifeTime;
		
		this.birds = $H();
		
		this.balls = this.randomBalls();
		this.cleanBalls = this.numBalls;
		this.ballQueue = [0,1,2,3,4];//this.randomQueue();
		
		this.userQueue = [];
		
//		console.debug(this.ballQueue);
	},
	
	createElement: function(parent, name) {
		var element = document.createElement('DIV');
		//console.debug(parent);
		//console.debug(name);
		//console.debug(123);
		element.id = name;
		
		$(parent).appendChild(element);
		
		return element;
	},
	
	createImagemaps: function() {
		var imageMaps = $H();
		
		this.birdStyles.each(function(style) {
			var area = document.createElement('AREA');
			area.shape = 'poly';
			if (style.value.join) {
				area.coords = style.value.join(',');
			}
			area.href = 'javascript://';

			var map = document.createElement('MAP');
			map.name = style.key;
			map.appendChild(area);
			
			this.set(style.key, map);
		}.bind(imageMaps));
		
		return imageMaps;
	},
	
	newBird: function() {
		
		bird = this.randomBird();
		this.runBird(bird);		
		this.birds.set(bird.name, bird);
	},
	
	randomQueue: function() {
		var range = $A($R(0,this.numBalls-1));
		return range.shuffle();
	},
	
	randomBalls: function() {
		var numbers = $A($R(this.minBallNumber,this.maxBallNumber)).shuffle();
		var balls = numbers.slice(0,this.numBalls);
		var ballnum=0;
		
		isballnums.shift();
		return balls.map(function(number, index) {
			//var start = 50 / (this.numBalls+1);
			//var pos = Math.round(start * (2*index + 1));
			number = isballnums.shift();
			var ball = new Ball('', number, this.name, this);
			
			//Element.setStyle(ball.element, {'left': pos + '%'});
			if(ballnum%2==0) var clname = 'up'; else clname = 'down';
			ball.element.className = 'p' + (ballnum+1) + ' ball ball' + (ballnum+1) + ' ' + clname;
			ballnum++;
			
			ball.setState('vacant');
			
			return ball;
		}.bind(this))
	},
	
	randomBird: function() {
		var classes = this.imageMaps.keys();
		var cssClass = parseInt(Math.round(Math.random()*(classes.length-1)));
		var map = this.imageMaps.get(classes[cssClass]);
		var birds = this.birds.values();
		var lastBird = birds[birds.size()-1];
		var index = lastBird ? lastBird.index+1 : 0;
		
		return new Bird(index, classes[cssClass], map, this);
	},
	
	getRandomBall: function() {
		while(true) {
			var index = parseInt(Math.round(Math.random()*(this.balls.length-1)));
			var ball = this.balls[index];
			
			if (ball.state == 'vacant') {
				return ball;
			}
		}
	},
	
	welcome: function() {
	    
		document.getElementById("my_bird").style.display = 'none';
	    
		this.setState('welcome');
		
		var msg = document.createElement('DIV');
		msg.app = this;
		msg.className = 'msg';
		msg.innerHTML = 'Вы набрали секретную комбинацию. Задача игры - набрать максимальное количество очков. Для этого нужно попасть прицелом в появляющиеся птички и убить их! В процессе игры скорость появления птичек увеличивается. Ваша задача - не дать птичке “испортить” шарик, на котором она сидит.';
		
		msg.btnStart = document.createElement('DIV');
		msg.btnStart.className = 'start';
		msg.btnStart.onclick = function() {
			this.remove();
			this.app.start();
		}.bind(msg);
		msg.appendChild(msg.btnStart);
		
		msg.btnCancel = document.createElement('DIV');
		msg.btnCancel.className = 'cancel';
		msg.btnCancel.onclick = function () {
			msg.app.setState(null);
			Element.remove(this);
		}.bind(msg);
		msg.appendChild(msg.btnCancel);
		
		this.element.appendChild(msg);
		Element.show(msg);
	},
	
	start: function() {
		// Create score indicator
		this.scoreIndicator = document.createElement('DIV');
		this.scoreIndicator.className = 'score';
		this.scoreIndicator.innerHTML = this.userScore;
		this.element.appendChild(this.scoreIndicator);
		
		// Create "end game" button
		this.finishButton =  document.createElement('DIV');
		this.finishButton.className = 'finish';
		this.finishButton.onclick = this.end.bind(this);
		this.element.appendChild(this.finishButton);
		
		document.getElementById('container').className = 'game';
		document.getElementById('header').className = 'game';
		document.getElementById('headerin').className = 'game';
		document.getElementById('chgme').className = 'game';
		document.getElementById('balls').className = 'game';
		
		this.newBird();
		
		this.setState('running');
//		console.debug('');
	},
	
	runBird: function(data) {
		var bird = data.value || data;
		var interval = this.moveInterval + Math.random();
		
		bird.scheduleAction('moveRandom', null, interval, true);
		bird.scheduleAction('show', null, interval+0.1, false);
		bird.scheduleAction('messUp', null, this.birdLifeTime, true);
	},
	
	decCleanBalls: function() {
		if (--this.cleanBalls <= this.minCleanBalls) {
			this.end();
		}
	},
	
	updateUserQueue: function(ball) {
		if (this.state == null)
		{
			var index = this.balls.indexOf(ball);
			
			if (this.userQueue.size() == this.numBalls) {
				this.userQueue.shift();
			}
			
			this.userQueue.push(index);
			
			if (this.ballQueue.compare(this.userQueue)) {
				this.welcome();
			}
		}
	},
	
	killBird: function(bird) {
		this.newBird();
		
		this.birds.unset(bird.name);
		
		this.userScore += this.killScore;
		
		this.scoreIndicator.innerHTML = this.userScore;
		
		if (this.userScore >= this.level.score && ++this.levelIndex < this.levelTable.size()) {
			this.level = this.levelTable[this.levelIndex];
			this.moveInterval = this.level.moveInterval;
			this.birdLifeTime = this.level.lifeTime;
			
			if (this.level.incBirds) {
				this.newBird();
			}
//			console.debug(this.level);
		}
		
//		console.debug(this.userScore);
	},
	
	results: function() {
		var msg = document.createElement('DIV');
		msg.app = this;
		msg.className = 'msg';
		msg.setAttribute('id', 'msg');
		msg.innerHTML = 'Прекрасно! Ваш результат: <b>' + this.userScore + '</b>'
		+ '<br />Введите ваше имя: <input type="text" id="msgName" value=""/>'
		+ '<br />Введите ваш номер телефона: <input type="text" id="msgValue" value="+7 *** *** ** **"/>';
		
		//msg.inputName = document.createElement('INPUT');
		//msg.inputName.type = 'text';
		//msg.inputName.value = '+7 *** *** ** **';
		//msg.inputName.setAttribute('id', 'msgValue');
		//msg.inputName.focus();
		////msg.inputName.onclick = function() { msg.inputName.value = '';}
		//msg.appendChild(msg.inputName);
		
		
		msg.save = document.createElement('DIV');
		msg.save.className = 'save';
		msg.save.onclick = function() {
			if (ValidateForm())
			{
			//msg.remove
			var ajax   = new Ajax.Updater(
			{ success: 'msg' },  // возвращаемый скриптом текст должен быть уже html-форматированным (таблица)
			'winners.php',		// путь к скрипту (в скрипте необходимо проверять, автворизован ли пользователь, и не плодить новые записи в базе)
			{
			    method: 'post', // GET-запрос
			    parameters: 'score='+msg.app.userScore+'&user='+document.getElementById('msgValue').value + '&name='+document.getElementById('msgName').value,
			    onFailure: msg.app.ajaxerror // функция чуть ниже
			}
            );
			}
		}
		msg.save.style.height = '230px';
		msg.appendChild(msg.save);
		
		msg.cancel = document.createElement('DIV');
		msg.cancel.className = 'cancel';
		msg.cancel.onclick = function() {
			this.app.element.remove();
			window.onload();
		}.bind(msg);
		msg.appendChild(msg.cancel);
		
		this.element.appendChild(msg);
		Element.show(msg);
	},
	
	ajaxerror: function() {
	    $$('.msg').innerHTML = 'Ошибка отправки ajax-запроса';
	},
	
	end: function() {
		this.birds.map(function(element) {
			var bird = element.value;
			bird.cancelAll();
			bird.element.remove();
		});
		
		$('container').className = ''; $('header').className = ''; $('headerin').className = ''; $('chgme').className = ''; $('balls').className = '';
		
		
		Element.remove(this.scoreIndicator);
		Element.remove(this.finishButton);
		
		document.getElementById("my_bird").style.display = 'block';
		
		this.results();
	}
});

/************************************************************/
/* Start game ***********************************************/
/************************************************************/

window.onload = function() {
	this.game = new GameApp('myGame', 'divGame');
	timerID = setTimeout(stupidBird, 1000);
}

function getBounds(element)
{
  var left = element.offsetLeft;
  var top = element.offsetTop;
  for (var parent = element.offsetParent; parent; parent = parent.offsetParent)
  {
    left += parent.offsetLeft - parent.scrollLeft;
    top += parent.offsetTop - parent.scrollTop
  }
  return {left: left, top: top, width: element.offsetWidth, height: element.offsetHeight};
}

function stupidBird(){
    if(!document.getElementById("my_bird")) return;
    var bird = document.getElementById("my_bird");
    var aBall = parseInt(Math.random()*4) + 1;
    var sBall = 'p'+ aBall;
    var my_delay = aBall * 1000;
    var classs = document.getElementsByClassName(sBall)[0];
    bird.style.left = classs.offsetLeft + 20+'px';
    bird.style.top = classs.offsetTop - 80+'px';
    if(aBall < 3){ bird.className = 'bird2'; }else{ bird.className = 'bird'; }
    timerID = setTimeout('stupidBird()', my_delay);
}

document.getElementsByClassName = function(cl) {
    var retnode = [];
    var myclass = new RegExp('\\b'+cl+'\\b');
    var elem = this.getElementsByTagName('*');
    for (var i = 0; i < elem.length; i++) {
	var classes = elem[i].className;
        if (myclass.test(classes)) retnode.push(elem[i]);
    }
    return retnode;
};

/**
 * DHTML phone number validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 */

// Declaring required variables
var digits = "0123456789";
// non-digit characters which are allowed in phone numbers
var phoneNumberDelimiters = "()- ";
// characters which are allowed in international phone numbers
// (a leading + is OK)
var validWorldPhoneChars = phoneNumberDelimiters + "+";
// Minimum no of digits in an international phone no.
var minDigitsInIPhoneNumber = 11;
var maxDigitsInIPhoneNumber = 11;

function isInteger(s)
{   var i;
    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number.
        var c = s.charAt(i);
        if (((c < "0") || (c > "9"))) return false;
    }
    // All characters are numbers.
    return true;
}
function trim(s)
{   var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not a whitespace, append to returnString.
    for (i = 0; i < s.length; i++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (c != " ") returnString += c;
    }
    return returnString;
}
function stripCharsInBag(s, bag)
{   var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for (i = 0; i < s.length; i++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

function checkInternationalPhone(strPhone){
var bracket=3
strPhone=trim(strPhone)
if(strPhone.indexOf("+")>1) return false
if(strPhone.indexOf("-")!=-1)bracket=bracket+1
if(strPhone.indexOf("(")!=-1 && strPhone.indexOf("(")>bracket)return false
var brchr=strPhone.indexOf("(")
if(strPhone.indexOf("(")!=-1 && strPhone.charAt(brchr+2)!=")")return false
if(strPhone.indexOf("(")==-1 && strPhone.indexOf(")")!=-1)return false
s=stripCharsInBag(strPhone,validWorldPhoneChars);
return (isInteger(s) && s.length >= minDigitsInIPhoneNumber && s.length <= maxDigitsInIPhoneNumber && s.substr(0,1) == 7);
}

function ValidateForm(){
	var Name= document.getElementById('msgName')
	var Phone= document.getElementById('msgValue')

	if ((Name.value==null)||(Name.value=="")){
		alert("Пожалуйста укажите свое имя")
		Name.focus()
		return false
	}

	
	if ((Phone.value==null)||(Phone.value=="")){
		alert("Пожалуйста укажите свой номер телефона в формате +7 *** *** ** **")
		Phone.focus()
		return false
	}
	if (checkInternationalPhone(Phone.value)==false){
		alert("Пожалуйста укажите верный номер телефона в формате +7 *** *** ** **")
		//Phone.value=""
		Phone.focus()
		return false
	}
	return true
 }
