// WideMargin. Simple fast bible software.
// Copyright (C) 2011  Daniel Hughes
//
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;

namespace WideMargin.Database
{
	public class BookList
	{
		private static BookList Instants;
		private Dictionary<string, Book> _books;
		private List<Book> _orderedBooks;
		
		private const string OldTestiment = "Old Testiment";
		private const string NewTestiment = "New Testiment";
		private const string All = "All";
		private const string Torah = "Torah";
		private const string Prophecy = "Prophecy";
		private const string Poetry = "Poetry";
		private const string Gospels = "Gospels";
		private const string Letters = "Letters";
		
		private BookList ()
		{
			_books = new Dictionary<string, Book>();
			_orderedBooks = new List<Book>();
			
			var books = new Book[]
			{
				new Book("Genesis", 
				         new int[]{31,25,24,26,32,22,24,22,29,32,32,20,18,24,21,16,27,33,38,18,34,24,20,67,34,35,46,22,35,43,55,32,20,31,29,43,36,30,23,23,57,38,34,34,28,34,31,22,33,26},
						 new string[]{ All, OldTestiment, Torah}),
				new Book("Exodus", 
				         new int[]{22,25,22,31,23,30,25,32,35,29,10,51,22,31,27,36,16,27,25,26,36,31,33,18,40,37,21,43,46,38,18,35,23,35,35,38,29,31,43,38},
						 new string[]{ All, OldTestiment, Torah }),
				new Book("Leviticus", 
				         new int[]{17,16,17,35,19,30,38,36,24,20,47,8,59,57,33,34,16,30,37,27,24,33,44,23,55,46,34},
						 new string[]{ All, OldTestiment, Torah }),
				new Book("Numbers", 
				         new int[]{54,34,51,49,31,27,89,26,23,36,35,16,33,45,41,50,13,32,22,29,35,41,30,25,18,65,23,31,40,16,54,42,56,29,34,13},
						 new string[]{ All, OldTestiment, Torah }),
				new Book("Deuteronomy", 
				         new int[]{46,37,29,49,33,25,26,20,29,22,32,32,18,29,23,22,20,22,21,20,23,30,25,22,19,19,26,68,29,20,30,52,29,12},
						 new string[]{ All, OldTestiment, Torah }),
				new Book("Joshua", 
				         new int[]{18,24,17,24,15,27,26,35,27,43,23,24,33,15,63,10,18,28,51,9,45,34,16,33},
						 new string[]{ All, OldTestiment }),
				new Book("Judges", 
				         new int[]{36,23,31,24,31,40,25,35,57,18,40,15,25,20,20,31,13,31,30,48,25},
						 new string[]{ All, OldTestiment }),
				new Book("Ruth", 
				         new int[]{22,23,18,22},
						 new string[]{ All, OldTestiment }),
				new Book("1 Samuel", 
				         new int[]{28,36,21,22,12,21,17,22,27,27,15,25,23,52,35,23,58,30,24,42,15,23,29,22,44,25,12,25,11,31,13},
						 new string[]{ All, OldTestiment }),
				new Book("2 Samuel", 
				         new int[]{27,32,39,12,25,23,29,18,13,19,27,31,39,33,37,23,29,33,43,26,22,51,39,25},
						 new string[]{ All, OldTestiment }),
				new Book("1 Kings", 
				         new int[]{53,46,28,34,18,38,51,66,28,29,43,33,34,31,34,34,24,46,21,43,29,53},
						 new string[]{ All, OldTestiment }),
				new Book("2 Kings", 
				         new int[]{18,25,27,44,27,33,20,29,37,36,21,21,25,29,38,20,41,37,37,21,26,20,37,20,30},
						 new string[]{ All, OldTestiment }),
				new Book("1 Chronicles", 
				         new int[]{54,55,24,43,26,81,40,40,44,14,47,40,14,17,29,43,27,17,19,8,30,19,32,31,31,32,34,21,30},
						 new string[]{ All, OldTestiment }),
				new Book("2 Chronicles", 
				         new int[]{17,18,17,22,14,42,22,18,31,19,23,16,22,15,19,14,19,34,11,37,20,12,21,27,28,23,9,27,36,27,21,33,25,33,27,23},
						 new string[]{ All, OldTestiment }),
				new Book("Ezra", 
				         new int[]{11,70,13,24,17,22,28,36,15,44},
						 new string[]{ All, OldTestiment }),
				new Book("Nehemiah", 
				         new int[]{11,20,32,23,19,19,73,18,38,39,36,47,31},
						 new string[]{ All, OldTestiment }),
				new Book("Esther", 
				         new int[]{22,23,15,17,14,14,10,17,32,3},
						 new string[]{ All, OldTestiment }),
				new Book("Job", 
				         new int[]{22,13,26,21,27,30,21,22,35,22,20,25,28,22,35,22,16,21,29,29,34,30,17,25,6,14,23,28,25,31,40,22,33,37,16,33,24,41,30,24,34,17},
						 new string[]{ All, OldTestiment }),
				new Book("Psalms", 
				         new int[]{6,12,8,8,12,10,17,9,20,18,7,8,6,7,5,11,15,50,14,9,13,31,6,10,22,12,14,9,11,12,24,11,22,22,28,12,40,22,13,17,13,11,5,26,17,11,9,14,20,23,19,9,6,7,23,13,11,11,17,12,8,12,11,10,13,20,7,35,36,5,24,20,28,23,10,12,20,72,13,19,16,8,18,12,13,17,7,18,52,17,16,15,5,23,11,13,12,9,9,5,8,28,22,35,45,48,43,13,31,7,10,10,9,8,18,19,2,29,176,7,8,9,4,8,5,6,5,6,8,8,3,18,3,3,21,26,9,8,24,13,10,7,12,15,21,10,20,14,9,6},
						 new string[]{ All, OldTestiment, Poetry }),
				new Book("Proverbs", 
				         new int[]{33,22,35,27,23,35,27,36,18,32,31,28,25,35,33,33,28,24,29,30,31,29,35,34,28,28,27,28,27,33,31},
						 new string[]{ All, OldTestiment }),
				new Book("Ecclesiastes", 
				         new int[]{18,26,22,16,20,12,29,17,18,20,10,14},
						 new string[]{ All, OldTestiment }),
				new Book("Song of Solomon", 
				         new int[]{17,17,11,16,16,13,13,14},
						 new string[]{ All, OldTestiment, Poetry }),
				new Book("Isaiah", 
				         new int[]{31,22,26,6,30,13,25,22,21,34,16,6,22,32,9,14,14,7,25,6,17,25,18,23,12,21,13,29,24,33,9,20,24,17,10,22,38,22,8,31,29,25,28,28,25,13,15,22,26,11,23,15,12,17,13,12,21,14,21,22,11,12,19,12,25,24},	
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Jeremiah", 
				         new int[]{19,37,25,31,31,30,34,22,26,25,23,17,27,22,21,21,27,23,15,18,14,30,40,10,38,24,22,17,32,24,40,44,26,22,19,32,21,28,18,16,18,22,13,30,5,28,7,47,39,46,64,34},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Lamentations", 
				         new int[]{22,22,66,22,22},
						 new string[]{ All, OldTestiment, Prophecy, Poetry}),
				new Book("Ezekiel", 
				         new int[]{28,10,27,17,17,14,27,18,11,22,25,28,23,23,8,63,24,32,14,49,32,31,49,27,17,21,36,26,21,26,18,32,33,31,15,38,28,23,29,49,26,20,27,31,25,24,23,35},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Daniel", 
				         new int[]{21,49,30,37,31,28,28,27,27,21,45,13},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Hosea", 
				         new int[]{11,23,5,19,15,11,16,14,17,15,12,14,16,9},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Joel", 
				         new int[]{20,32,21},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Amos", 
				         new int[]{15,16,15,13,27,14,17,14,15},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Obadiah", 
				         new int[]{21},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Jonah", 
				         new int[]{17,10,10,11},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Micah", 
				         new int[]{16,13,12,13,15,16,20},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Nahum", 
				         new int[]{15,13,19},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Habakkuk", 
				         new int[]{17,20,19},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Zephaniah", 
				         new int[]{18,15,20},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Haggai", 
				         new int[]{15,23},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Zechariah", 
				         new int[]{21,13,10,14,11,15,14,23,17,12,17,14,9,21},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Malachi", 
				         new int[]{14,17,18,6},
						 new string[]{ All, OldTestiment, Prophecy }),
				new Book("Matthew", 
				         new int[]{25,23,17,25,48,34,29,34,38,42,30,50,58,36,39,28,27,35,30,34,46,46,39,51,46,75,66,20},
						 new string[]{ All, NewTestiment, Gospels}),
				new Book("Mark", 
				         new int[]{45,28,35,41,43,56,37,38,50,52,33,44,37,72,47,20},
						 new string[]{ All, NewTestiment, Gospels}),
			    new Book("Luke", 
				         new int[]{80,52,38,44,39,49,50,56,62,42,54,59,35,35,32,31,37,43,48,47,38,71,56,53},
						 new string[]{ All, NewTestiment, Gospels}),
				new Book("John", 
				         new int[]{51,25,36,54,47,71,53,59,41,42,57,50,38,31,27,33,26,40,42,31,25},
						 new string[]{ All, NewTestiment, Gospels}),
				new Book("Acts",
				         new int[]{26,47,26,37,42,15,60,40,43,48,30,25,52,28,41,40,34,28,41,38,40,30,35,27,27,32,44,31},
						 new string[]{ All, NewTestiment}),
				new Book("Romans", 
				         new int[]{32,29,31,25,21,23,25,39,33,21,36,21,14,23,33,27},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("1 Corinthians", 
				         new int[]{31,16,23,21,13,20,40,13,27,33,34,31,13,40,58,24},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("2 Corinthians", 
				         new int[]{24,17,18,18,21,18,16,24,15,18,33,21,14},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Galatians", 
				         new int[]{24,21,29,31,26,18},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Ephesians", 
				         new int[]{23,22,21,32,33,24},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Philippians", 
				         new int[]{30,30,21,23},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Colossians", 
				         new int[]{29,23,25,18},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("1 Thessalonians", 
				         new int[]{10,20,13,18,28},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("2 Thessalonians", 
				         new int[]{12,17,18},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("1 Timothy", 
				         new int[]{20,15,16,16,25,21},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("2 Timothy", 
				         new int[]{18,26,17,22},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Titus", 
				         new int[]{16,15,15},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Philemon", 
				         new int[]{25},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Hebrews", 
				         new int[]{14,18,19,16,14,20,28,13,28,39,40,29,25},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("James", 
				         new int[]{27,26,18,17,20},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("1 Peter", 
				         new int[]{25,25,22,19,14},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("2 Peter", 
				         new int[]{21,22,18},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("1 John", 
				         new int[]{10,29,24,21,21},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("2 John", 
				         new int[]{13},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("3 John", 
				         new int[]{14},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Jude", 
				         new int[]{25},
						 new string[]{ All, NewTestiment, Letters}),
				new Book("Revelation", 
				         new int[]{20,29,22,11,14,17,17,13,21,11,19,17,18,20,8,21,18,24,21,15,27,21},
						 new string[]{ All, NewTestiment, Prophecy}),
				
			};
			
			int index = 0;
			foreach(var book in books)
			{
				book.Index = index;
				AddBook(book);
				index++;
			}
		}
		
		private void AddBook(Book book)
		{
			_books.Add(book.Name, book);
			_orderedBooks.Add(book);
		}
		
		public Book GetBook(string bookname)
		{
			return _books[bookname];	
		}
		
		public IEnumerable<string> AllBookNames()
		{
			return 	
				from book in _orderedBooks
				select book.Name;
		}
		
		public IEnumerable<string> GetCatagory(string catagoryName)
		{
			return
				from book in _orderedBooks
				where book.Catagories.Contains(catagoryName)
				select book.Name;
		}
		
		public bool IsBook(string bookName)
		{
			return _books.ContainsKey(bookName);
		}
		
		public Book NextBook(Book book)
		{
			if(book.Name == "Revelation")
			{
				return null; //thats all folks.	
			}
			int currentIndex = _orderedBooks.IndexOf(book);
			return _orderedBooks[currentIndex + 1];
		}
		
		public Book PreviousBook(Book book)
		{
			if(book.Name == "Genesis")
			{
				return null; //thats all folks.	
			}
			int currentIndex = _orderedBooks.IndexOf(book);
			return _orderedBooks[currentIndex - 1];
		}
		
		public static BookList Get()
		{
			if(Instants == null)
			{
				Instants = new BookList();	
			}
			return Instants;
		}
	}
}

