/*
	Copyright (C) 2012 2015 Johan Mattsson

	This library is free software; you can redistribute it and/or modify 
	it under the terms of the GNU Lesser General Public License as 
	published by the Free Software Foundation; either version 3 of the 
	License, or (at your option) any later version.

	This library 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 
	Lesser General Public License for more details.
*/

using Gee;
using Sqlite;

namespace BirdFont {

public class CharDatabase {
	public static GlyphRange full_unicode_range;

	static unowned Database db;
	static Database? database = null;

	public CharDatabase () {
		File f;
			
		full_unicode_range = new GlyphRange ();
		f = get_database_file ();
		open_database () ;
	}
	
	public static void open_database () {
		File f = get_database_file ();
		int rc = Database.open_v2 ((!) f.get_path (), out database, OPEN_READONLY);

		db = (!) database;

		if (rc != Sqlite.OK) {
			stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ());
		}
	}
	
	public static File get_database_file () {
		return SearchPaths.find_file (null, "ucd.sqlite");
	}

	public static GlyphRange search (string s) {
		GlyphRange result = new GlyphRange ();
		GlyphRange ucd_result = new GlyphRange ();
		int rc, cols;
		Statement statement;
		string select;
		unichar c;
		
		if (s.has_prefix ("U+") || s.has_prefix ("u+")) {
			c = Font.to_unichar (s.down ());
			
			if (c != '\0') {
				result.add_single (c);
			}
		}

		if (s.char_count () == 1) {
			result.add_single (s.get_char (0));
		}

		select = "SELECT unicode FROM Words "
			 + "WHERE word GLOB '" + s.replace ("'", "''") + "';";
					
		rc = db.prepare_v2 (select, select.length, out statement, null);
		
		if (rc == Sqlite.OK) {
			cols = statement.column_count();
			
			if (cols != 1) {
				warning ("Expecting one column.");
				return result;
			}

			while (true) {
				rc = statement.step ();
				
				if (rc == Sqlite.DONE) {
					break;
				} else if (rc == Sqlite.ROW) {
					c = (unichar) statement.column_int64 (0);
					ucd_result.add_single (c);
				} else {
					warning ("Error: %d, %s\n", rc, db.errmsg ());
					break;
				}
			}
			
			try {
				if (ucd_result.get_length () > 0) {
					ucd_result.sort ();
					result.parse_ranges (ucd_result.get_all_ranges ());
				}
			} catch (MarkupError e) {
				warning (e.message);
			}
			
		} else {
			warning ("SQL error: %d, %s\n", rc, db.errmsg ());
		}
		
		return result;
	}
	
	public static bool has_ascender (unichar c) {
		if (!c.islower()) return true;
		
		switch (c) {
			case 'b': return true;
			case 'd': return true;
			case 'f': return true;
			case 'h': return true;
			case 'k': return true;
			case 'l': return true;	
		}

		return false;
	}

	public static bool has_descender (unichar c) {
		switch (c) {
			case 'g': return true;
			case 'j': return true;
			case 'p': return true;
			case 'q': return true;
			case 'y': return true;
		}
		
		return false;		
	}
	
	public static string get_unicode_database_entry (unichar c) {
		string description = "";
		int rc, cols;
		Statement statement;
		string select = "SELECT description FROM Description "
			+ @"WHERE unicode = $((int64) c)";
		
		rc = db.prepare_v2 (select, select.length, out statement, null);
		
		if (rc == Sqlite.OK) {
			cols = statement.column_count();
			
			if (cols != 1) {
				warning ("Expecting one column.");
				return description;
			}

			while (true) {
				rc = statement.step ();
				
				if (rc == Sqlite.DONE) {
					break;
				} else if (rc == Sqlite.ROW) {
					description = statement.column_text (0);
				} else {
					printerr ("Error: %d, %s\n", rc, db.errmsg ());
					break;
				}
			}
					
		} else {
			printerr ("SQL error: %d, %s\n", rc, db.errmsg ());
		}
		
		if (description == "") {
			description = Font.to_hex (c).replace ("U+", "") + "\tUNICODE CHARACTER";
		}
		
		return description;
	}
	
	public static void get_full_unicode (GlyphRange glyph_range) {
		try {
			if (!is_null (full_unicode_range)) {
				glyph_range.parse_ranges (full_unicode_range.get_all_ranges ());
			}
		} catch (MarkupError e) {
			warning (e.message);
		}
	}
}

}
