--[[
 ################################## 
 #Source code for AnyLanguageStudy#
 #Copyright Nakano 2011.          #
 #                                #
 ######## VERSION HISTORY #########
 # V0.1 02/27/2011 (by nakano)    #
 # * Initial release              #
 # V0.2 03/02/2011 (by nakano)    #
 # * Increased stability          #
 # * Bug fixes                    # 
 # * Optimizations for showing    #
 #   long phrases.                #
 # V0.3 03/05/2011 (by nakano)    #
 # * Question font size can be    #
 #   increased                    #
 # * Added options menu           #
 # * If user answers wrong, right #
 #   answer is given (option)     #
 # * User may set delay before    #
 #   answers are shown (option)   #
 # V0.4 03/08/2011 (by nakano)    #
 # * Support for picture word list#
 # * Added range (option)         #
 # * Example sentences (option)   #
 # * Keys menu                    #
 # * Minor bug fixes and          #
 #   other optimizations          #
 ##################################
]]

math.randomseed( os.time() ); -- random seed

-- COLORS
gray = Color.new(180, 180, 180);
white = Color.new(255, 255, 255);
darkgray = Color.new(100, 100, 100, 128);
lime = Color.new(50,205,50);
red = Color.new(255,0,0);
lightblue = Color.new(64,255,255);
midnightblue = Color.new(25,25,112);

-- ALL IMAGES
genesis = Image.load("images/genesis.png");
background = Image.load("images/background.png")
square = Image.load("images/square.png")
triangle = Image.load("images/triangle.png")
circle = Image.load("images/circle.png")
cross = Image.load("images/cross.png")
keys = Image.load("images/keys.png")
right = Image.load("images/right.png")
options = Image.load("images/options.png")
longbutton = Image.load("images/longbutton.png")
shortbutton = Image.load("images/shortbutton.png")
sentencebox = Image.load("images/sentence.png")

-- FONTS
ifont = IntraFont.load("flash0:/font/jpn0.pgf", IntraFont.STRING_UTF8);
ifontLtn = IntraFont.load("flash0:/font/ltn0.pgf", IntraFont.STRING_UTF8);

-- GLOBAL VARIABLES OF SELECTING FILE
selection = 1;
page = 0;

sentence = {}; -- example sentences are stored here of selected language
currentSentencePath = "none"; -- path without file where example sentences are previously found

askLevel = 0;

--[[ 
Show right answer after wrong true/false
Show sentence after answer true/false
Wait before choices 0 (never), 3 (seconds), 5 (seconds), 10 (seconds), 100 (press)
Ask once 0 (ALL), 10, 20, 50, 100 (max)
]]
userOptions = {"true", "true", "0", "0"}

-- FUNCTIONS

showLogo = function()
	System.draw();
	screen:blit(0, 0, genesis);
	System.endDraw();
	screen.flip()
	screen.waitVblankStart(150);
end

string.split = function(str, pattern)
	pattern = pattern or "[^%s]+"
	if pattern:len() == 0 then pattern = "[^%s]+" end
	local parts = {__index = table.insert}
	setmetatable(parts, parts)
	str:gsub(pattern, parts)
	setmetatable(parts, nil)
	parts.__index = nil
	table.insert(parts, "false"); -- not quessed yet
	return parts
end

string.splitOptions = function(str, pattern)
	pattern = pattern or "[^%s]+"
	if pattern:len() == 0 then pattern = "[^%s]+" end
	local parts = {__index = table.insert}
	setmetatable(parts, parts)
	str:gsub(pattern, parts)
	setmetatable(parts, nil)
	parts.__index = nil
	return parts
end

string.splitSentences = function(str, pattern)
	pattern = pattern or "[^%s]+"
	if pattern:len() == 0 then pattern = "[^%s]+" end
	local parts = {__index = table.insert}
	setmetatable(parts, parts)
	str:gsub(pattern, parts)
	setmetatable(parts, nil)
	parts.__index = nil
	return parts
end

function trim (str)
	return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
end

function table.copy(t)
  local t2 = {}
  for k,v in pairs(t) do
    t2[k] = v
  end
  return t2
end

showSentence = function(PrimarySearch, SecondarySearch)
	local i = 0;
	local showedSentence = "";
	local sentenceIndexList = {}
	ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
	while (i < #sentence) do
		i = i + 1
		searchIndexPrimary = string.find(string.lower(sentence[i][1]), string.lower(PrimarySearch));
		if (searchIndexPrimary ~= nil) then
			table.insert(sentenceIndexList, i)
		end
	end
	
	i = 0;
	
	if (#sentenceIndexList == 0) then
		while (i < #sentence) do
			i = i + 1
			searchIndexSecondary = string.find(string.lower(sentence[i][2]), string.lower(SecondarySearch));
			if (searchIndexSecondary ~= nil) then
				table.insert(sentenceIndexList, i);
			end
		end
	end
	
	-- Choose sentence
	if (#sentenceIndexList ~= 0) then
		local sentenceIndex = math.random(1,#sentenceIndexList); -- 1..n
		sentenceIndex = sentenceIndexList[sentenceIndex]; 	-- get i value
	
		sentence1 = trim(sentence[sentenceIndex][1]);
			if (string.len(sentence1) > 40) then
				ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
			end
		
			if (string.len(sentence1) > 60) then
				local beginning = string.sub(sentence1, 1, 60);
				local ending = string.sub(sentence1, 61);
				sentence1 = beginning .. "\n" .. ending;
			end
			
			sentence2 = trim(sentence[sentenceIndex][2]);
			if (string.len(sentence2) > 40) then
				ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
			end
		
			if (string.len(sentence2) > 60) then
				local beginning = string.sub(sentence2, 1, 60);
				local ending = string.sub(sentence2, 61);
				sentence2 = beginning .. "\n" .. ending;
			end
			
			showedSentence = sentence1 .. "\n\n" .. sentence2;
	end
	
	-- Show sentence if exist
	if (showedSentence ~= "") then
		while true do
			System.draw()
			screen:blit(0, 118, sentencebox);
			screen:blit(196,240, longbutton);
			
			ifont:print(240, 146, showedSentence);
			
			local pad = Controls.readPeek()
		
			if (pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
				screen.waitVblankStart(20);
				break;
			
			elseif pad:home() then
				break; -- if no wait force exit
			end
		System.endDraw()
		end
	end
end

storeSentences = function(path) -- path include file name also
	local reversePath = string.reverse(path);
	local reverseIndex = string.find(reversePath, "/")
	local fileName = "sentence.csv"
	
	if (reverseIndex == nil) then -- path is root of AnyLanguageStudy
		-- fileName is sentence.csv then
		if (currentSentencePath == "") then -- no need reload sentence.csv it's already loaded
			return;
		end
		currentSentencePath = ""; -- root
	else
		local trueIndex = string.len(path) - reverseIndex + 1;
		
		if (currentSentencePath == string.sub(path, 0, trueIndex)) then
			return; -- no need for reloading
		end
		
		currentSentencePath = string.sub(path, 0, trueIndex);
		fileName = string.sub(path, 0, trueIndex) .. "sentence.csv";
	end
	
	file7 = io.open(fileName);
	
	if (file7 == nil ) then
		-- no sentences for current set
		currentSentencePath = "none";
		return
	end
	
	-- Parse sentences
	i = 1;
for line in file7:lines() do

	if (line ~= nil and string.len(trim(line)) > 0 and string.sub(line, 1, 1) ~= "#" and string.find(line, ";") ~= nil) then -- ignore empty sentences and commented lines or sentences without ;
	
	local index = 1;
	local str = line;
	local tempLine = "";
	
	while index ~= nil do
		index = string.find(str, ";", index)
	
		if (index == 1) then
			tempLine = tempLine .. " ";
		end
	
		tempLine = tempLine .. str:sub(1, index);
		
		if (index ~= nil) then
			str = str:sub(index + 1);
			index = 1;
		end
	end
  
	line = tempLine;
  
	sentence[i] = line:splitSentences("[^;]+");
	i = i + 1;
	end
end

	file7:close()
	
end

showKeys = function()

	System.draw()
		screen:blit(0, 0, keys);
		screen:blit(195, 250, longbutton);
		ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(240, 22, "Keys");
		
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(30, 35, "UP - Move up / Switch mode");
		ifontLtn:print(30, 55, "DOWN - Move down / Switch mode");
		ifontLtn:print(30, 75, "RIGHT - Next page / Switch show");
		ifontLtn:print(30, 95, "LEFT - Previous page / Switch show");
		ifontLtn:print(30, 115, "ANALOG UP/DOWN - Increase / decrease font size of question");
		ifontLtn:print(30, 135, "ANALOG LEFT/RIGHT - Increase / decrease range");
		ifontLtn:print(30, 155, "R - Next page / Clear list of learned words");
		ifontLtn:print(30, 175, "L - Previous page / Show keys");
		ifontLtn:print(30, 195, "SELECT - Open word list");
		ifontLtn:print(30, 215, "HOME - Quick quit");
		ifontLtn:print(270, 195, "START - Open global options");
		ifontLtn:print(270, 35, "SQUARE - Select / Answer");
		ifontLtn:print(270, 55, "TRIANGLE - Select / Answer");
		ifontLtn:print(270, 75, "CIRCLE - Select / Answer");
		ifontLtn:print(270, 95, "CROSS - Select / Answer");
		
	System.endDraw()
	screen.flip()

	while true do
	
		local pad = Controls.readPeek()
		
		if (pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
			screen.waitVblankStart(20);
			break;
			
		elseif pad:home() then
			break; -- if no wait force exit
		end
	end
end

checkKnownWords = function()
if (userOptions[4] == "0") then
	allKnown = 1 -- 1 all is learned; 0 all is not learned
	setKnown = 0
	i = 0;
	while (i < #word) do
		i = i + 1;
		if (word[i][#word[1]] == "false") then
			allKnown = 0;
			break;
		end
	end
else
	allKnown = 0;
	setKnown = 1;
	i = askMin;
	
	while (i < askMax) do
		i = i + 1;
		if (word[i][#word[1]] == "false") then
			setKnown = 0;
			break;
		end
	end
end

end

saveOptions = function()

	optionFile = "options.ini";
	file6 = io.open(optionFile,"w")
				
	i = 0;
	while (i < #userOptions) do
		i = i + 1;
		file6:write(userOptions[i] .. ";");
	end
				
	file6:close();

end

loadOptions = function()
	local file6 = io.open("options.ini", "r");

	if not file6 then
		return; -- no options file stored
	end
	
	local line = file6:read();
	
	userOptions = line:splitOptions("[^;]+");
	
	if (#userOptions ~= 4) then
		-- corrupted data
		userOptions = {"true", "true", "0", "0"}
	end
	
	file6:close();
	
end

waitShowAnswer = function(waitLimit)

local waitEternity = false
local imageLoaded = false;
questionImage = nil;

if (waitLimit == 100) then
	waitEternity = true
end

local starttime = os.clock()
--screen:clear()
while os.clock() - starttime < waitLimit or waitEternity do
System.draw()

screen:blit(0, 0, background);
screen:blit(30, 118, square);
screen:blit(30, 146, triangle);
screen:blit(30, 174, circle);
screen:blit(30, 202, cross);

	if (mode == 1) then
		-- if too long text, should smallen the font
		question1 = trim(word[question][#word[question] - 1]);
		if (string.len(question1) > 40) then
			ifont:setStyle(0.6 + extraQ, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		if (string.len(question1) > 80) then
			local beginning = string.sub(question1, 1, 80);
			local ending = string.sub(question1, 81);
			question1 = beginning .. "\n" .. ending;
		end
		
		if (string.find(question1, ".png")) then -- image query
			if (imageLoaded == false) then
			
				local file8 = io.open(question1);
				if (file8 == nil ) then
					questionImage = false;
				else
					questionImage = Image.load(question1);
					imageLoaded = true;
					file8:close()
				end
			end
			if (questionImage == false) then
				ifont:print(240, 56, "Not found: " .. question1);
			else
				screen:blit(0,0,questionImage) -- image was found, show it
				screen:blit(30, 118, square);
				screen:blit(30, 146, triangle);
				screen:blit(30, 174, circle);
				screen:blit(30, 202, cross);
			end
	
		else
			ifont:print(240, 56, question1); -- translation
		end
		
	elseif (mode == 2) then
		
		question1 = trim(word[question][show]);
		
		-- if wrong mode (comes from mode 2 to picture questionaire)
		if (string.find(question1, ".png")) then -- image query
			mode = 1;
			randomize();
		end
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter <= counts) do
		
			if (string.len(question1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[question] - 2;
				end
			
				question1 = trim(word[question][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		if (string.len(question1) > 40) then
			ifont:setStyle(0.6 + extraQ, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(question1) > 80) then
			local beginning = string.sub(question1, 1, 80);
			local ending = string.sub(question1, 81);
			question1 = beginning .. "\n" .. ending;
		end
		
		ifont:print(240, 56, question1);
		
	end
	ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
	ifont:print(100, 255, "Mode: " .. mode .. " / Show: " .. show ); -- show mode and show
	ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
	ifont:print(10, 267, "Range: " .. askMin .. "-" .. askMax .. " / " .. #word); -- show range
	ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
	if (allKnown == 1) then
			ifont:print(395, 260, "All once correct");
	elseif (setKnown == 1) then
			ifont:print(395, 260, "Set once correct");
	end
	
	local pad = Controls.readPeek()
		
		if (pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
			screen.waitVblankStart(20);
			break;
		elseif pad:right() then
			if (show == #word[1] - 2) then
				show = 1;
				screen.flip();
				screen.waitVblankStart(20);
			else
				show = show + 1;
				screen.flip();
				screen.waitVblankStart(20);
			end
				
		elseif pad:left() then
			if (show == 1) then
				show = #word[1] - 2;
				screen.flip();
				screen.waitVblankStart(20);
			else
				show = show - 1;
				screen.flip();
				screen.waitVblankStart(20);
			end
		
		elseif pad:up() and imageLoaded == false then
			if (mode == 1) then
				save();
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			else
				save();
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			end;
			
		elseif pad:down() and imageLoaded == false then
			if (mode == 1) then
				save();
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			else
				save();
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			end;
		
		elseif (pad:analogY() < -100 ) then
			extraQ = extraQ + 0.1;
			if (extraQ > 2) then
				extraQ = 2;
			end
		
		elseif (pad:analogY() > 100 ) then
			extraQ = extraQ - 0.1
			if (extraQ < 0) then
				extraQ = 0
			end
		
		elseif (pad:analogX() < - 100 and userOptions[4] ~= "0") then
			askLevel = askLevel - 1;
			if (askLevel < 0) then
				askLevel = math.ceil(#word / userOptions[4]) - 1;
			end
			
			calculateMinMax()
			screen.waitVblankStart(20);
			
		elseif (pad:analogX() > 100 and userOptions[4] ~= "0") then
			askLevel = askLevel + 1;
			if (askLevel > (math.ceil(#word / userOptions[4]) - 1)) then
				askLevel = 0;
			end
			calculateMinMax()
			screen.waitVblankStart(20);	
		
		elseif pad:select() then
			save()
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			initialize();
		
		elseif pad:home() then
				break; -- if no wait force exit
		
        elseif pad:start() then
			save()
			screen.waitVblankStart(20);
			openOptions();
			
		elseif pad:r() then
			result = System.msgDialog("Do you want to clear known list?", true, drawFunc)
			if (result==System.MSGDIALOG_RESULT_YES) then
				clearResults(word);
				allKnown = 0;
				save();
			end
		end
	
	ifont:setStyle(1.0 + extraQ, white, darkgray, IntraFont.ALIGN_CENTER);
    System.endDraw();
    screen.flip();
	
end
	
end

waitBeforeShowing = function()
	if (userOptions[3] == "0") then
		-- don't wait
	
	elseif (userOptions[3] == "3") then
		-- wait 3 secs
		waitShowAnswer(3)
	elseif (userOptions[3] == "5") then
		-- wait 5 secs
		waitShowAnswer(5)
	elseif (userOptions[3] == "10") then
		-- wait 10 secs
		waitShowAnswer(10)
	else
		-- wait press
		waitShowAnswer(100)
	end
	
end

loadSaveData = function(currentDictionary, word, mode)
saveDictionary = currentDictionary .. mode;
	-- check file exist
	file4 = io.open(saveDictionary)
	if (file4 ~= nil) then
		i = 1;
	
		for line in file4:lines() do
			if (i > #word) then
				break;
			end
			
			if (line == "false" or line == "true") then
				word[i][#word[1]] = line;
			else
				word[i][#word[1]] = false; -- if file is corrupted.
			end
			i = i + 1;	
		end
			
		file4:close();
	else
		clearResults(word);
	end
end

calculateMinMax = function()

-- Determine how many/which is asked at the same time
if (userOptions[4] == "0") then
	askLevel = 0;
	askMin = 1;
	askMax = #word;
elseif (userOptions[4] == "10") then
	askMin = 1 + askLevel * 10;
	askMax = 10 + askLevel * 10;
	if (askMax > #word) then
		askMax = #word
	end
elseif (userOptions[4] == "20") then
	askMin = 1 + askLevel * 20;
	askMax = 20 + askLevel * 20;
	if (askMax > #word) then
		askMax = #word
	end

elseif (userOptions[4] == "50") then
	askMin = 1 + askLevel * 50;
	askMax = 50 + askLevel * 50;
	if (askMax > #word) then
		askMax = #word
	end
else
	askMin = 1 + askLevel * 100;
	askMax = 100 + askLevel * 100;
	if (askMax > #word) then
		askMax = #word
	end
end

end

randomize = function()

calculateMinMax()

first = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[first][#word[1]] == "true") then
	while (word[first][#word[1]] == "true" and times < 50) do
		first = math.random(askMin,askMax);
		times = times + 1;
	end
end

second = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[second][#word[1]] == "true") then
	while (word[second][#word[1]] == "true" and times < 50) do
		second = math.random(askMin,askMax);
		times = times + 1;
	end
end

times = 0;

while (second == first) do 
	second = math.random(askMin,askMax);
	if (times > 100) then -- this is needed as this may me an infinite loop
		second = first;
		break;
	end
	times = times + 1;
end

third = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[third][#word[1]] == "true") then
	while (word[third][#word[1]] == "true" and times < 50) do
		third = math.random(askMin,askMax);
		times = times + 1;
	end
end

times = 0;

while (third == second or third == first) do 
	third = math.random(askMin,askMax);
	if (times > 100) then -- this is needed as this may me an infinite loop
		third = first;
		break;
	end
	times = times + 1;
end

fourth = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[fourth][#word[1]] == "true") then
	while (word[fourth][#word[1]] == "true" and times < 50) do
		fourth = math.random(askMin,askMax);
		times = times + 1;
	end
end

times = 0;

while (fourth == third or fourth == second or fourth == first) do
	fourth = math.random(askMin,askMax);
	if (times > 100) then -- this is needed as this may me an infinite loop
		fourth = first;
		break;
	end
	times = times + 1;
end

times = 0;

while true do
question = math.random(1,4);

	if (question == 1) then
		if (word[first][#word[1]] == "false" or times == 50) then
			question = first;
			break;
		end
	elseif (question == 2) then
		if (word[second][#word[1]] == "false" or times == 50) then
			question = second;
			break;
		end
	elseif (question == 3) then
		if (word[third][#word[1]] == "false" or times == 50) then
			question = third;
			break;
		end
	else
		if (word[fourth][#word[1]] == "false" or times == 50) then
			question = fourth;
			break;
		end
	end
	
	times = times + 1;
end

checkKnownWords()
	
end

clearResults = function(word)

	i = 1;
	while (i <= #word) do
	word[i][#word[i]] = "false";
	i = i + 1;
	end

end

openOptions = function()

	local currentX = 1;
	local currentY = 1;
	previousOptions = table.copy(userOptions)
	
	while true do
		local focus = {currentY,currentX} -- high level, selection
		local pad = Controls.readPeek()

		System.draw();
		screen:clear();
		screen:blit(0, 0, background);
		screen:blit(30, 20, options);
		
		ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(240, 42, "Global Options");
		
		-- SHOW SELECTOR
		if (focus[1] == 1) then
			if (focus[2] == 1) then
				screen:blit(240, 76, shortbutton)
			else
				screen:blit(270, 76, shortbutton)
			end
			
		elseif (focus[1] == 2) then
			if (focus[2] == 1) then
				screen:blit(240, 106, shortbutton)
			else
				screen:blit(270, 106, shortbutton)
			end
		
		elseif (focus[1] == 3) then
			if (focus[2] == 1) then
				screen:blit(240, 136, shortbutton)
			elseif(focus[2] == 2) then
				screen:blit(270, 136, shortbutton)
			elseif(focus[2] == 3) then
				screen:blit(300, 136, shortbutton)
			elseif(focus[2] == 4) then
				screen:blit(330, 136, shortbutton)
			else
				screen:blit(360, 136, shortbutton)
			end
		
		elseif (focus[1] == 4) then
			if (focus[2] == 1) then
				screen:blit(240, 166, shortbutton)
			elseif(focus[2] == 2) then
				screen:blit(270, 166, shortbutton)
			elseif(focus[2] == 3) then
				screen:blit(300, 166, shortbutton)
			elseif(focus[2] == 4) then
				screen:blit(330, 166, shortbutton)
			else
				screen:blit(360, 166, shortbutton)
			end
		
		elseif (focus[1] == 5) then
			if (focus[2] == 1) then
				screen:blit(71, 238, longbutton)
			elseif(focus[2] == 2) then
				screen:blit(186, 238, longbutton)
			else
				screen:blit(302, 238, longbutton)
			end
		end
		
		-- FIRST OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 66, "Show right answer after wrong");
		
		if (userOptions[1] == "true") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		end
	
		ifontLtn:print(240, 66, "YES");
		
		if (userOptions[1] == "true") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		end
		
		ifontLtn:print(270, 66, "NO");
		-- SECOND OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);	
		ifontLtn:print(40, 96, "Show sentence after answer");
		
		
		if (userOptions[2] == "true") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		end
	
		ifontLtn:print(240, 96, "YES");
		
		if (userOptions[2] == "true") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		end
		
		ifontLtn:print(270, 96, "NO");
		-- THIRD OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 126, "Wait before choices");
		
		if (userOptions[3] == "0") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 126, "3s");
			ifontLtn:print(300, 126, "5s");
			ifontLtn:print(330, 126, "10s");
			ifontLtn:print(360, 126, "Press");
		
		elseif (userOptions[3] == "3") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 126, "3s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 126, "5s");
			ifontLtn:print(330, 126, "10s");
			ifontLtn:print(360, 126, "Press");
		
		elseif (userOptions[3] == "5") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:print(270, 126, "3s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 126, "5s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 126, "10s");
			ifontLtn:print(360, 126, "Press");
			
		elseif (userOptions[3] == "10") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:print(270, 126, "3s");
			ifontLtn:print(300, 126, "5s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 126, "10s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 126, "Press");
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:print(270, 126, "3s");
			ifontLtn:print(300, 126, "5s");
			ifontLtn:print(330, 126, "10s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 126, "Press");
		end
		-- FOURTH OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 156, "Ask once");
		
		if (userOptions[4] == "0") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 156, "ALL");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 156, "10");
			ifontLtn:print(300, 156, "20");
			ifontLtn:print(330, 156, "50");
			ifontLtn:print(360, 156, "100");
		
		elseif (userOptions[4] == "10") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 156, "ALL");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 156, "10");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 156, "20");
			ifontLtn:print(330, 156, "50");
			ifontLtn:print(360, 156, "100");
		
		elseif (userOptions[4] == "20") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 156, "ALL");
			ifontLtn:print(270, 156, "10");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 156, "20");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 156, "50");
			ifontLtn:print(360, 156, "100");
			
		elseif (userOptions[4] == "50") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 156, "ALL");
			ifontLtn:print(270, 156, "10");
			ifontLtn:print(300, 156, "20");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 156, "50");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 156, "100");
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 156, "ALL");
			ifontLtn:print(270, 156, "10");
			ifontLtn:print(300, 156, "20");
			ifontLtn:print(330, 156, "50");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 156, "100");
		end
		
		ifontLtn:setStyle(0.8, lightblue, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 196, "Select option with CROSS and press Save");
		
		if (pad:start()) then
			screen.waitVblankStart(20);
			screen:clear()
			userOptions = previousOptions;
			break;
		
		elseif pad:home() then
			System.quit();
		
		elseif(pad:right()) then
			currentX = currentX + 1;
			
			if ((currentY == 1 or currentY == 2) and currentX > 2) then
				currentX = 1;
			elseif((currentY == 3 or currentY == 4) and currentX > 5) then
				currentX = 1;
			elseif(currentY == 5 and currentX > 3) then
				currentX = 1;
			end
			screen.waitVblankStart(20);
		
		elseif(pad:left()) then
			currentX = currentX - 1;
			
			if ((currentY == 1 or currentY == 2) and currentX < 1) then
				currentX = 2;
			elseif((currentY == 3 or currentY == 4) and currentX < 1) then
				currentX = 5;
			elseif(currentY == 5 and currentX < 1) then
				currentX = 3;
			end
			screen.waitVblankStart(20);
		
		elseif(pad:down()) then
			currentX = 1;
			currentY = currentY + 1;
			
			if (currentY > 5) then
				currentY = 1;
			end
			screen.waitVblankStart(20);
		
		elseif(pad:up()) then
			currentX = 1;
			currentY = currentY - 1;
			
			if (currentY < 1) then
				currentY = 5;
			end
			screen.waitVblankStart(20);
		-- Choose option
		elseif(pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
			if (currentX == 1 and currentY == 1) then
				userOptions[1] = "true";
			elseif (currentX == 2 and currentY == 1) then
				userOptions[1] = "false";
			elseif (currentX == 1 and currentY == 2) then
				userOptions[2] = "true";
			elseif (currentX == 2 and currentY == 2) then
				userOptions[2] = "false";
			elseif (currentX == 1 and currentY == 3) then
				userOptions[3] = "0";
			elseif (currentX == 2 and currentY == 3) then
				userOptions[3] = "3";
			elseif (currentX == 3 and currentY == 3) then
				userOptions[3] = "5";
			elseif (currentX == 4 and currentY == 3) then
				userOptions[3] = "10";
			elseif (currentX == 5 and currentY == 3) then
				userOptions[3] = "100";
			elseif (currentX == 1 and currentY == 4) then
				userOptions[4] = "0";
			elseif (currentX == 2 and currentY == 4) then
				userOptions[4] = "10";
			elseif (currentX == 3 and currentY == 4) then
				userOptions[4] = "20";
			elseif (currentX == 4 and currentY == 4) then
				userOptions[4] = "50";
			elseif (currentX == 5 and currentY == 4) then
				userOptions[4] = "100";
			elseif (currentX == 1 and currentY == 5) then
				-- save options
				previousOptions = userOptions;
				askLevel = 0;
				if (word ~= nil) then
					calculateMinMax()
					checkKnownWords()
				end
				saveOptions() -- no need for parameters userOption is global
				
				screen.waitVblankStart(20);
				screen:clear()
				break;
			elseif (currentX == 2 and currentY == 5) then
				-- cancel
				screen.waitVblankStart(20);
				screen:clear()
				userOptions = previousOptions;
				break;
			elseif (currentX == 3 and currentY == 5) then
				-- default
				userOptions = {"true", "true", "0", "0"}
				askLevel = 0;
				saveOptions()
				if (word ~= nil) then
					calculateMinMax()
					checkKnownWords()
				end
				screen.waitVblankStart(20);
				screen:clear()
				break;
			end
			screen.waitVblankStart(20);
		
		-- Open menu
		elseif pad:select() then
			userOptions = previousOptions;
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			initialize();
		
		end
		
		System.endDraw();
		screen.flip();
	end

end

menu = function(dictionary)
i = 1 + (page * 10);
local drawLevel = 1;
--
		ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
		System.draw();
		screen:clear();
		screen:blit(0, 0, background);
		
		ifontLtn:print(240, 22, "Select a word list");
		
		ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (#dictionary > 10) then
			ifontLtn:print(30, 20, "< L");
			ifontLtn:print(450, 20, "R >");
		end
		
		while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
			if (i == selection) then
				ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
			else
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			end
			
			ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
			i = i + 1;
			drawLevel = drawLevel + 1;
		end
		
		ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
		
		System.endDraw();
		screen.flip();
--
	while true do
		local pad = Controls.readPeek()

        if pad:home() then
			System.quit();
			
		elseif pad:start() then
			screen.waitVblankStart(20);
			openOptions();
			-- draw menus
			
			i = 1 + (page * 10);
			selection = i;
			
			System.draw();
			screen:clear();
			screen:blit(0, 0, background);
		
			ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(240, 22, "Select a word list");
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (#dictionary > 10) then
				ifontLtn:print(30, 20, "< L");
				ifontLtn:print(450, 20, "R >");
			end
		
			drawLevel = 1;
			while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
			end
		
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
		
			System.endDraw();
			screen.flip();
			screen.waitVblankStart(30);
			
		elseif (pad:r() or pad:right()) then
			page = page + 1;
			if ((page * 10) + 1 > #dictionary) then
				page = 0;
			end
			i = 1 + (page * 10);
			selection = i;
			
			System.draw();
			screen:clear();
			screen:blit(0, 0, background);
		
			ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(240, 22, "Select a word list");
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (#dictionary > 10) then
				ifontLtn:print(30, 20, "< L");
				ifontLtn:print(450, 20, "R >");
			end
		
			drawLevel = 1;
		
			while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
			end
		
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
		
			System.endDraw();
			screen.flip();
			screen.waitVblankStart(30);
		
		elseif (pad:l() or pad:left()) then
			page = page - 1;
			if (page < 0) then
				page = math.floor(#dictionary / 10);
				if (math.floor(#dictionary % 10) == 0) then
					page = page - 1
				end
			end
			i = 1 + (page * 10);
			selection = i;
			
			System.draw();
			screen:clear();
			screen:blit(0, 0, background);
		
			ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(240, 22, "Select a word list");
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (#dictionary > 10) then
				ifontLtn:print(30, 20, "< L");
				ifontLtn:print(450, 20, "R >");
			end
		
			drawLevel = 1;
			while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
			end
		
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
		
			System.endDraw();
			screen.flip();
			screen.waitVblankStart(30);
			
		elseif pad:down() then
			i = 1 + (page * 10);
			selection = selection + 1;
			screen.waitVblankStart(30);
			
			if (selection == #dictionary + 1 or selection > ((page + 1) * 10)) then
				selection = 1 + (page * 10);
			end
			
			System.draw();
			screen:clear();
			screen:blit(0, 0, background);
		
			ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(240, 22, "Select a word list");
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (#dictionary > 10) then
				ifontLtn:print(30, 20, "< L");
				ifontLtn:print(450, 20, "R >");
			end
		
			drawLevel = 1;
			while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
			end
		
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
		
			System.endDraw();
			screen.flip();
			
		elseif pad:up() then
			i = 1 + (page * 10);
			selection = selection - 1;
			screen.waitVblankStart(30);
			
			if (selection < 1 or selection <= (page * 10)) then
				selection = (page + 1) * 10;
				if (selection > #dictionary) then
					selection = #dictionary;
				end
			end
			
			System.draw();
			screen:clear();
			screen:blit(0, 0, background);
			
			ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(240, 22, "Select a word list");
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			
			if (#dictionary > 10) then
				ifontLtn:print(30, 20, "< L");
				ifontLtn:print(450, 20, "R >");
			end
			
			drawLevel = 1;
			while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
			end
		
			ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(400, 260, selection .. "/" .. #dictionary);
		
			System.endDraw();
			screen.flip();
			
		elseif pad:square() or pad:circle() or pad:cross() or pad:triangle() then
		
			if (io.open(dictionary[selection]) == nil ) then
				-- dictionary was not found
				
				System.draw();
				screen:clear()
				screen:blit(0, 0, background);
				
				ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(240, 22, "Select a word list");
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				
				if (#dictionary > 10) then
					ifontLtn:print(30, 20, "< L");
					ifontLtn:print(450, 20, "R >");
				end
				
				ifontLtn:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(240, 260, "File not found");
				
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				
				drawLevel = 1;
				while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
				end
		
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
				
				System.endDraw();
				screen.flip();
				screen.waitVblankStart(30);
				
			else
				-- store sentences
				storeSentences(dictionary[selection]);
				
				System.draw();
				screen:clear();
				screen:blit(0, 0, background);
				
				ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(240, 22, "Select a word list");
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				
				if (#dictionary > 10) then
					ifontLtn:print(30, 20, "< L");
					ifontLtn:print(450, 20, "R >");
				end
				
				drawLevel = 1;
				while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				ifontLtn:print(240, 20 * drawLevel + 30, dictionary[i]);
				i = i + 1;
				drawLevel = drawLevel + 1;
				end
		
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
				screen.waitVblankStart(30);
				System.endDraw();
				screen.flip();
				collectgarbage(); -- free memory of previous lists
				return dictionary[selection];
			end
		end
			
	end
end

initialize = function()

dictionary = {};
i = 1;
file = io.open("dictionary.ini", "r");

if not file then
	-- dictionary.ini missing
	ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
	System.draw();
	ifontLtn:print(240, 150, "Root folder did not have dictionary.ini file. It is required!");
	System.endDraw()
	screen.flip()
	screen.waitVblankStart(150);
	System.quit();
end

for line in file:lines() do
	if ( line ~= nil and string.len(trim(line)) ~= 0 and string.sub(line, 1, 1) ~= "#") then -- dont allow spaces only or commented files
		dictionary[i] = line:gsub(string.char(13),""); -- file name may have unnecessary characters. If so it cannot be opened.
		i = i + 1;
	end
end
file:close();

if (#dictionary == 0) then
	ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
	System.draw();
	ifontLtn:print(240, 150, "File dictionary.ini is empty.");
	System.endDraw()
	screen.flip()
	screen.waitVblankStart(150);
	System.quit();
end

selectedDictionary = menu(dictionary); -- Show items.

file2 = io.open(selectedDictionary);

i = 1;
word = {};

-- Parse words
for line in file2:lines() do

	if (line ~= nil and string.len(trim(line)) > 0 and string.sub(line, 1, 1) ~= "#" and string.find(line, ";") ~= nil) then -- ignore empty words and commented lines or words without ;
	
	-- Add space if only ;a;a -situation.
	local index = 1;
	local str = line;
	local tempLine = "";
	
	while index ~= nil do
		index = string.find(str, ";", index)
	
		if (index == 1) then
			tempLine = tempLine .. " ";
		end
	
		tempLine = tempLine .. str:sub(1, index);
		
		if (index ~= nil) then
			str = str:sub(index + 1);
			index = 1;
		end
	end
  
	line = tempLine;
  
	word[i] = line:split( "[^;]+" )
	i = i + 1;
	end
end
file2:close();

if (#word < 4) then
	ifontLtn:setStyle(0.8, red, darkgray, IntraFont.ALIGN_CENTER);
	System.draw();
	screen:clear()
	screen:blit(0, 0, background);
	ifontLtn:print(240, 260, "Selected list has not enough words. 4 is minimum.");
	System.endDraw();
	screen.flip()
	screen.waitVblankStart(100);
	initialize();
end

start();

end

start = function()

ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);

show = 1;
mode = 1; -- translation is question. If 2 answer is question.
extraQ = 0; -- with analog user may increase the font size of question.
showAnswer = false; -- for showing answer is user has guessed wrong.
local waited = false; -- for waiting only one time
local imageLoaded = false; -- for picture dictionary
questionImage = nil;
loadSaveData(selectedDictionary, word, mode);
randomize();

while true do
		-- Show questions
        System.draw();
		screen:blit(0, 0, background);
		screen:blit(30, 118, square);
		screen:blit(30, 146, triangle);
		screen:blit(30, 174, circle);
		screen:blit(30, 202, cross);
		
		if (waited == false) then
			waitBeforeShowing(); -- USER SET WAIT TIME
			waited = true;
		end
		
		if (mode == 1) then
		
		-- if too long text, should smallen the font
		question1 = trim(word[question][#word[question] - 1]);
		if (string.len(question1) > 40) then
			ifont:setStyle(0.6 + extraQ, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		if (string.len(question1) > 80) then
			local beginning = string.sub(question1, 1, 80);
			local ending = string.sub(question1, 81);
			question1 = beginning .. "\n" .. ending;
		end
		
		if (string.find(question1, ".png")) then -- image query
			if (imageLoaded == false) then
			
				local file8 = io.open(question1);
				if (file8 == nil ) then
					questionImage = false;
				else
					questionImage = Image.load(question1);
					imageLoaded = true;
					file8:close()
				end
			end
			if (questionImage == false) then
				ifont:print(240, 56, "Not found: " .. question1);
			else
				screen:blit(0,0,questionImage) -- image was found, show it
				screen:blit(30, 118, square);
				screen:blit(30, 146, triangle);
				screen:blit(30, 174, circle);
				screen:blit(30, 202, cross);
			end
	
		else
			ifont:print(240, 56, question1); -- translation
		end
		
		word1 = trim(word[first][show]);
		word2 = trim(word[second][show]);
		word3 = trim(word[third][show]);
		word4 = trim(word[fourth][show]);
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter < counts) do
		
			if (string.len(word1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[first] - 2;
				end
			
				word1 = trim(word[first][tempShow])
				counter = counter + 1;
	
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word2) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[second] - 2;
				end
			
				word2 = trim(word[second][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word3) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[third] - 2;
				end
			
				word3 = trim(word[third][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word4) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[fourth] - 2;
				end
			
				word4 = trim(word[fourth][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
			ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (string.len(word1) > 40) then
				ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word1) > 80) then
				local beginning = string.sub(word1, 1, 80);
				local ending = string.sub(word1, 81);
				word1 = beginning .. "\n" .. ending;
			end

			ifont:print(240, 136, word1); -- answer1
		
			ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (string.len(word2) > 40) then
				ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word2) > 80) then
				local beginning = string.sub(word2, 1, 80);
				local ending = string.sub(word2, 81);
				word2 = beginning .. "\n" .. ending;
			end
		
			ifont:print(240, 166, word2); -- answer2
		
			ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (string.len(word3) > 40) then
				ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
			end
		
			-- optimizing for japanese strings, if too long line break
			if (string.len(word3) > 80) then
				local beginning = string.sub(word3, 1, 80);
				local ending = string.sub(word3, 81);
				word3 = beginning .. "\n" .. ending;
			end
		
			ifont:print(240, 196, word3); -- answer3
		
			ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
			if (string.len(word4) > 40) then
				ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word4) > 80) then
				local beginning = string.sub(word4, 1, 80);
				local ending = string.sub(word4, 81);
				word4 = beginning .. "\n" .. ending;
			end
		
			ifont:print(240, 226, word4); -- answer4
		
			ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		elseif (mode == 2) then
		
		question1 = trim(word[question][show]);
		
		-- if wrong mode (comes from mode 2 to picture questionaire)
		if (string.find(question1, ".png")) then -- image query
			mode = 1;
			randomize();
		end
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter <= counts) do
		
			if (string.len(question1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[question] - 2;
				end
			
				question1 = trim(word[question][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		if (string.len(question1) > 40) then
			ifont:setStyle(0.6 + extraQ, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(question1) > 80) then
			local beginning = string.sub(question1, 1, 80);
			local ending = string.sub(question1, 81);
			question1 = beginning .. "\n" .. ending;
		end
		
		ifont:print(240, 56, question1);
		
		word1 = trim(word[first][#word[first] - 1]);
		word2 = trim(word[second][#word[second] - 1]);
		word3 = trim(word[third][#word[third] - 1]);
		word4 = trim(word[fourth][#word[fourth] - 1]);
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (string.len(word1) > 40) then
			ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word1) > 80) then
			local beginning = string.sub(word1, 1, 80);
			local ending = string.sub(word1, 81);
			word1 = beginning .. "\n" .. ending;
		end
		
		ifont:print(240, 136, word1); -- translation
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (string.len(word2) > 40) then
			ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word2) > 80) then
			local beginning = string.sub(word2, 1, 80);
			local ending = string.sub(word2, 81);
			word2 = beginning .. "\n" .. ending;
		end
		
		ifont:print(240, 166, word2); -- translation
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		
		if (string.len(word3) > 40) then
			ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word3) > 80) then
			local beginning = string.sub(word3, 1, 80);
			local ending = string.sub(word3, 81);
			word3 = beginning .. "\n" .. ending;
		end
		
		ifont:print(240, 196, word3); -- translation
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (string.len(word4) > 40) then
			ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word4) > 80) then
			local beginning = string.sub(word4, 1, 80);
			local ending = string.sub(word4, 81);
			word4 = beginning .. "\n" .. ending;
		end
		
		ifont:print(240, 226, word4); -- translation
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		end

		-- Show right answer
		if (userOptions[1] == "true" and showAnswer) then
			if (question == first) then
				screen:blit(60, 116, right);
			elseif (question == second) then
				screen:blit(60, 146, right);
			elseif (question == third) then
				screen:blit(60, 176, right);
			else
				screen:blit(60, 206, right);
			end
		end
		
		ifont:print(100, 255, "Mode: " .. mode .. " / Show: " .. show ); -- show mode and show
		ifont:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifont:print(10, 267, "Range: " .. askMin .. "-" .. askMax .. " / " .. #word); -- show range
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (allKnown == 1) then
			ifont:print(395, 260, "All once correct");
		elseif (setKnown == 1) then
			ifont:print(395, 260, "Set once correct");
		end
		
        local pad = Controls.readPeek()

        if pad:square() then
				if (mode == 1 and (question == first or string.lower(trim(word[question][show])) == string.lower(word1))) then -- there may be multiple same answers that's why or
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word1, question1)
					end
					randomize();			
				elseif(mode == 2 and (question == first or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word1))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word1)
					end
					randomize();
				else
					ifont:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Wrong")
					screen.flip();
					screen.waitVblankStart(30);
					showAnswer = true;
				end
				
		elseif pad:triangle() then
				if (mode == 1 and (question == second or string.lower(trim(word[question][show])) == string.lower(word2))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word2, question1)
					end
					randomize();
				elseif(mode == 2 and (question == second or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word2))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word2)
					end
					randomize();
				else
					ifont:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Wrong")
					screen.flip();
					screen.waitVblankStart(30);
					showAnswer = true;
				end
				
		elseif pad:circle() then
				if (mode == 1 and (question == third or string.lower(trim(word[question][show])) == string.lower(word3))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word3, question1)
					end
					randomize();
				elseif(mode == 2 and (question == third or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word3))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word3)
					end
					randomize();
				else
					ifont:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Wrong")
					screen.flip();
					screen.waitVblankStart(30);
					showAnswer = true;
				end
				
		elseif pad:cross() then
				if (mode == 1 and (question == fourth or string.lower(trim(word[question][show])) == string.lower(word4))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word4, question1)
					end
					randomize();
				elseif(mode == 2 and (question == fourth or sring.lower(trim(word[question][#word[question] - 1])) == string.lower(word4))) then
					-- Right answer
					ifont:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Right")
					screen.flip();
					screen.waitVblankStart(30);
					word[question][#word[1]] = "true";
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word4)
					end
					randomize();
				else
					ifont:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifont:print(240, 260, "Wrong")
					screen.flip();
					screen.waitVblankStart(30);
					showAnswer = true;
				end	
				
		elseif pad:right() then
				if (show == #word[1] - 2) then
					show = 1;
					screen.waitVblankStart(20);
				else
					show = show + 1;
					screen.waitVblankStart(20);
				end
				
		elseif pad:left() then
				if (show == 1) then
					show = #word[1] - 2;
					screen.waitVblankStart(20);
				else
					show = show - 1;
					screen.waitVblankStart(20);
				end
				
		elseif pad:up() and imageLoaded == false then -- these buttons cannot be used with picture dictionaries
			if (mode == 1) then
				save();
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			else
				save();
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			end;
			
		elseif pad:down() and imageLoaded == false then
			if (mode == 1) then
				save();
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			else
				save();
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			end;
		
		elseif (pad:analogY() < -100 ) then
			extraQ = extraQ + 0.1;
			if (extraQ > 2) then
				extraQ = 2;
			end
		
		elseif (pad:analogY() > 100 ) then
			extraQ = extraQ - 0.1
			if (extraQ < 0) then
				extraQ = 0
			end
		
		elseif (pad:analogX() < - 100 and userOptions[4] ~= "0") then
			askLevel = askLevel - 1;
			if (askLevel < 0) then
				askLevel = math.ceil(#word / userOptions[4]) - 1;
			end
			
			calculateMinMax()
			checkKnownWords()
			screen.waitVblankStart(20);
			
		elseif (pad:analogX() > 100 and userOptions[4] ~= "0") then
			askLevel = askLevel + 1;
			if (askLevel > (math.ceil(#word / userOptions[4]) - 1)) then
				askLevel = 0;
			end
			calculateMinMax()
			checkKnownWords()
			screen.waitVblankStart(20);	
		
		elseif pad:select() then
			save()
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			initialize();
		
		elseif pad:home() then
				break;
		
        elseif pad:start() then
			save()
			screen.waitVblankStart(20);
			openOptions();
			
		elseif pad:r() then
			result = System.msgDialog("Do you want to clear known list?", true, drawFunc)
			if (result==System.MSGDIALOG_RESULT_YES) then
				clearResults(word);
				allKnown = 0;
				save();
			end
		elseif pad:l() then
			screen.waitVblankStart(20);
			showKeys()
        end
		
		ifont:setStyle(1.0 + extraQ, white, darkgray, IntraFont.ALIGN_CENTER);
        System.endDraw();
        screen.flip();
end

save() -- switched save here
ifont:unload();
ifontLtn:unload();

System.quit(); -- Quit the application

end

save = function()
	saveFile = selectedDictionary .. mode;
	file3 = io.open(saveFile,"w")
				
	i = 0;
	while (i < #word) do
		i = i + 1;
		if (word[i][#word[1]] ~= nil) then
			result = tostring(word[i][#word[1]]) .. "\n";
		else
			result = "\n";
		end
		file3:write(result);
	end
				
	file3:close();
end

-- PROGRAM STARTS
showLogo();
loadOptions(); -- get user saved options
initialize(); -- calls start