#include"common.h"

#include<iostream>
#include<fstream>

namespace Edit
{
	extern vector2D coordinates1;
	extern vector2D coordinates2;
}

namespace Interface
{
	extern vector2D AlignedMouseCoordinates;	//GridInterval間隔で
	extern vector2D FirstAlignedMouseCoordinates;	//始点
}


namespace Place
{
	extern Direction NewDirection;	//新しい記号の方向
	extern Operation NewGateOperation;	//新しい論理ゲートの演算
	extern unsigned int NewGateIn; //新しい論理ゲートの入力数
	extern Module NewModule;		//新しいモジュール
	extern char NewLabelName[SIZE_OF_LABEL_NAME];	//新しいラベルの名前
}

extern Data main_data;
extern Data copy_data;


void Data::CopyRange(bool Erase,bool Copy)
{
	vector2D top_left(		Edit::coordinates1.Getx()<Edit::coordinates2.Getx() ? Edit::coordinates1.Getx() : Edit::coordinates2.Getx(),
							Edit::coordinates1.Gety()<Edit::coordinates2.Gety() ? Edit::coordinates1.Gety() : Edit::coordinates2.Gety());

	vector2D bottom_right(	Edit::coordinates1.Getx()>Edit::coordinates2.Getx() ? Edit::coordinates1.Getx() : Edit::coordinates2.Getx(),
							Edit::coordinates1.Gety()>Edit::coordinates2.Gety() ? Edit::coordinates1.Gety() : Edit::coordinates2.Gety());

	if(Copy)copy_data.Clear();

	for(unsigned int i=0;i<note.size();i++)
	{
		vector2D pos;
		pos=note[i].position();
		if(pos.Getx()>=top_left.Getx() && pos.Getx()<=bottom_right.Getx() && pos.Gety()>=top_left.Gety() && pos.Gety()<=bottom_right.Gety())
		{
			if(Copy)
			{
				Interface::AlignedMouseCoordinates=pos-Edit::coordinates2;
				strcpy_s(Place::NewLabelName,note[i].name());
				copy_data.WriteNote();
			}
			if(Erase) Delete(note,i--);
		}
	}

	for(unsigned int i=0;i<input.size();i++)
	{
		vector2D pos;
		pos=node_data[input[i].nodeindex()].position()-DirectionVector[input[i].direction()];
		if(pos.Getx()>=top_left.Getx() && pos.Getx()<=bottom_right.Getx() && pos.Gety()>=top_left.Gety() && pos.Gety()<=bottom_right.Gety())
		{
			if(Copy)
			{
				Interface::AlignedMouseCoordinates=pos-Edit::coordinates2;
				Place::NewDirection = input[i].direction();
				strcpy_s(Place::NewLabelName,input[i].name());
				copy_data.PlaceInLabel();
			}
			if(Erase) EraseInputLabel(i--);
		}
	}

	for(unsigned int i=0;i<output.size();i++)
	{
		vector2D pos;
		pos=node_data[output[i].nodeindex()].position()-DirectionVector[output[i].direction()];
		if(pos.Getx()>=top_left.Getx() && pos.Getx()<=bottom_right.Getx() && pos.Gety()>=top_left.Gety() && pos.Gety()<=bottom_right.Gety())
		{
			if(Copy)
			{
				Interface::AlignedMouseCoordinates=pos-Edit::coordinates2;
				Place::NewDirection = ReverseDirection(output[i].direction());
				strcpy_s(Place::NewLabelName,output[i].name());
				copy_data.PlaceOutLabel();
			}
			if(Erase)EraseOutputLabel(i--);
		}
	}

	for(unsigned int i=0;i<gate.size();i++)
	{
		vector2D pos0,pos1;
		switch(gate[i].direction())
		{
		case RIGHT:
			pos0=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[LEFT]*3+DirectionVector[UP]*gate[i].nIn();
			pos1=node_data[gate[i].NodeOutIndex()].position()-DirectionVector[RIGHT]+DirectionVector[DOWN]*gate[i].nIn();
			break;
		case DOWN:
			pos0=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[LEFT]*gate[i].nIn()+DirectionVector[UP]*3;
			pos1=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*gate[i].nIn()-DirectionVector[DOWN];
			break;
		case LEFT:
			pos0=node_data[gate[i].NodeOutIndex()].position()-DirectionVector[LEFT]+DirectionVector[UP]*gate[i].nIn();
			pos1=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*3+DirectionVector[DOWN]*gate[i].nIn();
			break;
		case UP:
			pos0=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[LEFT]*gate[i].nIn()-DirectionVector[UP];
			pos1=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*gate[i].nIn()+DirectionVector[DOWN]*3;
			break;
		}
		if(pos0.Getx()>=top_left.Getx() && pos0.Getx()<=bottom_right.Getx() && pos0.Gety()>=top_left.Gety() && pos0.Gety()<=bottom_right.Gety()
			&&pos1.Getx()>=top_left.Getx() && pos1.Getx()<=bottom_right.Getx() && pos1.Gety()>=top_left.Gety() && pos1.Gety()<=bottom_right.Gety())
		{
			if(Copy)
			{
				Interface::AlignedMouseCoordinates=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[gate[i].ReverseDirection()]-Edit::coordinates2;
				Place::NewDirection=gate[i].direction();
				Place::NewGateOperation=gate[i].operation();
				Place::NewGateIn=gate[i].nIn();
				copy_data.PlaceGate();
			}
			if(Erase)EraseGate(i--);
		}
	}

	for(unsigned int i=0;i<conductor.size();i++)
	{
		vector2D pos0,pos1;
		pos0=node_data[conductor[i].nodeindex0()].position();
		pos1=node_data[conductor[i].nodeindex1()].position();
		if(pos0.Getx()>=top_left.Getx() && pos0.Getx()<=bottom_right.Getx() && pos0.Gety()>=top_left.Gety() && pos0.Gety()<=bottom_right.Gety()
			&&pos1.Getx()>=top_left.Getx() && pos1.Getx()<=bottom_right.Getx() && pos1.Gety()>=top_left.Gety() && pos1.Gety()<=bottom_right.Gety())
		{
			if(Copy)
			{
				Interface::FirstAlignedMouseCoordinates=pos0-Edit::coordinates2;
				Interface::AlignedMouseCoordinates=pos1-Edit::coordinates2;
				copy_data.PlaceConductor();
			}
			if(Erase)EraseConductor(i--);
		}
	}

	for(unsigned int i=0;i<module.size();i++)
	{
		vector2D pos0,pos1;
		pos0=module[i].Center()+DirectionVector[UP]*(module[i].InternalHalfHeight()+module[i].UpMargin())+DirectionVector[LEFT]*(module[i].InternalHalfWidth()+module[i].LeftMargin());
		pos1=module[i].Center()+DirectionVector[DOWN]*(module[i].InternalHalfHeight()+module[i].DownMargin())+DirectionVector[RIGHT]*(module[i].InternalHalfWidth()+module[i].RightMargin());

		if(pos0.Getx()>=top_left.Getx() && pos0.Getx()<=bottom_right.Getx() && pos0.Gety()>=top_left.Gety() && pos0.Gety()<=bottom_right.Gety()
			&&pos1.Getx()>=top_left.Getx() && pos1.Getx()<=bottom_right.Getx() && pos1.Gety()>=top_left.Gety() && pos1.Gety()<=bottom_right.Gety())
		{
			if(Copy)
			{
				Place::NewModule=module[i];
				Interface::AlignedMouseCoordinates=module[i].Center()-Edit::coordinates2;
				copy_data.PlaceModule();
			}
			if(Erase)EraseModule(i--);
		}
	}

	char ExePath[MAX_PATH+1];
	char FileEdit[MAX_PATH+1];
	char drive[MAX_PATH+1],dir[MAX_PATH+1];
	GetModuleFileName(NULL,ExePath,MAX_PATH);
	_splitpath_s(ExePath,drive,MAX_PATH+1,dir,MAX_PATH+1,NULL,0,NULL,0);
	_makepath_s(FileEdit,MAX_PATH+1,drive,dir,"FileUsedByEditingOfAst","log");
	std::ofstream f(FileEdit);
	f << Version << std::endl <<std::endl;
	f << copy_data;
	f.close();
}

void LoadCopiedData()
{
	char ExePath[MAX_PATH+1];
	char FileEdit[MAX_PATH+1];
	char drive[MAX_PATH+1],dir[MAX_PATH+1];
	GetModuleFileName(NULL,ExePath,MAX_PATH);
	_splitpath_s(ExePath,drive,MAX_PATH+1,dir,MAX_PATH+1,NULL,0,NULL,0);
	_makepath_s(FileEdit,MAX_PATH+1,drive,dir,"FileUsedByEditingOfAst","log");
	std::ifstream f(FileEdit);

	if(f)
	{
		char s[SIZE_OF_LABEL_NAME];
		f.getline(s,SIZE_OF_LABEL_NAME);
		if(strcmp(s,Version)==0)
		{
			copy_data.Clear();
			f >> copy_data;
			if(!f.good())
			{
				copy_data.Clear();
				MessageBox(0,"ファイルが壊れています","エラー",MB_OK);
			}
		}
		else
			MessageBox(0,"バージョンの異なるファイルです","エラー",MB_OK);
		f.close();
	}
}

bool Data::AbleToPaste()
{
	unsigned int i;
	vector2D MouseCoordinates=Interface::AlignedMouseCoordinates;
	for(i=0;i<input.size();i++)
	{
		vector2D pos;
		pos=node_data[input[i].nodeindex()].position()-DirectionVector[input[i].direction()];
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		Place::NewDirection = input[i].direction();
		strcpy_s(Place::NewLabelName,input[i].name());
		if(!main_data.AbleToPlaceLabelIn())break;
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
	if(i<input.size())return false;
	for(i=0;i<output.size();i++)
	{
		vector2D pos;
		pos=node_data[output[i].nodeindex()].position()-DirectionVector[output[i].direction()];
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		Place::NewDirection = ReverseDirection(output[i].direction());
		strcpy_s(Place::NewLabelName,output[i].name());
		if(!main_data.AbleToPlaceLabelOut())break;
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
	if(i<output.size())return false;
	for(i=0;i<gate.size();i++)
	{
		Interface::AlignedMouseCoordinates=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[gate[i].ReverseDirection()]+MouseCoordinates;
		Place::NewDirection=gate[i].direction();
		Place::NewGateOperation=gate[i].operation();
		Place::NewGateIn=gate[i].nIn();
		if(!main_data.AbleToPlaceGate())break;
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
	if(i<gate.size())return false;
	for(i=0;i<conductor.size();i++)
	{
		Interface::FirstAlignedMouseCoordinates=node_data[conductor[i].nodeindex0()].position()+MouseCoordinates;
		Interface::AlignedMouseCoordinates=node_data[conductor[i].nodeindex1()].position()+MouseCoordinates;
		if(!main_data.AbleToPlaceConductor())break;
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
	if(i<conductor.size())return false;
	for(i=0;i<module.size();i++)
	{
		Place::NewModule=module[i];
		Interface::AlignedMouseCoordinates=module[i].Center()+MouseCoordinates;
		if(!main_data.AbleToPlaceModule())break;
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
	if(i<module.size())return false;
	return true;
}

void Data::Paste()
{
	vector2D MouseCoordinates=Interface::AlignedMouseCoordinates;
	for(unsigned int i=0;i<note.size();i++)
	{
		vector2D pos;
		pos=note[i].position();
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		strcpy_s(Place::NewLabelName,note[i].name());
		main_data.WriteNote();
	}
	for(unsigned int i=0;i<input.size();i++)
	{
		vector2D pos;
		pos=node_data[input[i].nodeindex()].position()-DirectionVector[input[i].direction()];
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		Place::NewDirection = input[i].direction();
		strcpy_s(Place::NewLabelName,input[i].name());
		main_data.PlaceInLabel();
	}
	for(unsigned int i=0;i<output.size();i++)
	{
		vector2D pos;
		pos=node_data[output[i].nodeindex()].position()-DirectionVector[output[i].direction()];
		Interface::AlignedMouseCoordinates=pos+MouseCoordinates;
		Place::NewDirection = ReverseDirection(output[i].direction());
		strcpy_s(Place::NewLabelName,output[i].name());
		main_data.PlaceOutLabel();
	}
	for(unsigned int i=0;i<gate.size();i++)
	{
		Interface::AlignedMouseCoordinates=node_data[gate[i].NodeOutIndex()].position()+DirectionVector[gate[i].ReverseDirection()]+MouseCoordinates;
		Place::NewDirection=gate[i].direction();
		Place::NewGateOperation=gate[i].operation();
		Place::NewGateIn=gate[i].nIn();
		main_data.PlaceGate();
	}
	for(unsigned int i=0;i<conductor.size();i++)
	{
		Interface::FirstAlignedMouseCoordinates=node_data[conductor[i].nodeindex0()].position()+MouseCoordinates;
		Interface::AlignedMouseCoordinates=node_data[conductor[i].nodeindex1()].position()+MouseCoordinates;
		main_data.PlaceConductor();
	}
	for(unsigned int i=0;i<module.size();i++)
	{
		Place::NewModule=module[i];
		Interface::AlignedMouseCoordinates=module[i].Center()+MouseCoordinates;
		main_data.PlaceModule();
	}
	Interface::AlignedMouseCoordinates=MouseCoordinates;
}