//------------------------- Copyright Block --------------------------
/* 

Tanzil Quran Navigator (ver 0.9.1)
Copyright (C) 2008 Hamid Zarrabi-Zadeh
http://tanzil.info

This program is free software: you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation, either version 3 of the License, or

(at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

GNU General Public License for more details.

The above copyright block and permission notice shall be included 

in all copies or substantial portions of this program.

*/

//--------------------------------------------------------------------

Quran = {

	// globals
	numSuras: 114, numPages: 604, numJuzs: 30,

	// private
	suraStarts: [], pageStarts: [], juzStarts: [], hizbStarts: [],

	// initialize 
	init: function() {

		for (var i=1; i<QuranData.Sura.length; i++)
			this.suraStarts[i] = this.getSuraStart(i);
		for (var i=1; i<QuranData.Juz.length; i++)
			this.juzStarts[i] = this.getJuzStart(i);
		for (var i=1; i<QuranData.Hizb.length; i++)
			this.hizbStarts[i] = this.getHizbStart(i);
	},

	// get start line of an aya

	getAyaStart: function(sura, aya) { 
		aya = aya || 1;
		return this.suraProps(sura).start+ (aya- 1);
	},

	// get start line of a sura

	getSuraStart: function(sura) {
		return this.getAyaStart(sura); 
	},

	// get start line of a page

	getPageStart: function(page) {
		return this.getAyaStart(this.pageProps(page).sura, this.pageProps(page).aya);
	},

	// get start line of a juz
	getJuzStart: function(juz) {
		return this.getAyaStart(this.juzProps(juz).sura, this.juzProps(juz).aya);
	},

	// get start line of a hizb
	getHizbStart: function(hizb) {
		return this.getAyaStart(this.hizbProps(hizb).sura, this.hizbProps(hizb).aya);
	},

	// return properties of a sura
	suraProps: function(sura) {

		var s = QuranData.Sura[sura] || [0, 7]; 

		var data = {};

		var items = ['start', 'ayas', 'order', 'rukus', 'name', 'tname', 'ename', 'type'];

		for (var i=0; i<items.length; i++)

			data[items[i]] = s[i];

		return data;
	},

	// return properties of a page

	pageProps: function(page) {

		var page = QuranData.Page[page] || [1,1]; 

		return {sura: page[0], aya: page[1]};

	},

	// return properties of a juz

	juzProps: function(juz) {

		var juz = QuranData.Juz[juz] || [1,1]; 

		return {sura: juz[0], aya: juz[1]};

	},

	// return properties of a hizb

	hizbProps: function(hizb) {

		var hizb = QuranData.Hizb[hizb] || [1,1]; 

		return {sura: hizb[0], aya: hizb[1]};

	},

	// get previous aya

	getPrevAya: function(sura, aya) {

		if (--aya == 0) 

			aya = this.suraProps(--sura).ayas;

		return {sura: sura, aya: aya};

	},

	// get next aya

	getNextAya: function(sura, aya) {

		if (++aya > this.suraProps(sura).ayas) {
			aya = 1; sura++;
		}
		return {sura: sura, aya: aya};
	},

	// adjust aya number

	fixAyaNum: function(sura, aya) {
		return Math.min(Math.max(aya, 1), this.suraProps(sura).ayas); 
	},

	// adjust sura number

	fixSuraNum: function(sura) {
		return Math.min(Math.max(sura, 1), this.numSuras); 
	},

	// adjust page number

	fixPageNum: function(page) {
		return Math.min(Math.max(page, 1), this.numPages); 
	},

	// adjust juz number

	fixJuzNum: function(juz) {
		return Math.min(Math.max(juz, 1), this.numJuzs); 
	},

	// return the name of a sura

	getSuraName: function(sura, nameType) {

		nameType = nameType || 'tname'; 

		//if(nameType != 'name')
		return this.suraProps(sura)[nameType]; 
	},

	// return the number of a sura

	getSuraNum: function(suraName, nameType) {

		// nameType in {'name', 'ename', 'tname'}

		nameType = nameType || 'tname'  

		for (i=1; i<=this.numSuras; i++)
			if (this.suraProps(i)[nameType] == suraName)
				return i;
		return 0;
	},

	// find sura and aya corresponding to a line number

	getLineCoords: function(line) {

		var sura = this.binarySearch(this.suraStarts, line);

		var aya = line- this.suraProps(sura).start+ 1;

		return {sura: sura, aya: aya};

	},

	// find the page containing an aya

	getAyaPage: function(sura, aya) {
		return this.binarySearch(this.pageStarts, this.getAyaStart(sura, aya));
	},

	// find the juz containing an aya

	getAyaJuz: function(sura, aya) {
		return this.binarySearch(this.juzStarts, this.getAyaStart(sura, aya));
	},

	// return properties of a hizb

	gethizbProps: function(hizb) {

		var hizb = QuranData.Hizb[hizb] || [1,1]; 

		return {sura: hizb[0], aya: hizb[1]};

	},

	// find the hizb containing an aya

	getHizb: function(sura, aya) {

		var up = this.hizbStarts.length-1; 

		var hizb;

		while(up > 0) {

			hizb = QuranData.Hizb[up];

			if (hizb[0] == sura && hizb[1] == aya)
			{
				return true;
				break
			}	
			up--;	
		}

		return false;
	},

	// find the last entry in theArray which is <= item

	binarySearch: function(theArray, item) {

		var down = 0, mid;

		var up = theArray.length; 

		while(up- down > 1) {

			mid = (down+ up)>> 1;

			if (theArray[mid] < item) down = mid;

			else up = mid;

		}

		if(theArray[up] != item)
			return up- 1;  

		return up;

	},

	// returns the page contents as an array of {sura, aya}

	getPageItems: function(page) {

		var pageArray = [];

		var from = this.pageProps(page);

		var to = this.pageProps(page+ 1);

		to = this.getPrevAya(to.sura, to.aya);

		if (from.sura == to.sura)
			pageArray = pageArray.concat(this.getAyaRange(from.sura, from.aya, to.aya));
		else {
			pageArray = pageArray.concat(this.getAyaRange(from.sura, from.aya, this.suraProps(from.sura).ayas));

			for (var i = from.sura+ 1 ; i < to.sura ; i++)

				pageArray = pageArray.concat(this.getAyaRange(i, 1, this.suraProps(i).ayas));

			pageArray = pageArray.concat(this.getAyaRange(to.sura, 1, to.aya));
		}
		return pageArray;
	},

	// subroutine used by getPageItems

	getAyaRange: function(sura, fromAya, toAya) {

		var outArray = [];

		for (i=fromAya; i<=toAya; i++)

			outArray.push({sura: sura, aya: i});

		return outArray;
	}
}

Quran.init();