public class JapaneseAndroidLearnHelperApplication extends MultiDexApplication {

	public static final ThemeType defaultThemeType = ThemeType.BLACK;
	
	private static JapaneseAndroidLearnHelperApplication singleton;

	public static JapaneseAndroidLearnHelperApplication getInstance() {
		return singleton;
	}
	
	private JapaneseAndroidLearnHelperContext context;
	
	private DictionaryManagerCommon dictionaryManager;
	
	private ConfigManager configManager;
	
	private WordDictionaryMissingWordQueue wordDictionaryMissingWordQueue;

	private QueueEventThread queueEventThread;
	
	private Typeface babelStoneHanSubset = null;
	
	// private Tracker tracker = null;

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
	}

	@Override
	public void onCreate() {
		super.onCreate();
		
		singleton = this;
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
	}

	@Override
	public void onTerminate() {
		super.onTerminate();

		stopQueueThread();

		if (dictionaryManager != null) {
			dictionaryManager.close();
		}
	}
	
	public JapaneseAndroidLearnHelperContext getContext() {
		
		if (context == null) {
			context = new JapaneseAndroidLearnHelperContext();
		}
		
		return context;
	}

	public DictionaryManagerCommon getDictionaryManager(final Activity activity) {
		
		Resources resources = activity.getResources();
		AssetManager assets = activity.getAssets();
				
		if (dictionaryManager == null) {
			
	        int versionCode = 0;
	        
	        try {
	        	PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
	        	
	            versionCode = packageInfo.versionCode;

	        } catch (NameNotFoundException e) {        	
	        }
	        
	        ILoadWithProgress loadWithProgress = new ILoadWithProgress() {
				
				@Override
				public void setMaxValue(int maxValue) {
				}
				
				@Override
				public void setError(String errorMessage) {					
					throw new RuntimeException(errorMessage);					
				}
				
				@Override
				public void setDescription(String desc) {
				}
				
				@Override
				public void setCurrentPos(int currentPos) {
				}
			};
						
			dictionaryManager = DictionaryManagerCommon.getDictionaryManager();
			
			dictionaryManager.init(activity, loadWithProgress, resources, assets, getPackageName(), versionCode);
		}
		
		return dictionaryManager;
	}

	public void setDictionaryManager(DictionaryManagerCommon dictionaryManager) {
		this.dictionaryManager = dictionaryManager;
	}

	public DataManager getDataManager() {

		if (dictionaryManager == null) {
			return null;
		}

		return dictionaryManager.getDataManager();
	}

	public ConfigManager getConfigManager(Activity activity) {
		
		if (configManager == null) {
			configManager = new ConfigManager(activity);
		}
		
		return configManager;
	}

	public void setConfigManager(ConfigManager configManager) {
		this.configManager = configManager;
	}
	
	public WordDictionaryMissingWordQueue getWordDictionaryMissingWordQueue(Activity activity) {
		
		if (wordDictionaryMissingWordQueue == null) {
			wordDictionaryMissingWordQueue = new WordDictionaryMissingWordQueue(activity);
		}
		
		return wordDictionaryMissingWordQueue;
	}

	public void setWordDictionaryMissingWordQueue(WordDictionaryMissingWordQueue wordDictionaryMissingWordQueue) {
		this.wordDictionaryMissingWordQueue = wordDictionaryMissingWordQueue;
	}

	public Typeface getBabelStoneHanSubset(AssetManager assetManager) {
		
		if (babelStoneHanSubset != null) {
			return babelStoneHanSubset;
		}
		
		babelStoneHanSubset = Typeface.createFromAsset(getAssets(), "BabelStoneHan-subset.ttf");
		
		return babelStoneHanSubset;
	}

	public void setContentViewAndTheme(Activity activity, int contentViewId) {
		activity.setTheme(getThemeType(activity).styleId);

		DataBindingUtil.setContentView(activity, contentViewId);
	}

	public ThemeType getThemeType() {
		return getThemeType(null);
	}

	private ThemeType getThemeType(Activity activity) {

		if (configManager != null) {
			return configManager.getCommonConfig().getThemeType(defaultThemeType);
		}

		if (activity == null) {
			return defaultThemeType;
		}

		getConfigManager(activity);

		if (configManager != null) {
			return configManager.getCommonConfig().getThemeType(defaultThemeType);
		}

		return defaultThemeType;
	}

	public int getLinkColor() {

		TypedArray typedArray = getTheme().obtainStyledAttributes(
				getThemeType().getStyleId(),
				new int[] { android.R.attr.textColorLink });

		int intColor = typedArray.getColor(0, 0);

		typedArray.recycle();

		return intColor;
	}

	/*
	public Tracker getTracker() {
		
		if (tracker != null) {
			return tracker;
		}
		
		GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);

		tracker = analytics.newTracker(R.xml.app_tracker);

		tracker.enableAdvertisingIdCollection(true);
		
		return tracker;		
	}
	*/

	public void logScreen(Activity activity, String screenName) {

	    /*
		Tracker tracker = getTracker();
		
		tracker.setScreenName(screenName);
		
		tracker.send(new HitBuilders.AppViewBuilder().build());
		*/

		addQueueEvent(activity, new StatLogScreenEvent(getConfigManager(activity).getCommonConfig().getOrGenerateUniqueUserId(), screenName));
	}
	
	public void logEvent(Activity activity, String screenName, String actionName, String label) {

	    /*
		Tracker tracker = getTracker();
		
		tracker.send(new HitBuilders.EventBuilder()
				.setCategory(screenName)
				.setAction(actionName).
				setLabel(label).
				build());
		*/

		addQueueEvent(activity, new StatLogEventEvent(getConfigManager(activity).getCommonConfig().getOrGenerateUniqueUserId(), screenName, actionName, label));
	}

	public synchronized void startQueueThread(Activity activity) {

		if (queueEventThread == null || queueEventThread.isAlive() == false) {

            queueEventThread = new QueueEventThread(activity.getPackageManager(), activity.getPackageName());

            queueEventThread.start();
		}
	}

	public synchronized void stopQueueThread() {

		if (queueEventThread != null && queueEventThread.isAlive() == true) {

            queueEventThread.requestStop();

			try {
                queueEventThread.join(11000);

			} catch (InterruptedException e) {
				// noop
			}
		}
	}

	public synchronized void addQueueEvent(Activity activity, IQueueEvent queueEvent) {

		startQueueThread(activity);

		if (queueEventThread != null) {

			ThemeType themeType = getThemeType(activity);

			queueEventThread.addQueueEvent(activity, themeType, queueEvent);
		}
	}

	public enum ThemeType {

		BLACK(	R.style.JapaneseDictionaryBlackStyle,
				android.R.color.white,
				R.color.title_background_for_black,
				android.R.color.white,
				Color.DKGRAY,
				R.drawable.delete_for_black,
				R.drawable.user_group_list_for_black,
				R.drawable.listening_for_black),

		WHITE(	R.style.JapaneseDictionaryWhiteStyle,
				android.R.color.black,
				R.color.title_background_for_white,
				android.R.color.black,
				Color.WHITE,
				R.drawable.delete_for_white,
				R.drawable.user_group_list_for_white,
				R.drawable.listening_for_white);

		private int styleId;

		private int textColorId;

		private int titleItemBackgroundColorId;

		private int kanjiStrokeColorId;

		private int kanjiSearchRadicalInactiveColorId;

		private int deleteIconId;

		private int userGroupListIconId;

		private int listenIconId;

		private ThemeType(int styleId, int textColorId, int titleItemBackgroundColorId, int kanjiStrokeColorId, int kanjiSearchRadicalInactiveColorId, int deleteIconId, int userGroupListIconId, int listenIconId) {
			this.styleId = styleId;
			this.textColorId = textColorId;
			this.titleItemBackgroundColorId = titleItemBackgroundColorId;
			this.kanjiStrokeColorId = kanjiStrokeColorId;
			this.kanjiSearchRadicalInactiveColorId = kanjiSearchRadicalInactiveColorId;
			this.deleteIconId = deleteIconId;
			this.userGroupListIconId = userGroupListIconId;
			this.listenIconId = listenIconId;
		}

		public int getStyleId() {
			return styleId;
		}

		public int getTextColorId() {
			return textColorId;
		}

		public int getTextColorAsColor() {
			return getInstance().getResources().getColor(textColorId);
		}

		public int getTitleItemBackgroundColorAsColor() {
			return getInstance().getResources().getColor(titleItemBackgroundColorId);
		}

		public Drawable getTitleItemBackgroundColorAsDrawable() {
			ColorDrawable colorDrawable = new ColorDrawable(getTitleItemBackgroundColorAsColor());

			return colorDrawable;
		}

		public int getKanjiStrokeColorAsColor() {
			return getInstance().getResources().getColor(kanjiStrokeColorId);
		}

		public int getKanjiSearchRadicalInactiveColorId() {
			return kanjiSearchRadicalInactiveColorId;
		}

		public int getDeleteIconId() {
			return deleteIconId;
		}

		public int getUserGroupListIconId() {
			return userGroupListIconId;
		}

		public Drawable getUserGroupListIconAsDrawable() {
			return getInstance().getResources().getDrawable(userGroupListIconId);
		}

		public int getListenIconId() {
			return listenIconId;
		}
	}
} public class MenuShorterHelper {

	public static void onCreateOptionsMenu(Menu menu) {
		menu.add(Menu.NONE, R.id.main_menu_kana_text_menu_item, Menu.NONE, R.string.main_menu_kana_text_short);
		menu.add(Menu.NONE, R.id.main_menu_counters_text_menu_item, Menu.NONE, R.string.main_menu_counters_text_short);
		menu.add(Menu.NONE, R.id.main_menu_keigo_table_text_menu_item, Menu.NONE, R.string.main_menu_keigo_table_text_short);
		menu.add(Menu.NONE, R.id.main_menu_transitive_intransitive_pairs_table_text_menu_item, Menu.NONE, R.string.main_menu_transitive_intransitive_pairs_table_text_short);
		menu.add(Menu.NONE, R.id.main_menu_dictionary_text_menu_item, Menu.NONE, R.string.main_menu_dictionary_text);
		menu.add(Menu.NONE, R.id.main_menu_kanji_text_menu_item, Menu.NONE, R.string.main_menu_kanji_text_short);
		// menu.add(Menu.NONE, R.id.main_menu_kanji_recognizer_text_menu_item, Menu.NONE, R.string.main_menu_kanji_recognizer_text_short);
		menu.add(Menu.NONE, R.id.main_menu_show_user_group_menu_item, Menu.NONE, R.string.main_menu_show_user_group_text);
	}
	
	public static boolean onOptionsItemSelected(MenuItem item, Context applicationContext, Activity activity) {
		
		int itemId = item.getItemId();
		
		if (itemId == R.id.main_menu_kana_text_menu_item) { // kana table
			
			Intent intent = new Intent(applicationContext, Kana.class);

			activity.startActivity(intent);
			
			return true;
		} else if (itemId == R.id.main_menu_counters_text_menu_item) { // counter table
			
			Intent intent = new Intent(applicationContext, CountersActivity.class);

			activity.startActivity(intent);
			
			return true;
		} else if (itemId == R.id.main_menu_keigo_table_text_menu_item) { // keigo table
			
			Intent intent = new Intent(applicationContext, KeigoTable.class);

			activity.startActivity(intent);
			
			return true;
		} else if (itemId == R.id.main_menu_transitive_intransitive_pairs_table_text_menu_item) { // transitive intransitive pairs table
			
			Intent intent = new Intent(applicationContext, TransitiveIntransitivePairsTable.class);

			activity.startActivity(intent);
			
		} else if (itemId == R.id.main_menu_dictionary_text_menu_item) { // dictionary
			
			Intent intent = new Intent(applicationContext, WordDictionaryTab.class);

			activity.startActivity(intent);
			
			return true;
		} else if (itemId == R.id.main_menu_kanji_text_menu_item) { // kanji search
			
			Intent intent = new Intent(applicationContext, KanjiSearch.class);

			activity.startActivity(intent);
			
			return true;
		/* } else if (itemId == R.id.main_menu_kanji_recognizer_text_menu_item) { // kanji recognize
			
			Intent intent = new Intent(applicationContext, KanjiRecognizeActivity.class);

			activity.startActivity(intent);	
			
			return true;
		*/
		} else if (itemId == R.id.main_menu_show_user_group_menu_item) { // pokaz grupy uzytkownika

			Intent intent = new Intent(applicationContext, UserGroupActivity.class);

			activity.startActivity(intent);

			return true;
		}

		return false;
	}
} public class KanaTestConfig {
		
	private final String kanaTestConfigPrefix = "kanaTestConfig_";
		
	private final String rangeTestPostfix = "rangeTest";
		
	private final String testMode1Postfix = "testMode1";
	private final String testMode2Postfix = "testMode2";
		
	private final String untilSuccessPostfix = "untilSuccess";
	private final String untilSuccessNewWordLimitPostfix = "untilSuccessNewWordLimit";
		
	private final String gojuuonPostfix = "gojuuon";
	private final String dakutenHandakutenPostfix = "dakutenHandakuten";
	private final String youonPostfix = "youon";
				
	public RangeTest getRangeTest() {
			
		String rangeTest = preferences.getString(kanaTestConfigPrefix + rangeTestPostfix, RangeTest.HIRAGANA_KATAKANA.toString());
			
		return RangeTest.valueOf(rangeTest);
	}

	public TestMode1 getTestMode1() {
			
		String testMode1 = preferences.getString(kanaTestConfigPrefix + testMode1Postfix, TestMode1.CHOOSE.toString());
			
		return TestMode1.valueOf(testMode1);
	}

	public TestMode2 getTestMode2() {
			
		String testMode2 = preferences.getString(kanaTestConfigPrefix + testMode2Postfix, TestMode2.KANA_TO_ROMAJI.toString());
			
		return TestMode2.valueOf(testMode2);
	}

	public void setRangeTest(RangeTest rangeTest) {
			
		Editor editor = preferences.edit();
			
		editor.putString(kanaTestConfigPrefix + rangeTestPostfix, rangeTest.toString());
			
		editor.commit();
	}

	public void setTestMode1(TestMode1 testMode1) {
			
		Editor editor = preferences.edit();
			
		editor.putString(kanaTestConfigPrefix + testMode1Postfix, testMode1.toString());
			
		editor.commit();
	}

	public void setTestMode2(TestMode2 testMode2) {
			
		Editor editor = preferences.edit();
			
		editor.putString(kanaTestConfigPrefix + testMode2Postfix, testMode2.toString());
			
		editor.commit();
	}

	public Boolean getUntilSuccess() {
		return preferences.getBoolean(kanaTestConfigPrefix + untilSuccessPostfix, true);
	}

	public void setUntilSuccess(boolean untilSuccess) {
			
		Editor editor = preferences.edit();
			
		editor.putBoolean(kanaTestConfigPrefix + untilSuccessPostfix, untilSuccess);
			
		editor.commit();
	}

	public Boolean getUntilSuccessNewWordLimit() {
		return preferences.getBoolean(kanaTestConfigPrefix + untilSuccessNewWordLimitPostfix, false);
	}

	public void setUntilSuccessNewWordLimit(boolean untilSuccessNewWordLimit) {
			
		Editor editor = preferences.edit();
			
		editor.putBoolean(kanaTestConfigPrefix + untilSuccessNewWordLimitPostfix, untilSuccessNewWordLimit);
			
		editor.commit();
	}
		
	public Boolean getGojuuon() {
		return preferences.getBoolean(kanaTestConfigPrefix + gojuuonPostfix, true);
	}

	public Boolean getDakutenHandakuten() {
		return preferences.getBoolean(kanaTestConfigPrefix + dakutenHandakutenPostfix, true);
	}

	public Boolean getYouon() {
		return preferences.getBoolean(kanaTestConfigPrefix + youonPostfix, true);
	}

	public void setGojuuon(Boolean gojuuon) {
			
		Editor editor = preferences.edit();
			
		editor.putBoolean(kanaTestConfigPrefix + gojuuonPostfix, gojuuon);
			
		editor.commit();
	}

	public void setDakutenHandakuten(boolean dakutenHandakuten) {
			
		Editor editor = preferences.edit();
			
		editor.putBoolean(kanaTestConfigPrefix + dakutenHandakutenPostfix, dakutenHandakuten);
			
		editor.commit();
	}

	public void setYouon(boolean youon) {
			
		Editor editor = preferences.edit();
			
		editor.putBoolean(kanaTestConfigPrefix + youonPostfix, youon);
			
		editor.commit();
	}		
} public class JapaneseAndroidLearnHelperKanaTestContext {

	// from test
	private EntryOrderList<KanaEntry> allKanaEntries;
	
	private Map<String, List<KanaEntry>> allKanaEntriesGroupBy;
		
	private boolean initialized = false;
	
	private String charTestValue;
	
	private String[][] buttonValues;
	
	private int correctAnswers = 0;
	
	private int incorrectAnswers = 0;
	
	// methods
	
	public void resetTest() {
		allKanaEntries = null;
		allKanaEntriesGroupBy = null;
		initialized = false;
		charTestValue = null;
		buttonValues = null;
		correctAnswers = 0;
		incorrectAnswers = 0;
	}
	
	public EntryOrderList<KanaEntry> getAllKanaEntries() {
		return allKanaEntries;
	}

	public Map<String, List<KanaEntry>> getAllKanaEntriesGroupBy() {
		return allKanaEntriesGroupBy;
	}

	public boolean isInitialized() {
		return initialized;
	}

	public void setAllKanaEntries(EntryOrderList<KanaEntry> allKanaEntries) {
		this.allKanaEntries = allKanaEntries;
	}

	public void setAllKanaEntriesGroupBy(
			Map<String, List<KanaEntry>> allKanaEntriesGroupBy) {
		this.allKanaEntriesGroupBy = allKanaEntriesGroupBy;
	}

	public void setInitialized(boolean initialized) {
		this.initialized = initialized;
	}

	public String getCharTestValue() {
		return charTestValue;
	}

	public void setCharTestValue(String charTestValue) {
		this.charTestValue = charTestValue;
	}

	public String[][] getButtonValues() {
		return buttonValues;
	}

	public void setButtonValues(String[][] buttonValues) {
		this.buttonValues = buttonValues;
	}
	
	public void incrementCorrectAnswers() {
		correctAnswers++;
	}
	
	public void incrementIncorrectAnswers() {
		incorrectAnswers++;
	}

	public int getCorrectAnswers() {
		return correctAnswers;
	}

	public int getIncorrectAnswers() {
		return incorrectAnswers;
	}
	
	public static enum RangeTest {
		HIRAGANA,
		
		KATAKANA,
		
		HIRAGANA_KATAKANA;
	}
	
	public static enum TestMode1 {
		CHOOSE,
		
		INPUT;
	}
	
	public static enum TestMode2 {
		KANA_TO_ROMAJI,
		
		ROMAJI_TO_KANA;
	}
} public static enum RangeTest {
	HIRAGANA,
		
	KATAKANA,
		
	HIRAGANA_KATAKANA;
} public static enum TestMode1 {
	CHOOSE,
		
	INPUT;
} public static enum TestMode2 {
	KANA_TO_ROMAJI,
		
	ROMAJI_TO_KANA;
} public class ReportProblem {
	
	public static Intent createReportProblemIntent(String mailSubject, String mailBody, String versionName, int versionCode) {
		
		Intent email = new Intent(Intent.ACTION_SEND);
		
		mailBody += "---\nVersion code: " + versionCode + "\nVersion name: " + versionName + "\n";
		
		email.putExtra(Intent.EXTRA_EMAIL, new String[] { "fryderyk.mazurek@gmail.com" } );
		
		email.putExtra(Intent.EXTRA_SUBJECT, mailSubject);
		email.putExtra(Intent.EXTRA_TEXT, mailBody);
		
		email.setType("message/rfc822");
		
		return email;
	}
} public class Button implements IScreenItem {
	
	private android.widget.Button button;
	
	private String text;
	
	private Float textSize;
	
	private OnClickListener onClickListener;
	
	public Button(String text) {
		this.text = text;
	}
	
	public void setText(String text) {
		this.text = text;
		
		if (button != null) {
			button.setText(text);
		}
	}
	
	public String getText() {
		return text;
	}
	
	public void setTextSize(Float textSize) {
		this.textSize = textSize;

		if (button != null) {
			button.setTextSize(textSize);
		}
	}

	public void generate(Context context, Resources resources, ViewGroup layout) {
		
		LayoutInflater layoutInflater = ((Activity)context).getLayoutInflater();
		
		LinearLayout linearLayoutInflate = (LinearLayout)layoutInflater.inflate(R.layout.button_wrapper_layout, null);
		
		button = (android.widget.Button)linearLayoutInflate.getChildAt(0);
		
		linearLayoutInflate.removeViewAt(0);
				
		if (layout instanceof android.widget.TableRow) {		
			button.setLayoutParams(new android.widget.TableRow.LayoutParams(android.widget.TableRow.LayoutParams.MATCH_PARENT, android.widget.TableRow.LayoutParams.WRAP_CONTENT));
			
		} else if (layout instanceof LinearLayout) {
			button.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
			
		} else {
			throw new RuntimeException(String.valueOf(layout.getClass()));
		}
		
		button.setText(text);
		
		if (textSize != null) {
			button.setTextSize(textSize);
		}
		
		button.setOnClickListener(onClickListener);
		
		layout.addView(button);		
	}
	
	public int getY() {
		
		if (button != null) {
			return button.getTop();
		}
		
		throw new RuntimeException("button is null");
	}

	public String toString() {
		return "***" + text + "***";
	}

	public void setOnClickListener(OnClickListener onClickListener) {
		this.onClickListener = onClickListener;		
	}
} public interface IScreenItem {
	public void generate(Context context, Resources resources, ViewGroup layout);
	
	public int getY();
	
	public String toString();
} public class StringValue implements IScreenItem {
	
	private TextView textView;
	
	private CharSequence value;
	
	private float textSize;
	
	private Integer gravity;
	
	private int level;
	
	private Integer marginLeft = null;
	private Integer marginTop = null;
	private Integer marginRight = null;
	private Integer marginBottom = null;
	
	private Integer layoutWeight;
	
	private OnClickListener onClickListener;
	
	private OnTouchListener onTouchListener;
	
	private Integer textColor;
	
	private Integer defaultTextColor;
	
	private Typeface typeface;
	
	private Integer backgroundColor;

	public StringValue(String value, float textSize, int level) {
		this.value = value;
		this.textSize = textSize;
		this.level = level;
	}

	public StringValue(Spanned value, float textSize, int level) {
		this.value = value;
		this.textSize = textSize;
		this.level = level;
	}
	
	public void setValue(CharSequence value) {
		this.value = value;
		
		if (textView != null) {
			textView.setText(this.value);
		}
	}
	
	public String getValue() {
		return this.value.toString();
	}
	
	public void setGravity(int gravity) {
		this.gravity = gravity;
	}
	
	public void setLayoutWidth(Integer layoutWeight) {
		this.layoutWeight = layoutWeight;
	}
	
	public void setNullMargins(boolean nullMargins) {
		
		if (nullMargins == true) {		
			this.marginLeft = 0;
			this.marginTop = 0;
			this.marginRight = 0;
			this.marginBottom = 0;
			
		} else {
			this.marginLeft = null;
			this.marginTop = null;
			this.marginRight = null;
			this.marginBottom = null;			
		}
	}
	
	public void setTypeface(Typeface typeface) {
		this.typeface = typeface;
	}
	
	public void setBackgroundColor(Integer backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

	public void generate(Context context, Resources resources, ViewGroup layout) {
		textView = new TextView(context);
				
		if (layout instanceof android.widget.TableRow) {
			android.widget.TableRow.LayoutParams layoutParam = new android.widget.TableRow.LayoutParams(android.widget.TableRow.LayoutParams.WRAP_CONTENT, android.widget.TableRow.LayoutParams.WRAP_CONTENT);
			
			if (marginLeft != null || marginTop != null || marginRight != null || marginBottom != null) {
				layoutParam.setMargins(marginLeft != null ? marginLeft : 0, marginTop != null ? marginTop : 0,
						marginRight != null ? marginRight : 0, marginRight != null ? marginRight : 0);
			} else {
				layoutParam.setMargins(20 + level * 20, 5, 0, 0);
			}

			if (layoutWeight != null) {
				layoutParam.weight = layoutWeight;
			}
			
			if (gravity != null) {
				layoutParam.gravity = gravity;
			}
			
			textView.setLayoutParams(layoutParam);
		} else if (layout instanceof LinearLayout) {
			LinearLayout.LayoutParams layoutParam = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
			
			if (marginLeft == null && marginTop == null && marginRight == null && marginBottom == null) {
				layoutParam.setMargins(20 + level * 20, 5, 0, 0);
			}
			
			if (layoutWeight != null) {
				layoutParam.weight = layoutWeight;
			}
			
			textView.setLayoutParams(layoutParam);
		} else {
			throw new RuntimeException(String.valueOf(layout.getClass()));
		}
		
		if (gravity != null) {
			textView.setGravity(gravity);
		}
		
		textView.setTextSize(textSize);
		textView.setText(value);
		
		defaultTextColor = textView.getTextColors().getDefaultColor();
		
		if (textColor != null) {
			textView.setTextColor(textColor.intValue());
		}
		
		if (typeface != null) {
			textView.setTypeface(typeface);
		}
		
		if (backgroundColor != null) {
			textView.setBackgroundColor(backgroundColor);
		}
		
		textView.setOnClickListener(onClickListener);
		textView.setOnTouchListener(onTouchListener);
				
		layout.addView(textView);			
	}
	
	public void setMarginLeft(Integer marginLeft) {
		this.marginLeft = marginLeft;
	}

	public void setMarginTop(Integer marginTop) {
		this.marginTop = marginTop;
	}

	public void setMarginRight(Integer marginRight) {
		this.marginRight = marginRight;
	}

	public void setMarginBottom(Integer marginBottom) {
		this.marginBottom = marginBottom;
	}

	public String toString() {
		if (value != null) {
			return value.toString();
		} else {
			return null;
		}
	}
	
	public int getBottomPositionOnScreen() {
		if (textView == null) {
			throw new RuntimeException("getBottomPositionOnScreen");
		}
		
		int[] location = new int[2];
		
		textView.getLocationOnScreen(location);
		
		return location[1] + textView.getHeight();
	}
	
	public void setOnClickListener(OnClickListener onClickListener) {
		this.onClickListener = onClickListener;		
	}

	public void setOnTouchListener(OnTouchListener onTouchListener) {
		this.onTouchListener = onTouchListener;
	}
	
	public void setText(String text) {
		this.value = text;
		
		if (textView != null) {
			textView.setText(text);
		}
	}
	
	public void setTextColor(Integer textColor) {
		this.textColor = textColor;
		
		if (textView != null) {
			textView.setTextColor(textColor.intValue());
		}
	}
	
	public int getY() {
		
		if (textView != null) {
			return textView.getTop();
		}
		
		throw new RuntimeException("textview is null");
	}

	public Integer getDefaultTextColor() {
		return defaultTextColor;
	}
} public class TableLayout implements IScreenItem {

	public static enum LayoutParam {

		@SuppressWarnings("deprecation")
		FillParent_WrapContent(new android.widget.TableLayout.LayoutParams(
				android.widget.TableLayout.LayoutParams.FILL_PARENT,
				android.widget.TableLayout.LayoutParams.WRAP_CONTENT)),

		WrapContent_WrapContent(new android.widget.TableLayout.LayoutParams(
				android.widget.TableLayout.LayoutParams.WRAP_CONTENT,
				android.widget.TableLayout.LayoutParams.WRAP_CONTENT));

		private android.widget.TableLayout.LayoutParams layoutParam;

		private LayoutParam(LayoutParams layoutParam) {
			this.layoutParam = layoutParam;
		}

		public android.widget.TableLayout.LayoutParams getLayoutParam() {
			return layoutParam;
		}
	}

	private final LayoutParam layoutParam;

	private final Boolean shrinkAllColumns;
	private final Boolean stretchAllColumns;

	private final List<TableRow> tableRows = new ArrayList<TableRow>();

	public TableLayout(LayoutParam layoutParam, Boolean shrinkAllColumns, Boolean stretchAllColumns) {
		this.layoutParam = layoutParam;

		this.shrinkAllColumns = shrinkAllColumns;
		this.stretchAllColumns = stretchAllColumns;
	}

	public void addTableRow(TableRow tableRow) {
		tableRows.add(tableRow);
	}

	@Override
	public void generate(Context context, Resources resources, ViewGroup layout) {

		android.widget.TableLayout tableLayout = new android.widget.TableLayout(context);

		tableLayout.setLayoutParams(layoutParam.getLayoutParam());

		if (shrinkAllColumns != null) {
			tableLayout.setShrinkAllColumns(shrinkAllColumns.booleanValue());
		}

		if (stretchAllColumns != null) {
			tableLayout.setStretchAllColumns(stretchAllColumns.booleanValue());
		}

		for (TableRow currentTableRow : tableRows) {
			currentTableRow.generate(context, resources, tableLayout);
		}

		layout.addView(tableLayout);
	}

	@Override
	public int getY() {

		if (tableRows != null && tableRows.size() > 0) {
			return tableRows.get(0).getY();
		}

		throw new RuntimeException("tableRows is null");
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();

		for (TableRow currentTableRow : tableRows) {
			sb.append(currentTableRow.toString()).append("\n");
		}

		return sb.toString();
	}
} public class TableRow implements IScreenItem {
	
	private android.widget.TableRow tableRow = null;
	
	private List<IScreenItem> screenItems = new ArrayList<IScreenItem>();
	
	public void addScreenItem(IScreenItem item) {
		screenItems.add(item);
	}
	
	public int getScreenItemSize() {
		return screenItems.size();
	}

	public void generate(Context context, Resources resources, ViewGroup layout) {
		
		if (screenItems.size() > 0) {
			tableRow = new android.widget.TableRow(context);

			for (IScreenItem currentScreenItem : screenItems) {
				currentScreenItem.generate(context, resources, tableRow);
			}
			
			layout.addView(tableRow);			
		}
	}
	
	public int getY() {
		
		if (tableRow != null) {
			return tableRow.getTop();
		}
		
		throw new RuntimeException("tableRow is null");
	}
	
	public String toString() {
		
		StringBuffer sb = new StringBuffer();
		
		if (screenItems.size() > 0) {
			for (IScreenItem currentScreenItem : screenItems) {
				sb.append(currentScreenItem.toString().replaceAll("\n", " ")).append("; ");
			}
		}
		
		return sb.toString();
	}

	public void setVisibility(int visibility) {
		tableRow.setVisibility(visibility);
	}
} public class TitleItem implements IScreenItem {
	
	private TextView textView;
	
	private String title;
	
	private int level;
	
	private OnClickListener onClickListener;
	
	public TitleItem(String title, int level) {
		this.title = title;
		this.level = level;
	}

	public void generate(Context context, Resources resources, ViewGroup layout) {
		textView = new TextView(context);
		
		textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

		textView.setBackgroundColor(JapaneseAndroidLearnHelperApplication.getInstance().getThemeType().getTitleItemBackgroundColorAsColor());
		textView.setTextSize(16.0f);
		
		StringBuffer titleSb = new StringBuffer();
		
		for (int levelIdx = 0; levelIdx < level; ++levelIdx) {
			titleSb.append("   ");
		}
		titleSb.append(title);
		
		textView.setText(titleSb);	
		
		textView.setOnClickListener(onClickListener);
		
		layout.addView(textView);
	}
	
	public String toString() {
		return " *** " + title;			
	}
	
	public int getTopPositionOnScreen() {
		if (textView == null) {
			throw new RuntimeException("getTopPositionOnScreen");
		}
		
		int[] location = new int[2];
		
		textView.getLocationOnScreen(location);
		
		return location[1];
	}
	
	public int getY() {
		
		if (textView != null) {
			return textView.getTop();
		}
		
		throw new RuntimeException("textview is null");
	}

	public String getTitle() {
		return title;
	}

	public int getLevel() {
		return level;
	}
	
	public void setOnClickListener(OnClickListener onClickListener) {
		this.onClickListener = onClickListener;		
	}
} public class EntryOrderList<T> {
	
	private List<T> list;
	
	private int groupSize;
	
	private int currentPos;
	
	public EntryOrderList(List<T> list, int groupSize) {
		
		this.list = list;
		
		this.groupSize = groupSize;
		
		this.currentPos = 0;
	}
	
	public T getNext() {
		
		if (currentPos < list.size()) {
			return list.get(currentPos);
		}
		
		return null;
	}
	
	public int getCurrentPos() {
		return currentPos;
	}
	
	public int size() {
		return list.size();
	}
	
	public T getEntry(int idx) {
		return list.get(idx);
	}

	public void currentPositionOk() {		
		currentPos++;
	}
	
	public void currentPositionBad() {
		
		if (currentPos >= list.size()) {
			return;
		}
		
		T currentPosT = list.get(currentPos);
		
		int nextPosition = currentPos + groupSize;
		
		if (nextPosition > list.size()) {
			nextPosition = list.size();
		}
		
		list.add(nextPosition, currentPosT);
		
		currentPos++;
	}
	
	public String toString() {
		
		StringBuffer sb = new StringBuffer();
		
		for (int idx = 0; idx < list.size(); ++idx) {
			
			if (idx == currentPos) {
				sb.append("* ");
			}
			
			if (idx == currentPos + groupSize) {
				sb.append("| ");
			}
			
			sb.append(list.get(idx));
			
			if (idx != list.size() - 1) {
				sb.append(" ");
			}
		}
		
		return sb.toString();		
	}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import pl.idedyk.android.japaneselearnhelper.JapaneseAndroidLearnHelperApplication;
import pl.idedyk.android.japaneselearnhelper.MenuShorterHelper;
import pl.idedyk.android.japaneselearnhelper.R;
import pl.idedyk.android.japaneselearnhelper.config.ConfigManager.KanaTestConfig;
import pl.idedyk.android.japaneselearnhelper.context.JapaneseAndroidLearnHelperKanaTestContext;
import pl.idedyk.android.japaneselearnhelper.context.JapaneseAndroidLearnHelperKanaTestContext.RangeTest;
import pl.idedyk.android.japaneselearnhelper.context.JapaneseAndroidLearnHelperKanaTestContext.TestMode1;
import pl.idedyk.android.japaneselearnhelper.context.JapaneseAndroidLearnHelperKanaTestContext.TestMode2;
import pl.idedyk.android.japaneselearnhelper.problem.ReportProblem;
import pl.idedyk.android.japaneselearnhelper.screen.Button;
import pl.idedyk.android.japaneselearnhelper.screen.IScreenItem;
import pl.idedyk.android.japaneselearnhelper.screen.StringValue;
import pl.idedyk.android.japaneselearnhelper.screen.TableLayout;
import pl.idedyk.android.japaneselearnhelper.screen.TableRow;
import pl.idedyk.android.japaneselearnhelper.screen.TitleItem;
import pl.idedyk.android.japaneselearnhelper.utils.EntryOrderList;
import pl.idedyk.japanese.dictionary.api.dto.KanaEntry;
import pl.idedyk.japanese.dictionary.api.dto.KanaEntry.KanaGroup;
import pl.idedyk.japanese.dictionary.api.tools.KanaHelper;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.Toast;
package pl.idedyk.android.japaneselearnhelper.kana;



public class KanaTest extends Activity {

	final int max_x = 4;
	final int max_y = 4;

	private StringValue charTest;

	private StringValue position;

	private Button[][] chooseButtons;

	private TitleItem answerTitleItem;

	//private EditText inputAnswerEditText;

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);

		MenuShorterHelper.onCreateOptionsMenu(menu);

		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);

		return MenuShorterHelper.onOptionsItemSelected(item, getApplicationContext(), this);
	}

	@Override
	public void onBackPressed() {

		DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
					case DialogInterface.BUTTON_POSITIVE:

						finish();

						break;

					case DialogInterface.BUTTON_NEGATIVE:

						// noop

						break;
				}
			}
		};

		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		builder.setMessage(getString(R.string.kana_test_quit_question))
				.setPositiveButton(getString(R.string.kana_test_quit_question_yes), dialogClickListener)
				.setNegativeButton(getString(R.string.kana_test_quit_question_no), dialogClickListener).show();
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);

		JapaneseAndroidLearnHelperApplication.getInstance().setContentViewAndTheme(this, R.layout.kana_test);

		JapaneseAndroidLearnHelperApplication.getInstance().logScreen(this, getString(R.string.logs_kana_test));

		generateDatas();

		LinearLayout mainLayout = (LinearLayout) findViewById(R.id.kana_test_main_layout);
		LinearLayout answerLayout = (LinearLayout) findViewById(R.id.kana_test_answer_layout);

		final List<IScreenItem> screenMainItems = createMainScreenTest();
		final List<IScreenItem> screenAnswerItems = createAnswerScreenTest();

		fillLayout(screenMainItems, mainLayout);
		fillLayout(screenAnswerItems, answerLayout);

		fillScreenValue();

		/*
		android.widget.Button reportProblemButton = (android.widget.Button) findViewById(R.id.kana_test_report_problem_button);

		reportProblemButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View view) {

				StringBuffer detailsSb = new StringBuffer();

				for (IScreenItem currentScreenItem : screenMainItems) {
					detailsSb.append(currentScreenItem.toString()).append("\n\n");
				}

				for (IScreenItem currentScreenItem : screenAnswerItems) {
					detailsSb.append(currentScreenItem.toString()).append("\n\n");
				}

				String chooseEmailClientTitle = getString(R.string.choose_email_client);

				String mailSubject = getString(R.string.kana_test_report_problem_email_subject);

				String mailBody = getString(R.string.kana_test_report_problem_email_body, detailsSb.toString());

				String versionName = "";
				int versionCode = 0;

				try {
					PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);

					versionName = packageInfo.versionName;
					versionCode = packageInfo.versionCode;

				} catch (NameNotFoundException e) {
				}

				Intent reportProblemIntent = ReportProblem.createReportProblemIntent(mailSubject, mailBody.toString(),
						versionName, versionCode);

				startActivity(Intent.createChooser(reportProblemIntent, chooseEmailClientTitle));
			}
		});
		*/
	}

	private void generateDatas() {

		JapaneseAndroidLearnHelperKanaTestContext kanaTestContext = JapaneseAndroidLearnHelperApplication.getInstance()
				.getContext().getKanaTestContext();

		if (kanaTestContext.isInitialized() == true) {
			return;
		}

		KanaTestConfig kanaTestConfig = JapaneseAndroidLearnHelperApplication.getInstance().getConfigManager(this)
				.getKanaTestConfig();

		List<KanaEntry> allKanaEntries = null;

		RangeTest rangeTest = kanaTestConfig.getRangeTest();