/**
 * @file
 * @brief 攚宨昤夋惂屼娭楢偺幚憰傪峴偆.
 * 
 * @author S.F.
 * @version $Id:
 * Copyright (C) 2000-2002 Satoshi Fujiwara. All Rights Reserved.
 */

#pragma warning( disable : 4786 )	///<STL偺寈崘奜偟
// 儊儌儕乕儕乕僋専弌梡
#include "sfdebug.h"

// System Includes //

#include "stdio.h"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>

// Project Includes //


#include "exception.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#include "system.h"
#include "console.h"
#include "Obj.h"
#include "Obj2D.h"
#include "ObjRectangle.h"
#include "ObjQuadrangle.h"
#include "BackGround.h"

# define WIDEN2(x) L ## x
# define WIDEN(x) WIDEN2(x)
//////////////////////////////////////////////////////////////////////
// 峔抸/徚柵
//////////////////////////////////////////////////////////////////////
using namespace sf::system::console;
using namespace sf;

const int Background::Map::HEIGHT_MAX = 64;
const int Background::Map::CELL_SIZE = 64;
const int Background::Map::WIDTH = 8;

const int Background::Map::DRAW_HEIGHT = 9;
const float Background::Map::DRAW_START_X  = 96.0f;
const float Background::Map::DRAW_START_Y  = 448.0f;
const float Background::Map::DRAW_CENTER_Y = 256.0f;

const int Background::Map::CELL_TEX_COUNT_W = 4;
const int Background::Map::CELL_TEX_COUNT_H = 4;

const sf::system::console::sprite::Info Background::msBlankSpriteInfo = 
{
	"media\\blank.bmp",0.0f,0.0f,0.0f,0.0f,0xff000000,sprite::SPRITE2D
};

Background::Background() : ObjRectangle()
{
	using namespace sf::system;

	System *psys = instance();
	mpConsole = psys->console();

	z(0.99f);
	color(0xffffffff);
	mOffsetX = mOffsetY = 0.0f;
	mpMap = NULL;
	
	mStartOffsetX = mStartOffsetY = 0.0f;
	mpBlankSprite = instance()->console()->createSprite(&msBlankSpriteInfo);
	
	mObj[0].sprite(mpBlankSprite);
	mObj[1].sprite(mpBlankSprite);
	mObj[0].visibility(false);
	mObj[1].visibility(false);
	mObj[0].z(0.01f);
	mObj[1].z(0.01f);
	mObj[0].drawMode(DRAW_ADD);
	mObj[1].drawMode(DRAW_ADD);
	
	for(int i = 0;i < 4;i++){
		mObj[0].vertex(i)->diffuse  = 0x40000020;
		mObj[1].vertex(i)->diffuse  = 0x40400000;

		mObj[0].vertex(i)->specular = 0.0f;
		mObj[1].vertex(i)->specular = 0.0f;

		mObj[0].vertex(i)->z = 0.01f;
		mObj[1].vertex(i)->z = 0.01f;
	}

}

Background::~Background()
{
	unload();
	delete mpBlankSprite;
}

// 僥僋僗僠儍偍傛傃儅僢僾僨乕僞偺傾儞儘乕僪 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
void Background::unload()
{
	visibility(false);	
	sprite::Sprite * psprite;
	for(TextureList::iterator it = mTextureList.begin();it != mTextureList.end();++it)
	{
		psprite = *it;
		delete psprite;
	}
	mTextureList.clear();
	mMapData.clear();
}// unload()

// 攚宨僨乕僞偺儘乕僪 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
void Background::load(const char * const pMapFileName)
{
	unload();
	
	// 僼傽僀儖僱乕儉偺僶僢僋傾僢僾
	mFileName = pMapFileName;

	std::fstream file(pMapFileName,std::ios::in);
	
	if(!file.is_open()){
		throw FatalErrorException(L"File Open Error",WIDEN(__FILE__),__LINE__);
	}

	int num_tex,i;
	sprite::Sprite *psp;
	sprite::Info sp_info;

	// 僥僋僗僠儍偺撉傒崬傒 
	file >> num_tex;
	long flags = 0;
	for(i = 0;i < num_tex;i++)
	{
		file >> sp_info.fileName;
		file >> sp_info.cellHeight;
		file >> sp_info.cellWidth;
		file >> sp_info.centerX;
		file >> sp_info.centerY;

		flags = file.flags();
		flags = ((flags ^ std::ios::dec) | std::ios::hex | std::ios::showbase);
		file.flags(flags);   
		file >> sp_info.transparentColor;

		flags = ((flags ^ std::ios::hex) | std::ios::dec);

		file.flags(flags);
		sp_info.type = sprite::SPRITE2D;

		psp = mpConsole->createSprite(&sp_info);
	
	
		if(file.fail())
		{
			throw FatalErrorException(L"File Read Error",WIDEN(__FILE__),__LINE__);
		};

		mTextureList.push_back(psp);
		mTextureInfoList.push_back(sp_info);
	}

	file >> mMapWidth >> mMapHeight;
	
	mOffsetYLimit = (float) (mMapHeight - 1) * Map::CELL_SIZE - screen::HEIGHT;
	flags = ((flags ^ std::ios::dec) | std::ios::hex);
	file.flags(flags);   
	
	//mpMap = new int[ mMapHeight * mMapWidth];
	DWORD data;
	for(i = 0;i < mMapWidth * mMapHeight;i ++)
	{
		file >> data;
		if(file.fail()){
			throw FatalErrorException(L"File Read Error",WIDEN(__FILE__),__LINE__);
		}
		mMapData.push_back(data);
	}

}//load()

// 儅僢僾僨乕僞傪夋柺偵昤夋偡傞 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
void Background::draw()
{
	// 昞帵懏惈偺僠僃僢僋
	if(!visibility()) return;
	
	int map_offset_y  = (int)(mOffsetY + startOffsetY() ) / Map::CELL_SIZE;
	float screen_offset_y = (int)(mOffsetY + startOffsetY()) % Map::CELL_SIZE;

	//float sy = Map::DRAW_START_Y + screen_offset_y + map_start_offset_y1;
	
	// 昤夋奐巒y嵗昗
	float sy = Map::DRAW_START_Y + screen_offset_y;

	float sx = 0.0f;
	
	float ex = 0.0f;
	float ey = 0.0f;

	// 僙儖僒僀僘
	float cell_size = (float)Map::CELL_SIZE;
	
	int data,index,spriteNo,dy;


	ObjRectangle *pobj = (ObjRectangle *)this;
	
	// 儅僢僾僙儖偺昤夋
	for(int i = map_offset_y;i < Map::DRAW_HEIGHT + map_offset_y; i++){
 		if(i >= 0 &&  i <  mMapHeight){
			sx = Map::DRAW_START_X + mOffsetX + startOffsetX();
			dy = i * Map::WIDTH;

			for(int j = 0;j < Map::WIDTH; j++)
			{
				data = mMapData[dy + j];
				if(data){
					--data;
					index = data & 0xf;
					spriteNo = (data & 0xffff0000) >> 16;
			
					y(sy);
					x(sx);
			
					ObjRectangle::index(index);

					mTextureList[spriteNo]->draw(pobj);
				}

				sx += cell_size;

			}
		}
		sy -= cell_size;
	}

	// 幚嵺偺昞帵僄儕傾傪傢偐傞傛偆偵偡傞偨傔偺昞帵 
	if(edit()){// 曇廤拞偺傒昞帵偡傞
		if(startOffsetY() != 0){		
			mObj[0].visibility(true);
			mObj[0].vertex(0)->x = (viewport::X);
			mObj[0].vertex(1)->x = (viewport::X + viewport::WIDTH);
			mObj[0].vertex(2)->x = (viewport::X);
			mObj[0].vertex(3)->x = (viewport::X + viewport::WIDTH);

			if(startOffsetY() > 0){
				sy = viewport::Y;
				ey = viewport::Y + 
					((viewport::Y + startOffsetY()) < (viewport::Y + viewport::HEIGHT)) 
					? (startOffsetY() + viewport::Y) 
					: (viewport::Y + viewport::HEIGHT);
			} else {
				sy = (((viewport::Y + viewport::HEIGHT) + startOffsetY()) > viewport::Y) 
					?  (viewport::Y + viewport::HEIGHT + startOffsetY()) : viewport::Y  ;
				ey = viewport::Y + viewport::HEIGHT;
			}

			mObj[0].vertex(0)->y = (sy);
			mObj[0].vertex(1)->y = (sy);
			mObj[0].vertex(2)->y = (ey);
			mObj[0].vertex(3)->y = (ey);
		} else {
			mObj[0].visibility(false);
		}
		
		if(startOffsetX() != 0){
			mObj[1].visibility(true);
			mObj[1].vertex(0)->y = (viewport::Y);
			mObj[1].vertex(1)->y = (viewport::Y);
			mObj[1].vertex(2)->y = (viewport::Y +  viewport::HEIGHT);
			mObj[1].vertex(3)->y = (viewport::Y + viewport::HEIGHT);

			if(startOffsetX() > 0){
				sx = viewport::X;
				ex = viewport::X + 
					(viewport::X + startOffsetX() < (viewport::X + viewport::WIDTH)) 
						? ( startOffsetX() + viewport::X)
					: (viewport::X + viewport::WIDTH);
			} else {
				sx = (((viewport::X + viewport::WIDTH) + startOffsetX()) > viewport::X) 
					?  (viewport::X + viewport::WIDTH + startOffsetX()) : viewport::X  ;
				ex = viewport::X + viewport::WIDTH;
			}

			mObj[1].vertex(0)->x = (sx);
			mObj[1].vertex(1)->x = (ex);
			mObj[1].vertex(2)->x = (sx);
			mObj[1].vertex(3)->x = (ex);
		} else {
			mObj[1].visibility(false);
		};
	} else {
		mObj[1].visibility(false);
		mObj[0].visibility(false);
	}

}// draw

// Map僨乕僞偺僙乕僽 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
bool Background::save(const char *pMapFileName)
{
	std::wstring err_savestr = L"Background:save() Error!";
	int i;

	// 僼傽僀儖僱乕儉偑NULL偺応崌丄儘乕僪帪偺僼傽僀儖僱乕儉傪巊梡
	if(pMapFileName == NULL){
		if(mFileName.c_str() == NULL){
			return false;
		} else {
			pMapFileName = mFileName.c_str();
		}
	}

	std::fstream file(pMapFileName,std::ios::out);
	
	if(!file.is_open())
		return false;


	sprite::Info sp_info;

	// 僥僋僗僠儍悢偺彂偒崬傒 

	file << mTextureInfoList.size() << std::endl;

	long flags = 0;
	
	for(TextureInfoList::iterator it = mTextureInfoList.begin();
			it != mTextureInfoList.end(); it ++)
	{
		sp_info = *it;
		
		file << sp_info.fileName << std::endl;

		file << sp_info.cellHeight << " ";
		file << sp_info.cellWidth << " ";
		file << sp_info.centerX << " ";
		file << sp_info.centerY << " ";

		flags = file.flags();
		flags = ((flags ^ std::ios::dec) | std::ios::hex | std::ios::showbase);
		file.flags(flags);   

		file << sp_info.transparentColor << std::endl;

		flags = ((flags ^ std::ios::hex) | std::ios::dec);

		file.flags(flags);
		
		if(file.fail())
		{
			system::instance()->errorTerminate(err_savestr.c_str());
		};
	}

	file << mMapWidth << " " << mMapHeight << std::endl;
	
	flags = ((flags ^ std::ios::dec) | std::ios::hex);
	file.flags(flags);   
	
	//mpMap = new int[ mMapHeight * mMapWidth];
	DWORD data;
	for(i = 0;i < mMapWidth * mMapHeight;i ++)
	{
		data = mMapData[i] ;

		file << data;
		
		if((i & 0x7) == 7) {
			file << std::endl;
		} else {
			file << " ";
		}
	
		if(file.fail()){
			system::instance()->errorTerminate(err_savestr.c_str());
			return false;
		}
	}
	return true;
}

// Map僨乕僞傪僙僢僩 亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅亅
void Background::setData(float screenX, float screenY, DWORD value)
{
	int y = (int)(viewport::HEIGHT - screenY + mOffsetY) / Map::CELL_SIZE;
	int x = (int)(screenX + mOffsetX - Map::DRAW_START_X + Map::CELL_SIZE / 2) / Map::CELL_SIZE;
	mMapData[x + y * Map::WIDTH] = value;
}
