#ifndef SHEET_H_
#define SHEET_H_

namespace system {
	class SheetController;
	
	/*
	 * シート
	 */
	class Sheet {
		// 定数
		static const dword FLAG_UNUSED = 0;
		static const dword FLAG_USED = 1;
		
		Picture pict_;
		dword flags_;
		int xpos_, ypos_, height_;
		color_16 col_inv_; // 透過色
		
		bool mouse_;
		bool fixed_;
		
		void set_mouse(bool mouse) { mouse_ = mouse; }
		bool get_mouse() { return mouse_; }
	public:
		explicit Sheet();
		void init(int xsize, int ysize) { pict_.init(xsize, ysize); }
		
		// 使用マークを付ける
		void use() { flags_ = FLAG_USED; }
		
		// 未使用マークを付ける
		void release() { flags_ = FLAG_UNUSED; }
		
		// 使用中かどうか
		bool used() const { return flags_ == FLAG_USED; }
		
		// 高さを設定する
		void set_height(int height) { height_ = height; }
		
		// 高さを取得する
		int get_height() const { return height_; }
		
		// 画像バッファを取得
		Picture* get_buffer() { return &pict_; }
		
		// 画像バッファを取得
		const Picture* get_buffer() const { return &pict_; }
		
		// 透過色を設定
		void set_invisible_color(color_16 color) { col_inv_ = color; }
		
		// 透過色を取得
		color_16 get_invisible_color() const { return col_inv_; }
		
		// 固定するかどうかを設定
		void set_fix(bool fixed) { fixed_ = fixed; }
		
		// 固定かどうか
		bool fixed() { return fixed_; }
		
		// 位置を設定
		void set_xpos(int xpos) { xpos_ = xpos; }
		void set_ypos(int ypos) { ypos_ = ypos; }
		
		// 位置を取得
		int get_xpos() const { return xpos_; }
		int get_ypos() const { return ypos_; }
		friend class SheetController;
	};
	
	/*
	 * シートコントローラ
	 */
	class SheetController {
		Sheet* sheets0_; // シートの実体を格納
		Sheet** sheets_; // シートへのポインタを格納
		Picture map_; // マウス有りマップ
		Picture map_nomouse_; // マウス無しマップ
		
		bool exist_mouse_; // マウスのシートが存在するか
		int* taskids_;
		
		int top_; // トップの高さ
		
		/*
		 * 領域を広げる
		 */
		//void expand();
		
	public:
		// 定数
		static const int MAX_SHEETS = 256; // 最大シート数

		explicit SheetController();
		~SheetController();
		
		Sheet* alloc(int taskid = -1, bool mouse = false);
		void free(Sheet* sht);
		
		void updown(Sheet* sht, int new_height);
		void updown(int old_height, int new_height);
		
		// シートの中の指定した範囲を再描画
		void refresh(const Sheet* sht, int x0, int y0, int x1, int y1);
		
		// シートの中の指定した範囲を再描画
		void refresh_winframe(const Sheet* sht);
		
		// 指定した画面の範囲を、指定した高さの範囲において再描画
		void refresh_sub(int x0, int y0, int x1, int y1, int h0, int h1);
		
		// マップを再描画
		void refresh_map(int x0, int y0, int x1, int y1, int h0);
		
		// 指定した画面の範囲を、指定した高さの範囲において再描画
		void refresh_sub_dragframe(int x0, int y0, int x1, int y1, int h0, int h1);
		
		// マップを再描画
		void refresh_map_dragframe(int x0, int y0, int x1, int y1, int h0);
		
		// シートを上下左右に移動
		void slide(Sheet* sht, int xpos, int ypos);
		
		// ドラッグ枠を上下左右に移動
		void slide_dragframe(Sheet* sht, int xpos, int ypos);
		
		// 指定した座標のシートIDを取得
		int get_sheetid(int x, int y);
		int get_sheetid_test(int x, int y);
		
		// 指定したシートのシートIDを取得
		int get_sheetid(Sheet* sht);
		
		// 指定した高さのシートIDを取得
		int get_sheetid(int height);
		
		// 指定したシートIDのシートを取得
		Sheet* get_sheet(int sheetid);
		
		// 指定したシートIDのタスクIDを取得
		int get_taskid(int sheetid);
		
		// 指定したシートのタスクIDを取得
		int get_taskid(Sheet* sht) { return get_taskid(sht - sheets0_); }
	};
	
	// 指定したタスクIDのシートを取得
	Sheet* get_sheet_taskid(int taskid);
}

#endif /*SHEET_H_*/
