#include "../bootpack.h"

namespace systemtask {
	int cnt_timeout = 0;
	volatile int load_count = 0; // 負荷計数用
}

using namespace systemtask;


void system::task_idle() {
	Task* task = g_taskctl->get_current_task();
	queue<Message>* fifo = task->fifo();
	Message* msg = 0;
	Timer* tim = g_timerctl->alloc();
	tim->set_task(task, 1);
	timer_settime(tim, 1);
	for (;;) {
		io_cli();
		if (fifo->size() == 0) {
			//g_taskctl->sleep(task);
			// sleepしないで、10msec全て消費する。
			io_sti();
			continue;
		}
		msg = &fifo->back();
		io_sti();
		if (msg->type == MSG::TYPE::TIMER) {
			load_count++;
			timer_settime(tim, 1);
		}
		fifo->pop();
	}
}

void system::task_keyboard() {
	Task* task = g_taskctl->get_current_task();
	queue<Message>* fifo = task->fifo();
	Message* msg = 0;
	byte data[5] = {0, 0, 0, 0, 0};
	Picture* buffer_back = g_sheet_back->get_buffer();
	char s[256];
	int x, y;
	Timer* tim = g_timerctl->alloc();
	tim->set_task(task, 100);
	for (;;) {
		io_cli();
		if (fifo->size() == 0) {
			g_taskctl->sleep(task);
			io_sti();
			continue;
		}
		msg = &fifo->back();
		io_sti();
		if (msg->type == MSG::TYPE::KEYBOARD) {
			data[4] = data[3];
			data[3] = data[2];
			data[2] = data[1];
			data[1] = data[0];
			data[0] = msg->arg1;
			sprintf(s, "KEY CODE : %02X -> %02X -> %02X -> %02X -> %02X",
				data[0], data[1], data[2], data[3], data[4]);
			buffer_back->box(0, 16, strlen(s) * 8 - 1, 32 - 1, Screen::BACKGROUND_COLOR);
			buffer_back->putstr(0, 16, s, 0xffff);
			g_shtctl->refresh(g_sheet_back, 0, 16, strlen(s) * 8, 32);
			if (data[0] == 0x01) { // ESCキーでリブート
//				pic0_imr << 0xff; // 全割り込み禁止
//				pic1_imr << 0xff;
				Mouse::out(0xf5); // データ送信禁止
				while (task1_fifo->size() > 0) {
					task1_fifo->pop();
				}
				for (y = 0; y < buffer_back->get_ysize(); y++) {
					for (x = 0; x < buffer_back->get_xsize(); x++) {
						g_screen->point(x, y,
							mixC(
								convC_inv(g_screen->get_color(x, y)), 0xa0a0a0, 50, 50
								)
							);
					}
				}
				*dbg << "rebooting system.";
				dbg->flush();
				cnt_timeout = 0;
				timer_settime(tim, 100);
			}
		} else if (msg->type == MSG::TYPE::TIMER) {
			if (msg->arg1 == 100) {
				if (cnt_timeout < 2) {
					sprintf(s, "%d", 2 - cnt_timeout);
					cnt_timeout++;
					timer_settime(tim, 100);
					*dbg << s;
					dbg->flush();
				} else {
					io_cli();
					IO8 KBC(0x64);
					KBC << 0xfe; // reboot
					for (;;) { io_hlt(); }
				}
			}
		}
		fifo->pop();
	}
}

void system::task_mouse() {
	Picture* buffer_back = g_sheet_back->get_buffer();
	// マウスカーソルの位置記憶用変数
	int m_xpos = buffer_back->get_xsize() / 2;
	int m_ypos = buffer_back->get_ysize() / 2;
	int m_xpos_old, m_ypos_old;
	int dm_xpos, dm_ypos; // カーソル移動変化量
	
	bool right_pushed = false;
	bool left_pushed = false;
	bool middle_pushed = false;
	
	Task* task = g_taskctl->get_current_task();
	queue<Message>* fifo = task->fifo();
	Message* msg = 0;
	
	Mouse::enable(task);
	
	// マウスカーソル用シートの生成
	Sheet* sheet_mouse = g_shtctl->alloc(TASK_MOUSE, true);
	sheet_mouse->init(Mouse::XSIZE, Mouse::YSIZE);
	Picture* buffer_mouse = sheet_mouse->get_buffer();
	sheet_mouse->set_invisible_color(0x0001);
	Mouse::init_cursor(buffer_mouse);
	g_shtctl->slide(sheet_mouse, m_xpos, m_ypos);
	g_shtctl->updown(sheet_mouse, 1000);
	
	// ウィンドウがドラッグ状態かどうか
	bool window_drag = false;
	
	Sheet* on_sheet = 0;
	Sheet* active_sheet = get_sheet_taskid(TASK_KERNEL);
	Picture* buf_on_sheet = 0;
	Sheet* sheet_win1 = active_sheet;
	int xpos_on_sheet = 0, ypos_on_sheet = 0;
	Picture* buffer_win1 = sheet_win1->get_buffer();
	
	Sheet* sheet_taskbar = get_sheet_taskid(TASK_TASKBAR);
	Picture* buffer_taskbar = sheet_taskbar->get_buffer();
	Sheet* sheet_dframe = NULL;
	
	
	char s[256];
	
	*dbg << "mouse";

	for (;;) {
		io_cli();
		if (fifo->size() == 0) {
			g_taskctl->sleep(task);
			io_sti();
			continue;
		}
		msg = &fifo->back();
		io_sti();
		if (msg->type == MSG::TYPE::MOUSE) {
			if (Mouse::decode(msg->arg1)) {
				// デコード完了
				m_xpos_old = m_xpos;
				m_ypos_old = m_ypos;
				m_xpos += Mouse::mdec.x;
				m_ypos += Mouse::mdec.y;
				if (m_xpos < 0) { m_xpos = 0; }
				if (m_xpos >= buffer_back->get_xsize()) { m_xpos = buffer_back->get_xsize() - 1; }
				if (m_ypos < 0) { m_ypos = 0; }
				if (m_ypos >= buffer_back->get_ysize()) { m_ypos = buffer_back->get_ysize() - 1; }
				dm_xpos = m_xpos - m_xpos_old;
				dm_ypos = m_ypos - m_ypos_old;
				g_shtctl->slide(sheet_mouse, m_xpos, m_ypos);
				
				if (right_pushed != false && Mouse::mdec.button & 0x02) {
					right_pushed = true;
					
				}
				if (Mouse::mdec.button & 0x04) { middle_pushed = true; }
				
				if (!window_drag) {
					int sid = g_shtctl->get_sheetid(m_xpos, m_ypos);
					on_sheet = g_shtctl->get_sheet(sid);
					buffer_win1->box(10, 55, 10 + 8 * 10 - 1, 55 + 32 - 1, Screen::TASKBAR_COLOR);
					sprintf(s, "%04d, %04d", m_xpos, m_ypos);
					buffer_win1->putstr(10, 55, s, convC(0x555555));
					sprintf(s, "scroll %2d", Mouse::mdec.scroll);
					buffer_win1->putstr(10, 55 + 16, s, convC(0x555555));
					g_shtctl->refresh(sheet_win1, 10, 55, 10 + 8 * 10, 55 + 32);
					
					buffer_win1->box(10, 55 + 16 * 3, 10 + 8 * 9 - 1, 55 + 16 * 4 - 1, Screen::TASKBAR_COLOR);
					sprintf(s, "sid = %03d", sid);
					buffer_win1->putstr(10, 55 + 16 * 3, s, 0x0000);
					g_shtctl->refresh(sheet_win1, 10, 55 + 16 * 3, 10 + 8 * 9, 55 + 16 * 4);
				} else {
					#if DRAG_FRAME == 1
					g_shtctl->slide(sheet_dframe,
						sheet_dframe->get_xpos() + dm_xpos,
						sheet_dframe->get_ypos() + dm_ypos);
					#elif DRAG_FRAME == 2
					g_shtctl->slide_dragframe(sheet_dframe,
						sheet_dframe->get_xpos() + dm_xpos,
						sheet_dframe->get_ypos() + dm_ypos);
					#endif
				}
/*
				sprintf(s, "lcr scroll=%d", Mouse::mdec.scroll);
				if (Mouse::mdec.button & 0x01) { s[0] = 'L'; }
				if (Mouse::mdec.button & 0x02) { s[2] = 'R'; }
				if (Mouse::mdec.button & 0x04) { s[1] = 'C'; }
				buffer_back->box(0, 32, strlen(s) * 8 + 7, 48 - 1, Screen::BACKGROUND_COLOR);
				buffer_back->putstr(0, 32, s, 0xffff);
				g_shtctl->refresh(sheet_back, 0, 32, strlen(s) * 8 + 8, 48);
				
				if (Mouse::mdec.scroll != 0 && (Mouse::mdec.button & 0x04) == 0) {
					g_shtctl->slide(sheet_win1,
						sheet_win1->get_xpos(), sheet_win1->get_ypos() + 16 * 3 * Mouse::mdec.scroll);
				} else if (Mouse::mdec.scroll != 0 && (Mouse::mdec.button & 0x04) != 0) {
					g_shtctl->slide(sheet_win1,
						sheet_win1->get_xpos() + 16 * 3 * Mouse::mdec.scroll, sheet_win1->get_ypos());
				}
*/

				if (left_pushed == false && Mouse::mdec.button & 0x01) {
					// left push
					left_pushed = true;
					buf_on_sheet = on_sheet->get_buffer();
					xpos_on_sheet = on_sheet->get_xpos();
					ypos_on_sheet = on_sheet->get_ypos();
					if (xpos_on_sheet <= m_xpos &&
						m_xpos <= xpos_on_sheet + buf_on_sheet->get_xsize() &&
						ypos_on_sheet <= m_ypos &&
						m_ypos <= ypos_on_sheet + buf_on_sheet->get_ysize())
					{
						if (!on_sheet->fixed()) {
							g_shtctl->updown(on_sheet, 1000);
							if (on_sheet != active_sheet) {
								Window::make(active_sheet, false);
	//							g_shtctl->refresh(active_sheet, 0, 0,
	//								active_sheet->get_buffer()->get_xsize(),
	//								active_sheet->get_buffer()->get_ysize());
								g_shtctl->refresh_winframe(active_sheet);
								active_sheet = on_sheet;
								Window::make(active_sheet, true);
	//							g_shtctl->refresh(active_sheet, 0, 0,
	//								active_sheet->get_buffer()->get_xsize(),
	//								active_sheet->get_buffer()->get_ysize());
								g_shtctl->refresh_winframe(active_sheet);
							}
						}
						if (m_ypos <= ypos_on_sheet + 28 && !on_sheet->fixed())
						{
							// ウィンドウのタイトルバー上でクリック
							window_drag = true;
							sheet_dframe = g_shtctl->alloc();
							#if DRAG_FRAME == 1
							sheet_dframe->init(20, 20);
							#elif DRAG_FRAME == 2
							sheet_dframe->init(
								on_sheet->get_buffer()->get_xsize(), on_sheet->get_buffer()->get_ysize());
							sheet_dframe->set_invisible_color(0x0000);
							#endif
							Picture* buffer_dframe = sheet_dframe->get_buffer();
							
							#if DRAG_FRAME == 1
							buffer_dframe->box(0, 0,
								20 - 1, 20 - 1,
								0x0000);
							buffer_dframe->box(8, 0,
								12 - 1, 20 - 1,
								convC(0xC0C0C0));
							buffer_dframe->box(0, 8,
								20 - 1, 12 - 1,
								convC(0xC0C0C0));
							g_shtctl->slide(sheet_dframe,
								on_sheet->get_xpos() - 10, on_sheet->get_ypos() - 10);
							#elif DRAG_FRAME == 2
							buffer_dframe->box(0, 0,
								buffer_dframe->get_xsize() - 1, buffer_dframe->get_ysize() - 1,
								convC(0xC0C0C0));
							buffer_dframe->box(2, 2,
								buffer_dframe->get_xsize() - 3, buffer_dframe->get_ysize() - 3,
								0x0000);
							g_shtctl->slide_dragframe(sheet_dframe,
								on_sheet->get_xpos(), on_sheet->get_ypos());
							#endif
							g_shtctl->updown(sheet_dframe, 1000);
						} else {
							// タイトルバー以外（しかしウィンドウ上）でクリック
							int to = g_shtctl->get_taskid(on_sheet);
							sprintf(s, "test %d", to);
							*dbg << s;
							g_taskctl->send_message(to,
								Message::create(MSG::TYPE::MOUSE, m_xpos, m_ypos)
							);
						}
					}
				} else if (left_pushed && (Mouse::mdec.button & 0x01) == 0) {
					// left release
					left_pushed = false;
					if (window_drag) {
						g_shtctl->updown(sheet_dframe, -1);
//						g_shtctl->updown(sdf_t, -1);
//						g_shtctl->updown(sdf_b, -1);
//						g_shtctl->updown(sdf_l, -1);
//						g_shtctl->updown(sdf_r, -1);
						#if DRAG_FRAME == 1
						g_shtctl->slide(on_sheet,
							sheet_dframe->get_xpos() + 10, sheet_dframe->get_ypos() + 10);
						#elif DRAG_FRAME == 2
						g_shtctl->slide(on_sheet,
							sheet_dframe->get_xpos(), sheet_dframe->get_ypos());
						#endif
						g_shtctl->free(sheet_dframe);
						window_drag = false;
					}
				}

			}
		}
		fifo->pop();
	}
}

volatile void system::task_taskbar() {
	Picture* buffer_back = g_sheet_back->get_buffer();
	Task* task = g_taskctl->get_current_task();
	queue<Message>* fifo = task->fifo();
	Message* msg = 0;
	
	DateTime date1, date2;
	char s[256];

	Sheet* taskbar = get_sheet_taskid(g_taskctl->get_taskid(task));
	Picture* buffer = taskbar->get_buffer();
	
	box_sht(taskbar, 1, 1, 20 + 8 * 5 - 2, buffer->get_ysize() - 2, convC(0x203050));
	putstr_sht(taskbar, 10, 5, "start", 0xffff, convC(0x203050));
	
	Timer* tim1 = g_timerctl->alloc();
	tim1->set_task(task, 1);
	timer_settime(tim1, 5);
	Timer* tim2 = g_timerctl->alloc();
	tim2->set_task(task, 2);
	timer_settime(tim2, 3);
	
	bool menu_open = false;
	Sheet* m1 = NULL;
	
	for (;;) {
		io_cli();
		if (fifo->size() == 0) {
			g_taskctl->sleep(task);
			io_sti();
			continue;
		}
		msg = &fifo->back();
		io_sti();
		if (msg->type == MSG::TYPE::TIMER) {
			if (msg->arg1 == 1) {
				timer_settime(tim1, 100);
				buffer->box(buffer->get_xsize() - 6 * 12 - 2, 6, buffer->get_xsize() - 3, 17, Screen::TASKBAR_COLOR);
				sprintf(s, "%02d/%02d  %02d:%02d",
					date1.month, date1.day, date1.hour, date1.minute, date1.second);
				buffer->putstr(buffer->get_xsize() - 6 * 12 - 2, 6, s, 0x0000, font_mini);
				g_shtctl->refresh(taskbar, buffer->get_xsize() - 6 * 12 - 2, 6, buffer->get_xsize() - 2, 18);
				date1.second++;
				if (date1.second >= 60) {
					date1.second = 0;
					date1.minute++;
				}
				if (date1.minute >= 60) {
					date1.minute = 0;
					date1.hour++;
				}
				if (date1.hour >= 24) {
					date1.hour = 0;
					date1.day++;
				}
				if ((date1.day > 31 &&
					(date1.month == 1 || date1.month == 3 || date1.month == 5 ||
					date1.month == 7 || date1.month == 8 || date1.month == 10 ||
					date1.month == 12)) ||
					(date1.day > 30 &&
					(date1.month == 4 || date1.month == 6 || date1.month == 9 ||
					date1.month == 11)) ||
					(date1.day > 28 && date1.month == 2))
				{
					date1.day = 0;
					date1.month++;
				}
				if (date1.month > 12) {
					date1.month = 0;
					date1.year++;
				}
			} else if (msg->arg1 == 2) {
				timer_settime(tim2, 6000);
				RTC::read(&date1);
				RTC::read(&date2);
				int i = 0;
				while (date1 != date2 ||
					(date1.second < 0 || date1.second > 60) ||
					(date1.minute < 0 || date1.minute > 59) ||
					(date1.hour < 0 || date1.hour > 24) ||
					(date1.day < 1 || date1.day > 31) ||
					(date1.month < 1 || date1.month > 12) ||
					(date1.year < 1990))
				{
					RTC::read(&date1);
					RTC::read(&date2);
					if (i > 5) { break; }
					i++;
				}
			}
		} else if (msg->type == MSG::TYPE::MOUSE) {
			int xpos = msg->arg1;
			int ypos = msg->arg2;
			sprintf(s, "clicked %04d, %03d", xpos, ypos);
			buffer->box(200, 7, 200 + 8 * 17 - 1, 22, Screen::TASKBAR_COLOR);
			buffer->putstr(200, 7, s, 0x0000);
			g_shtctl->refresh(taskbar, 200, 7, 200 + 8 * 17, 23);
			if (10 <= xpos && xpos < 20 + 8 * 5 && !menu_open) {
				menu_open = true;
				m1 = g_shtctl->alloc(TASK_TASKBAR);
				m1->init(200, 400);
				m1->set_fix(true);
				Picture* b1 = m1->get_buffer();
				b1->box(0, 0, 199, 399, convC(0x556677));
				b1->putstr(10, 10, "start menu", 0xffff);
				g_shtctl->slide(m1, 0, taskbar->get_ypos() - 400);
				g_shtctl->updown(m1, 1000);
			} else if (menu_open) {
				g_shtctl->updown(m1, -1);
				g_shtctl->free(m1);
				menu_open = false;
			}
		}
		fifo->pop();
	}
}

void system::task_b_main() {
	Task* current_task = g_taskctl->get_current_task();
	Sheet* sht = g_shtctl->alloc(g_taskctl->get_taskid(current_task));
	sht->init(300, 200);
	sht->set_invisible_color(0x0001);
	Window::make(sht, false);
	Picture* buf = sht->get_buffer();
	buf->box(3,  29, 300 - 4, 200 - 4, Screen::TASKBAR_COLOR);
	buf->putstr(20, 50, "test", 0x0000);
	buf->putstr(10, 8, "load", 0xffff);
	g_shtctl->updown(sht, 2);
	g_shtctl->slide(sht, 200, 200);
	
	queue<Message>* fifo = current_task->fifo();
	Message msg;
	char s[256], tmp[256];
	Timer* tim = g_timerctl->alloc();
	tim->set_task(g_taskctl->get_current_task(), 1);
	timer_settime(tim, 100);
	int count = 0;
	int percent = 0;
	for (;;) {
		io_cli();
		if (fifo->size() == 0) {
			g_taskctl->sleep(current_task);
			io_sti();
			continue;
		}
		msg = fifo->back();
		fifo->pop();
		io_sti();
		if (msg.type == MSG::TYPE::TIMER) {
			if (msg.arg1 == 1) {
				buf->box(20, 50 + 16 * 1, 20 + 8 * 18 - 1, 50 + 16 * 4 - 1, Screen::TASKBAR_COLOR);
				buf->putstr(20, 50 + 16 * 1, "system idle", 0x0000);
				count = load_count;
				if (count >= 100) { count = 100; }
				if (count < 0) { count = 0; }
				percent = ((1000 - count * 10) * 100) / 1000;
				sprintf(s, "%3u0 msec/sec", count);
				buf->putstr(20, 50 + 16 * 2, s, 0x0000);
				sprintf(s, "cpu %3u %%", percent);
				buf->putstr(20, 50 + 16 * 3, s, 0x0000);
				g_shtctl->refresh(sht, 20, 50 + 16 * 1, 20 + 8 * 18, 50 + 16 * 4);
				load_count = 0;
				timer_settime(tim, 100);
			}
		}
	}
}

