//------------------------------------------------------------------------------
/** @file    	ux_gui.C
    @brief   	GUI 처리 라이브러리
    @author  	유영창 bmfrog2@gmail.com
    @date 		2009년 1월 17일
	@license
*///----------------------------------------------------------------------------

#include <stdio.h>
#include <string.h>

#include <sys/poll.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <linux/input.h>
#include <linux/limits.h>				// PATH_MAX
#include <fcntl.h>                      // O_RDWR , O_NOCTTY 등의 상수 정의
#include <time.h>

#include <linux/kdev_t.h>				// MKDEV

#include <sys/types.h>
#include <sys/un.h>
#include <termios.h>

#include <pollmng.h>

#include <sys/stat.h>

#include <ix.h>
#include <ux_gui.h>

//------------------------------------------------------------------------------
/** @brief	GUI 처리에 필요한 라이브러리를 초기화 한다.
    @param  exit_flag : 초기화 실패시 프로그램 종료 여부  , 1 이면 프로그램 종료
    @return
    @remark 없음
*///----------------------------------------------------------------------------
int ux_gui_lib_init( int exit_flag )
{

	return 0;

end_label:
	if( exit_flag ) exit(0);
	return -1;
}


#define MAX_COLOR_ITEMS             32			//128
#define MAX_MAP_AREA                32			//1024
#define MAP_AREA_COLOR               0
#define MAP_AREA_LEFT                1
#define MAP_AREA_TOP                 2
#define MAP_AREA_RIGHT               3
#define MAP_AREA_BOTTOM              4
#define MAP_AREA_TYPE              	 5
#define MAP_AREA_LAST             	 6

#define MAP_AREA_TYPE_NONE           0
#define MAP_AREA_TYPE_BUTTON         1

static color_t 	map_colors[MAX_COLOR_ITEMS];
static int 		map_colors_count = 0;

static int 		map_areas[MAX_MAP_AREA][MAP_AREA_LAST];
static int 		map_areas_count = 0;

static bmp_t   	*map_bmp_front 	= NULL;
static bmp_t   	*map_bmp_back 	= NULL;
static bmp_t   	*map_bmp_mask 	= NULL;

static dc_t		*map_dc         = NULL;
static int 		map_last_x     = 0;
static int 		map_last_y     = 0;


//------------------------------------------------------------------------------
/** @brief	전경 그림을 읽어 온다.
    @param 	fileaname : 비트맵 파일명
    @return	정상 0
    @return	실패 -1
    @remark
*///----------------------------------------------------------------------------
int 	ux_gui_screen_map_load_front_bitmap( char *filename )
{
	if( map_bmp_front != NULL ) gx_bmp_close( map_bmp_front );
	map_bmp_front = gx_bmp_open( filename );
	if( map_bmp_front == NULL ) return -1;
	return 0;
}

//--------------------------------------------------------------
// 설명 : 배경 그림을 읽어 온다.
// 매계 : fileaname : 비트맵 파일명
// 반환 : 정상 0 , 실패 -1
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int 	ux_gui_screen_map_load_back_bitmap( char *filename )
{
	if( map_bmp_back != NULL ) gx_bmp_close( map_bmp_back );
	map_bmp_back = gx_bmp_open( filename );
	if( map_bmp_back == NULL ) return -1;
	return 0;
}

//--------------------------------------------------------------
// 설명 : 마스크 그림을 읽어 온다.
// 매계 : fileaname : 비트맵 파일명
// 반환 : 정상 0 , 실패 -1
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int 	ux_gui_screen_map_load_mask_bitmap( char *filename )
{
	if( map_bmp_mask != NULL ) gx_bmp_close( map_bmp_mask );
	map_bmp_mask = gx_bmp_open( filename );
	if( map_bmp_mask == NULL ) return -1;
	return 0;
}

//--------------------------------------------------------------
// 설명 : GUI 스크린 맵을 처리 하는 파일을 읽어 초기화 한다.
// 매계 : exit_flag 초기화 실패시 프로그램 종료 여부
//        1 이면 프로그램 종료
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_load( char *filename )
{
	FILE *fp;
	char readbuff[256];
	char *str;
	int  ret;
	int  index, r,g,b;
	int  left, top,right,bottom;

	memset( map_colors, 0, sizeof( map_colors ) );
	map_colors_count = 0;

	memset( map_areas, 0, sizeof(map_areas) );
	map_areas_count = 0;


	ret = 0;
	fp = fopen( filename,"r" );
	if( fp == NULL ) return -1;

	printf( "OK GOOD LOAD MAP FILE [%s]\n", filename );
	while( !feof( fp ) )
	{
		memset( readbuff,0,sizeof( readbuff ) );
		fgets( readbuff, sizeof( readbuff ) -1, fp );
		str = readbuff;
		while( *str )
		{
			if( *str == 0x0A || *str == 0x0D ) *str = 0;
			str++;
		}

		if( readbuff[0] == 'E' && readbuff[1] == 'D' ) break;		// 파일 끝 명령 이면 처리 종료
		if( readbuff[0] == 'R' && readbuff[1] == 'M' ) continue;	// remark 명령이면 무시

		printf( "[%s]\n", readbuff );								// 디버그로 표시

		// 그림 파일 읽기 요청이면 이에 대한 처리
		if( readbuff[0] == 'B' )
		{
			switch( readbuff[1] )
			{
			case 'F' : ret = ux_gui_screen_map_load_front_bitmap( &readbuff[3] ); break;
			case 'B' : ret = ux_gui_screen_map_load_back_bitmap	( &readbuff[3] ); break;
			case 'M' : ret = ux_gui_screen_map_load_mask_bitmap	( &readbuff[3] ); break;
			}

			if( ret < 0 ) return ret;
			continue;
		}

		// 색 정보 처리
		if( readbuff[0] == 'C' && readbuff[1] == 'M' )
		{
			sscanf( &readbuff[3], "%d,%d,%d,%d", &index, &r,&g,&b );
			if( index < MAX_COLOR_ITEMS )
			{
				if( map_colors_count < ( index + 1 ) ) map_colors_count = index + 1;
	    		map_colors[ index ].red 	= r;
	    		map_colors[ index ].green 	= g;
	    		map_colors[ index ].blue 	= b;
			}
			continue;
		}
		// 영역 정보 처리
		if( readbuff[0] == 'A' && readbuff[1] == 'R' )
		{
			sscanf( &readbuff[3], "%d,%d,%d,%d,%d", &index, &left,&top,&right, &bottom );
			if( map_areas_count < MAX_MAP_AREA )
			{
				if( map_colors_count < ( index + 1 ) ) map_colors_count = index + 1;
	    		map_areas[ map_areas_count ][MAP_AREA_COLOR ] = index;
//dprintf("ux_gui_screen_map_load : map_areas_count = %d\n", map_areas_count);

	    		map_areas[ map_areas_count ][MAP_AREA_LEFT  ] = left;
	    		map_areas[ map_areas_count ][MAP_AREA_TOP   ] = top;
	    		map_areas[ map_areas_count ][MAP_AREA_RIGHT ] = right;
	    		map_areas[ map_areas_count ][MAP_AREA_BOTTOM] = bottom;
	    		map_areas[ map_areas_count ][MAP_AREA_TYPE  ] = MAP_AREA_TYPE_NONE;

	    		map_areas_count++;
			}
			continue;
		}

	}

	fclose( fp );

	return 0;
}


//--------------------------------------------------------------
// 설명 : GUI 스크린 맵을 처리 하는 파일을 읽어 초기화 한다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_set_dc( dc_t	*dc )
{
	map_dc = dc;
	return 0;
}

//--------------------------------------------------------------
// 설명 : 전경 화면을 그린다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_draw_front( void )
{
	gx_bitblt( map_dc, 0, 0, (dc_t *)map_bmp_front, 0, 0, map_bmp_front->width-1, map_bmp_front->height-1);
	return 0;
}

//--------------------------------------------------------------
// 설명 : 이벤트 데이터를 넘겨 사전 처리 한다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_put_ie_event( ie_event_t *event_data )
{
	// 마우스 좌표를 구한다.
	switch(event_data->type)
	{
	case IE_MOUSE_DOWN	:
	case IE_MOUSE_UP 	:
	case IE_MOUSE_MOVE 	:	map_last_x = event_data->data.mouse.x;
							map_last_y = event_data->data.mouse.y;
							break;
	}

	return 0;

}

//--------------------------------------------------------------
// 설명 : 영역 인덱스를 구한다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_get_area( void )
{
    color_t  	color;
	int			lp;

    gx_get_pixel( map_bmp_mask, map_last_x, map_last_y, &color );

    for( lp = 0; lp < map_areas_count; lp++ )
    {
    	//dprintf( "index = %03d %03d:%03d %03d:%03d %03d:%03d\n", lp,
		//		map_colors[lp].red		,color.red 	,
		//		map_colors[lp].green	,color.green,
		//		map_colors[lp].blue		,color.blue );

		if( map_colors[lp].red		!= color.red 	) continue;
		if( map_colors[lp].green	!= color.green 	) continue;
		if( map_colors[lp].blue		!= color.blue  	) continue;

		//dprintf( "OK PASS\n" );


		return lp;
    }

	//dprintf( "NO FOUND\n" );
    return -1;

}

//--------------------------------------------------------------
// 설명 : 전경 영역을 그린다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_draw_area_front	( int area_index )
{
	int lp;
	int x1, x2, y1,y2;

	for( lp = 0; lp < map_areas_count; lp++ )
	{
		if( map_areas[ lp ][MAP_AREA_COLOR ] != area_index ) continue;

	    x1 = map_areas[ lp ][MAP_AREA_LEFT  ];
	    y1 = map_areas[ lp ][MAP_AREA_TOP   ];
	    x2 = map_areas[ lp ][MAP_AREA_RIGHT ];
	    y2 = map_areas[ lp ][MAP_AREA_BOTTOM];

	    gx_bitblt( map_dc, x1, y1, (dc_t *)map_bmp_front, x1, y1, x2-x1, y2-y1 );

	}
	return 0;
}


//------------------------------------------------------------------------------
/** @brief	배경 영역을 그린다.
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_draw_area_back	( int area_index )
{
	int lp;
	int x1, x2, y1,y2;

	for( lp = 0; lp < map_areas_count; lp++ )
	{
		if( map_areas[ lp ][MAP_AREA_COLOR ] != area_index ) continue;

	    x1 = map_areas[ lp ][MAP_AREA_LEFT  ];
	    y1 = map_areas[ lp ][MAP_AREA_TOP   ];
	    x2 = map_areas[ lp ][MAP_AREA_RIGHT ];
	    y2 = map_areas[ lp ][MAP_AREA_BOTTOM];

	    gx_bitblt( map_dc, x1, y1, (dc_t *)map_bmp_back, x1, y1, x2-x1, y2-y1 );
	}
	return 0;
}

//------------------------------------------------------------------------------
/** @brief	스크립 맵 관리자에게  버튼 영역임을 표기 한다.
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_mark_button( int area_index )
{
	int lp;
	int x1, x2, y1,y2;

	for( lp = 0; lp < map_areas_count; lp++ )
	{
		if( map_areas[ lp ][MAP_AREA_COLOR ] != area_index ) continue;
	    map_areas[lp][MAP_AREA_TYPE] = MAP_AREA_TYPE_BUTTON;
	}
	return 0;
}

//------------------------------------------------------------------------------
/** @brief	버튼이 다운된 모습을 그린다.
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_draw_button_down( int area_index )
{
	int lp;
	int x1, x2, y1,y2;

//dprintf("ux_gui_screen_map_draw_button_down : area_index = %d\n", area_index);

	for( lp = 0; lp < map_areas_count; lp++ )
	{
		if( map_areas[ lp ][MAP_AREA_COLOR  ] != area_index 			) continue;
		if( map_areas[ lp ][MAP_AREA_TYPE ] != MAP_AREA_TYPE_BUTTON 	) continue;
//dprintf("ux_gui_screen_map_draw_button_down : area_index_forloop = %d\n", map_areas[ lp ][MAP_AREA_COLOR  ]);

	    x1 = map_areas[ lp ][MAP_AREA_LEFT  ];
	    y1 = map_areas[ lp ][MAP_AREA_TOP   ];
	    x2 = map_areas[ lp ][MAP_AREA_RIGHT ];
	    y2 = map_areas[ lp ][MAP_AREA_BOTTOM];

	    gx_bitblt( map_dc, x1, y1, (dc_t *)map_bmp_back, x1, y1, x2-x1, y2-y1 );
	}
	return 0;
}

//--------------------------------------------------------------
// 설명 : 버튼이 msec 대기후 업된 모습을 그린다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_draw_button_up	( int area_index , int msec_delay )
{

	int lp;
	int x1, x2, y1,y2;
//dprintf("ux_gui_screen_map_draw_button_up : area_index = %d\n", area_index);

	// 대기 처리
	for( lp = 0; lp < map_areas_count; lp++ )
	{
		if( map_areas[ lp ][MAP_AREA_COLOR ] != area_index ) continue;
		if( map_areas[ lp ][MAP_AREA_TYPE ] != MAP_AREA_TYPE_BUTTON 	) continue;
		usleep( msec_delay );
		break;
	}

	// 표출 처리
	for( lp = 0; lp < map_areas_count; lp++ )
	{
		if( map_areas[ lp ][MAP_AREA_COLOR ] != area_index ) continue;
		if( map_areas[ lp ][MAP_AREA_TYPE ] != MAP_AREA_TYPE_BUTTON 	) continue;

//dprintf("ux_gui_screen_map_draw_button_up : area_index_forloop = %d\n", map_areas[ lp ][MAP_AREA_COLOR  ]);

	    x1 = map_areas[ lp ][MAP_AREA_LEFT  ];
	    y1 = map_areas[ lp ][MAP_AREA_TOP   ];
	    x2 = map_areas[ lp ][MAP_AREA_RIGHT ];
	    y2 = map_areas[ lp ][MAP_AREA_BOTTOM];

	    gx_bitblt( map_dc, x1, y1, (dc_t *)map_bmp_front, x1, y1, x2-x1, y2-y1 );
	}
	return 0;
}


//--------------------------------------------------------------
// 설명 : 마우스 위치를 얻는다.
//--------------------------------------------------------------
//------------------------------------------------------------------------------
/** @brief
    @param
    @return
    @remark
*///----------------------------------------------------------------------------
int ux_gui_screen_map_get_mouse_pos( int *x, int *y )
{
	*x = map_last_x;
	*y = map_last_y;

	return 0;
}