/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <samplenativeimeui.h>
#include <dlog.h>
#include <app_i18n.h>

#define SAMPLE_IME_MAIN_LABEL_FONT "Tizen:style=Regular"
#define SAMPLE_IME_SUB_LABEL_FONT "Tizen:style=Regular"
#define SAMPLE_IME_MAIN_LABEL_SIZE 45
#define SAMPLE_IME_SUB_LABEL_SIZE 23
#define SAMPLE_IME_SYMBOL_LABEL_SIZE 35
#define SAMPLE_IME_SPACE_LABEL_SIZE 24
#define SAMPLE_IME_ENTER_LABEL_SIZE 30
#define SAMPLE_IME_MAGNIFIER_WIN_WIDTH 88
#define SAMPLE_IME_MAGNIFIER_WIN_HEIGHT 108
#define SAMPLE_IME_MAGNIFIER_LABEL_SIZE 60
#define SAMPLE_IME_MAGNIFIER_WIN_GAP 14

extern char *g_system_language;
extern IMEDisplayMode g_current_ime_display_mode;
/* main window bg, magnifier window, magnifier label for both portrait and landscape */
static Evas_Object *g_keyboard_bg[IME_DISPLAY_MODE_MAX] = {NULL};
static Evas_Object *g_magnifier_win[IME_DISPLAY_MODE_MAX] = {NULL};
static Evas_Object *g_magnifier_label[IME_DISPLAY_MODE_MAX] = {NULL};

static IMEKeyEventCallBack *g_key_event_cb = NULL;
static const char *g_shift_state_signal[IME_SHIFT_STATE_MAX] = {"shift,off", "shift,on", "shift,lock"};

/* when screen rotates, there are different offset under different rotation degree */
static int g_screen_rotation_degree = 0;

void sample_native_ime_set_screen_rotation_degree(int degree)
{
	g_screen_rotation_degree = degree;
}

/**
 * @brief register callback event
 *
 * @param callback the callback functions
 *
 * @return the register result, success or not
 */
Eina_Bool sample_native_ime_set_key_events_callback(IMEKeyEventCallBack *callback)
{
	if (NULL == callback)
		return EINA_FALSE;
	else
		g_key_event_cb = callback;
	return EINA_TRUE;
}

/**
 * @brief key down callback function,
 *        which will call the register callback event in IMEKeyEventCallBack
 *
 * @param data the pointer of data
 * @param obj the pointer of Evas_Object
 * @param emission the emission string
 * @param source the source string
 *
 */
static void sample_native_ime_key_down_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
{
	/* key down callback */
	IMEKeyProperty *key_property = (IMEKeyProperty *)data;
	if (g_key_event_cb)
		g_key_event_cb->key_down_cb(key_property, g_key_event_cb->key_down_data);
}

/**
 * @brief key up callback function,
 *        which will call the register callback event in IMEKeyEventCallBack
 *
 * @param data the pointer of data
 * @param obj the pointer of Evas_Object
 * @param emission the emission string
 * @param source the source string
 *
 */
static void sample_native_ime_key_up_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
{
	/* key up callback */
	IMEKeyProperty *key_property = (IMEKeyProperty *)data;
	if (g_key_event_cb)
		g_key_event_cb->key_up_cb(key_property, g_key_event_cb->key_up_data);
}

/**
 * @brief key long press callback function,
 *        which will call the register callback event
 *
 * @param data the pointer of data
 * @param obj the pointer of Evas_Object
 * @param emission the emission string
 * @param source the source string
 *
 */
static void sample_native_ime_key_long_press_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
{
	/* key long press callback */
	IMEKeyProperty *key_property = (IMEKeyProperty *)data;
	if (g_key_event_cb)
		g_key_event_cb->key_long_press_cb(key_property, g_key_event_cb->key_long_press_data);
}

/**
 * @brief create key button for ime keyboard
 *
 * @param main_win the main window for keyboard
 * @param key_property the property for key
 * @param edje_path the path of edje file
 * @param scale_ratio the scale ratio for ui
 * @param shift_state the shift state for keyboard
 *
 * @return the pointer of key object
 */
static Evas_Object *sample_native_ime_button_create(Evas_Object *main_win, IMEKeyProperty *key_property, char *edje_path, double scale_ratio, IMEShiftState shift_state)
{
	if (NULL == main_win)
		return NULL;

	Evas *ev = evas_object_evas_get(main_win);
	Evas_Object *key = edje_object_add(ev);
	evas_object_resize(key, key_property->width * scale_ratio, key_property->height * scale_ratio);
	evas_object_move(key, key_property->x * scale_ratio, key_property->y * scale_ratio);

	/* set key style by different key type, which is describe in samplenativeimeconfig.h */
	if (IME_KEY_TYPE_CHAR == key_property->key_type)
	{
		char period[2] = {'.', 0};
		if ((!strcmp(key_property->key_value[shift_state][0], period)) && (!strcmp(key_property->sub_label[shift_state].label_text, "")))
		{
			edje_object_file_set(key, edje_path, "sample_ime_question_key");
			edje_object_text_class_set(key, "SAMPLE_IME_MAIN_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_MAIN_LABEL_SIZE * scale_ratio);
			edje_object_part_text_set(key, "main_label", key_property->main_label[shift_state].label_text);
		}
		else
		{
			edje_object_file_set(key, edje_path, "sample_ime_key");
			/* set main and sub label for key */
			edje_object_text_class_set(key, "SAMPLE_IME_MAIN_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_MAIN_LABEL_SIZE * scale_ratio);
			edje_object_part_text_set(key, "main_label", key_property->main_label[shift_state].label_text);
			edje_object_text_class_set(key, "SAMPLE_IME_SUB_LABEL_CLASS", SAMPLE_IME_SUB_LABEL_FONT, SAMPLE_IME_SUB_LABEL_SIZE * scale_ratio);
			edje_object_part_text_set(key, "sub_label", key_property->sub_label[shift_state].label_text);
		}
	}
	else if (IME_KEY_TYPE_CONTROL == key_property->key_type)
	{
		/* set style for different control key */
		if (!strcmp(key_property->key_value[shift_state][0], "Shift"))
		{
			edje_object_file_set(key, edje_path, "sample_ime_shift_key");
		}
		else if (!strcmp(key_property->key_value[shift_state][0], "Back"))
		{
			edje_object_file_set(key, edje_path, "sample_ime_back_space_key");
		}
		else if (!strcmp(key_property->key_value[shift_state][0], "Space"))
		{
			edje_object_file_set(key, edje_path, "sample_ime_space_key");
			edje_object_text_class_set(key, "SAMPLE_IME_SPACE_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_SPACE_LABEL_SIZE * scale_ratio);
			edje_object_part_text_set(key, "main_label", key_property->main_label[shift_state].label_text);
		}
		else if (!strcmp(key_property->key_value[shift_state][0], "Enter"))
		{
			edje_object_file_set(key, edje_path, "sample_ime_enter_key");
			edje_object_text_class_set(key, "SAMPLE_IME_MAIN_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_ENTER_LABEL_SIZE * scale_ratio);
		}
	}
	else if (IME_KEY_TYPE_MODECHANGE == key_property->key_type)
	{
		if (!strcmp(key_property->main_label[shift_state].label_text, "?123") || !strcmp(key_property->main_label[shift_state].label_text, "abc") || !strcmp(key_property->main_label[shift_state].label_text, "1/2") || !strcmp(key_property->main_label[shift_state].label_text, "2/2"))
		{
			edje_object_file_set(key, edje_path, "sample_ime_symbol_key");
			edje_object_text_class_set(key, "SAMPLE_IME_SYMBOL_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_SYMBOL_LABEL_SIZE * scale_ratio);
			edje_object_part_text_set(key, "main_label", key_property->main_label[shift_state].label_text);
		}
		if (!strcmp(key_property->main_label[shift_state].label_text, "setting"))
		{
			edje_object_file_set(key, edje_path, "sample_ime_setting_key");
			edje_object_text_class_set(key, "SAMPLE_IME_SUB_LABEL_CLASS", SAMPLE_IME_SUB_LABEL_FONT, SAMPLE_IME_SUB_LABEL_SIZE * scale_ratio);
			edje_object_part_text_set(key, "sub_label", key_property->sub_label[shift_state].label_text);
		}
	}
	else if (IME_KEY_TYPE_STRING == key_property->key_type)
	{
		edje_object_file_set(key, edje_path, "sample_ime_key");
		edje_object_text_class_set(key, "SAMPLE_IME_MAIN_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_MAIN_LABEL_SIZE * scale_ratio);
		edje_object_part_text_set(key, "main_label", key_property->main_label[shift_state].label_text);
		edje_object_text_class_set(key, "SAMPLE_IME_SUB_LABEL_CLASS", SAMPLE_IME_SUB_LABEL_FONT, SAMPLE_IME_SUB_LABEL_SIZE * scale_ratio);
		edje_object_part_text_set(key, "sub_label", key_property->sub_label[shift_state].label_text);
	}
	/* register key event callback */
	edje_object_signal_callback_add(key, "elm,action,press", "", sample_native_ime_key_down_cb, key_property);
	edje_object_signal_callback_add(key, "elm,action,release", "", sample_native_ime_key_up_cb, key_property);
	edje_object_signal_callback_add(key, "elm,action,longpress", "", sample_native_ime_key_long_press_cb, key_property);
	return key;
}

/**
 * @brief create background for window
 *
 * @param main_win the main window of keyboard
 * @param width the width of bg object
 * @param height the height of bg object
 * @param edje_path the path of edje file
 *
 * @return the pointer of bg object
 */
static Evas_Object *sample_native_ime_window_bg_create(Evas_Object *main_win, int width, int height, char *edje_path)
{
	if (NULL == main_win)
		return NULL;

	Evas *ev = evas_object_evas_get(main_win);
	Evas_Object *bg = edje_object_add(ev);
	edje_object_file_set(bg, edje_path, "sample_ime_keyboard_bg");
	evas_object_resize(bg, width, height);
	evas_object_show(bg);
	return bg;
}

/**
 * @brief create magnifier window
 *
 * @param main_win the main window of keyboard
 * @param edje_path the path of edje file
 * @param scale_ratio the scale ration of ui
 *
 * @return the pointer of magnifier window
 */
Evas_Object *sample_native_ime_magnifier_win_create(Evas_Object *main_win, char *edje_path, double scale_ratio)
{
	if (NULL == main_win)
		return NULL;

	/* create magnifier window */
	Evas_Object *magnifier_win = elm_win_add(main_win, "Magnifier", ELM_WIN_UTILITY);
	elm_win_borderless_set(magnifier_win, EINA_TRUE);
	elm_win_alpha_set(magnifier_win, EINA_TRUE);
	elm_win_title_set(magnifier_win, "Keyboard Magnifier Window");
	elm_win_prop_focus_skip_set(magnifier_win, EINA_TRUE);
	evas_object_resize(magnifier_win, SAMPLE_IME_MAGNIFIER_WIN_WIDTH * scale_ratio, SAMPLE_IME_MAGNIFIER_WIN_HEIGHT * scale_ratio);

	/* set rotation degree for magnifier window */
	int rotations[4] = {0, 90, 180, 270};
	elm_win_wm_rotation_available_rotations_set(magnifier_win, rotations, 4);

	/* set label style for magnifier window */
	Evas *ev = evas_object_evas_get(magnifier_win);
	g_magnifier_label[g_current_ime_display_mode] = edje_object_add(ev);
	edje_object_file_set(g_magnifier_label[g_current_ime_display_mode], edje_path, "sample_ime_magnifier_label");
	evas_object_resize(g_magnifier_label[g_current_ime_display_mode], SAMPLE_IME_MAGNIFIER_WIN_WIDTH * scale_ratio, SAMPLE_IME_MAGNIFIER_WIN_HEIGHT * scale_ratio);
	evas_object_move(g_magnifier_label[g_current_ime_display_mode], 0, 0);
	evas_object_show(g_magnifier_label[g_current_ime_display_mode]);

	return magnifier_win;
}

/**
 * @brief show magnifier window,
 *        calculate the coordinate for different rotation degree
 *
 * @param x the x coordinate of magnifier window
 * @param y the y coordinate of magnifier window
 * @param width the width of magnifier window
 * @param height the height of magnifier window
 * @param label_text the label text string
 * @param scale_ratio the scale ratio of ui
 */
void sample_native_ime_magnifier_win_show(int x, int y, int width, int height, const char *label_text, double scale_ratio)
{
	int rotation_x = 0;
	int rotation_y = 0;
	if (NULL != g_magnifier_win[g_current_ime_display_mode])
	{
		edje_object_text_class_set(g_magnifier_label[g_current_ime_display_mode], "SAMPLE_IME_MAIN_LABEL_CLASS", SAMPLE_IME_MAIN_LABEL_FONT, SAMPLE_IME_MAGNIFIER_LABEL_SIZE * scale_ratio);
		edje_object_part_text_set(g_magnifier_label[g_current_ime_display_mode], "main_label", label_text);

		/* calculate coordinate for magnifier window after rotation */
		switch (g_screen_rotation_degree)
		{
		case 0:
		{
			rotation_x = (x - (SAMPLE_IME_MAGNIFIER_WIN_WIDTH - width) / 2) * scale_ratio;
			rotation_y = (SAMPLE_NATIVE_IME_RESOLUTION_H - SAMPLE_NATIVE_IME_IME_HEIGHT_P - SAMPLE_IME_MAGNIFIER_WIN_HEIGHT - SAMPLE_IME_MAGNIFIER_WIN_GAP + y) * scale_ratio;
			break;
		}
		case 90:
		{
			rotation_x = (SAMPLE_NATIVE_IME_RESOLUTION_W - SAMPLE_NATIVE_IME_IME_HEIGHT_L - SAMPLE_IME_MAGNIFIER_WIN_GAP - SAMPLE_IME_MAGNIFIER_WIN_HEIGHT + y) * scale_ratio;
			rotation_y = (SAMPLE_NATIVE_IME_RESOLUTION_H - SAMPLE_IME_MAGNIFIER_WIN_WIDTH - x + (SAMPLE_IME_MAGNIFIER_WIN_WIDTH - width) / 2) * scale_ratio;
			break;
		}
		case 180:
		{
			rotation_x = (SAMPLE_NATIVE_IME_RESOLUTION_W - SAMPLE_IME_MAGNIFIER_WIN_WIDTH - x) * scale_ratio;
			rotation_y = (SAMPLE_NATIVE_IME_IME_HEIGHT_P + SAMPLE_IME_MAGNIFIER_WIN_GAP - y) * scale_ratio;
			break;
		}
		case 270:
		{
			rotation_x = (SAMPLE_NATIVE_IME_IME_HEIGHT_L + SAMPLE_IME_MAGNIFIER_WIN_GAP - y) * scale_ratio;
			rotation_y = (x - (SAMPLE_IME_MAGNIFIER_WIN_WIDTH - width) / 2) * scale_ratio;
			break;
		}
		default:
		{
			dlog_print(DLOG_DEBUG, LOG_TAG, "Wrong rotation angle: %d", g_screen_rotation_degree);
			break;
		}
		}
		evas_object_move(g_magnifier_win[g_current_ime_display_mode], rotation_x, rotation_y);
		elm_win_raise(g_magnifier_win[g_current_ime_display_mode]);
		evas_object_show(g_magnifier_win[g_current_ime_display_mode]);
	}
}
/**
 * @brief hide magnifier window
 *
 * @param
 *
 * @return
 */
void sample_native_ime_magnifier_win_hide()
{
	if (NULL != g_magnifier_win[g_current_ime_display_mode])
		evas_object_hide(g_magnifier_win[g_current_ime_display_mode]);
}

/**
 * @brief create different layout for ime
 *
 * @param main_win the main window of keyboard
 * @param layout the pointer of layout
 * @param edje_path the path of edje file
 * @param scale_ratio the scale ratio of ui
 * @param shift_state the shift state of keyboard
 *
 * @return create ime layout result, success or not
 */
int sample_native_ime_layout_create(Evas_Object *main_win, IMELayout *layout, char *edje_path, double scale_ratio, IMEShiftState shift_state)
{
	if ((NULL == main_win) || (NULL == layout))
		return -1;

	/* initial bg */
	if (NULL == g_keyboard_bg[layout->display_mode])
		g_keyboard_bg[layout->display_mode] = sample_native_ime_window_bg_create(main_win, layout->width * scale_ratio, layout->height * scale_ratio, edje_path);

	/* initial magnifier window */
	if (NULL == g_magnifier_win[layout->display_mode])
		g_magnifier_win[layout->display_mode] = sample_native_ime_magnifier_win_create(main_win, edje_path, scale_ratio);

	int i = 0;
	int j = 0;
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			if (NULL == layout->button_key[i][j].key_obj)
				layout->button_key[i][j].key_obj = sample_native_ime_button_create(main_win, &(layout->button_key[i][j]), edje_path, scale_ratio, shift_state);
		}
	}

	return 0;
}

/**
 * @brief ime show layout
 *
 * @param layout the pointer of layout
 *
 * @return ime layout show result, success or not
 */
int sample_native_ime_layout_show(IMELayout *layout)
{
	if (NULL == layout)
		return -1;

	/* show keyboard background on different display mode */
	if (NULL != g_keyboard_bg[g_current_ime_display_mode])
		evas_object_show(g_keyboard_bg[g_current_ime_display_mode]);

	int i = 0;
	int j = 0;
	/* show all keys of layout */
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			if (NULL != layout->button_key[i][j].key_obj)
				evas_object_show((Evas_Object *)(layout->button_key[i][j].key_obj));
		}
	}

	return 0;
}

/**
 * @brief ime layout hide
 *
 * @param layout the pointer of layout
 *
 * @return hide layout result, success of not
 */
int sample_native_ime_layout_hide(IMELayout *layout)
{
	if (NULL == layout)
		return -1;

	/* hide window background */
	if (NULL != g_keyboard_bg[g_current_ime_display_mode])
		evas_object_hide(g_keyboard_bg[g_current_ime_display_mode]);

	int i = 0;
	int j = 0;
	/* hide all keys of layout */
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			if (NULL != layout->button_key[i][j].key_obj)
				evas_object_hide((Evas_Object *)(layout->button_key[i][j].key_obj));
		}
	}

	return 0;
}

/**
 * @brief set disable status for return key
 *
 * @param layout the pointer of layout
 * @param disabled the disabled status of return key
 *
 * @return set return key result, success or not
 */
Eina_Bool sample_native_ime_set_return_disable(IMELayout *layout, Eina_Bool disabled)
{
	Evas_Object *enter_btn = NULL;
	int i = 0;
	int j = 0;
	/* get the return key */
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			IMEKeyProperty *key_property = &(layout->button_key[i][j]);
			if (!strcmp(key_property->key_value[0][0], "Enter"))
				enter_btn = (Evas_Object *)(key_property->key_obj);
		}
	}

	const char *buf = edje_object_part_text_get(enter_btn, "main_label");
	/* check the return key contain text or image */
	if ((buf != NULL) && (buf[0] != '\0'))
	{
		if (disabled)
			edje_object_signal_emit(enter_btn, "elm,state,disabled", "main_label");
		else
			edje_object_signal_emit(enter_btn, "elm,state,default", "main_label");
	}
	else
	{
		if (disabled)
			edje_object_signal_emit(enter_btn, "elm,state,disabled", "image");
		else
			edje_object_signal_emit(enter_btn, "elm,state,default", "image");
	}
	return EINA_TRUE;
}

/**
 * @brief set type for return key
 *
 * @param layout the pointer of layout
 * @param type the type of return key
 *
 * @return set return key type result, success or not
 */
Eina_Bool sample_native_ime_set_return_type(IMELayout *layout, Ecore_IMF_Input_Panel_Return_Key_Type type)
{
	Evas_Object *enter_btn = NULL;
	int i = 0;
	int j = 0;
	/* get return key */
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			IMEKeyProperty *key_property = &(layout->button_key[i][j]);
			if (!strcmp(key_property->key_value[0][0], "Enter"))
				enter_btn = (Evas_Object *)(key_property->key_obj);
		}
	}

	/* set return key by type */
	if ((type > 0) && (type < 9))
	{
		if (g_system_language != NULL && strcmp(g_system_language, "ko_KR.UTF-8") == 0)
		{
			const char *strType[] = {"IDS_RETURN_KEY_TYPE_DEFAULT", "IDS_RETURN_KEY_TYPE_DONE", "IDS_RETURN_KEY_TYPE_GO", "IDS_RETURN_KEY_TYPE_JOIN", "IDS_RETURN_KEY_TYPE_LOGIN", "IDS_RETURN_KEY_TYPE_NEXT", "IDS_RETURN_KEY_TYPE_SEARCH", "IDS_RETURN_KEY_TYPE_SEND", "IDS_RETURN_KEY_TYPE_SIGNIN"};
			edje_object_part_text_set(enter_btn, "main_label", i18n_get_text(strType[type]));
			edje_object_signal_emit(enter_btn, "enter,hide", "image");
		}
		else
		{
			const char *strType[] = {"Default", "Done", "Go", "Join", "Login", "Next", "Search", "Send", "Sign in"};
			edje_object_part_text_set(enter_btn, "main_label", strType[type]);
			edje_object_signal_emit(enter_btn, "enter,hide", "image");
		}
	}
	else
	{
		edje_object_part_text_set(enter_btn, "main_label", "");
		edje_object_signal_emit(enter_btn, "enter,show", "image");
	}

	return EINA_TRUE;
}

/**
 * @brief update shift state for keyboard
 *
 * @param layout the pointer of layout
 * @param shift_state the shift state of key board
 *
 * @return update shift state result, success or not
 */
Eina_Bool sample_native_ime_update_shift_state(IMELayout *layout, IMEShiftState shift_state)
{
	if (NULL == layout)
		return EINA_FALSE;

	int i = 0;
	int j = 0;
	/* get shift key */
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			IMEKeyProperty *key_property = &(layout->button_key[i][j]);
			if (!strcmp(key_property->key_value[shift_state][0], "Shift"))
			{
				/* emit signal to update shift state */
				edje_object_signal_emit(key_property->key_obj, g_shift_state_signal[shift_state], "image");
			}
		}
	}
	return EINA_TRUE;
}

/**
 * @brief update key labels
 *
 * @param key_property the pointer of key property
 * @param shift_state the shift state of keyboard
 *
 * @return ime update key result, success or not
 */
static Eina_Bool sample_native_ime_update_key(IMEKeyProperty *key_property, IMEShiftState shift_state)
{
	/* update labels or image for key */
	if ((NULL != key_property) && (NULL != key_property->key_obj))
	{
		if (IME_KEY_TYPE_CHAR == key_property->key_type)
		{
			edje_object_part_text_set(key_property->key_obj, "main_label", key_property->main_label[shift_state].label_text);
			edje_object_part_text_set(key_property->key_obj, "sub_label", key_property->sub_label[shift_state].label_text);
		}
		else if (!strcmp(key_property->key_value[shift_state][0], "Shift"))
		{
			edje_object_signal_emit(key_property->key_obj, g_shift_state_signal[shift_state], "image");
		}
		return EINA_TRUE;
	}
	return EINA_FALSE;
}

/**
 * @brief update layouts
 *
 * @param layout the pointer of layout
 * @param shift_state the shift state of keyboard
 *
 * @return ime update layout result, success or not
 */
Eina_Bool sample_native_ime_update_layout(IMELayout *layout, IMEShiftState shift_state)
{
	if (NULL == layout)
		return EINA_FALSE;

	int i = 0;
	int j = 0;
	/* update all keys in the layout */
	for (i = 0; i < layout->row_number; ++i)
	{
		for (j = 0; j < layout->row_infos[i].key_number; ++j)
		{
			IMEKeyProperty *key_property = &(layout->button_key[i][j]);
			sample_native_ime_update_key(key_property, shift_state);
		}
	}

	return EINA_TRUE;
}
