#include <all_far.h>


#include "Int.h"

BOOL FTP::DoFtpConnect(int blocked)
{
	char  hst[FAR_MAX_NAME],
	   usr[FAR_MAX_NAME],
	   pwd[FAR_MAX_NAME];
	const char *m;
	BOOL  askPwd = Host.AskLogin;
	hConnect = NULL;
	WINPORT(SetLastError)(ERROR_SUCCESS);

	if(!Host.Host[0])
		return FALSE;

	CurrentState = fcsConnecting;
	//Create`n`Init connection
	hConnect = new Connection;

	if(!hConnect)
	{
		CurrentState = fcsNormal;
		return FALSE;
	}

	hConnect->InitData(&Host,blocked);
	hConnect->InitCmdBuff();
	hConnect->InitIOBuff();

	do
	{
		hConnect->Host.ExtCmdView = Host.ExtCmdView;
		StrCpy(hst, Host.Host,     ARRAYSIZE(hst));
		StrCpy(usr, Host.User,     ARRAYSIZE(usr));
		StrCpy(pwd, Host.Password, ARRAYSIZE(pwd));

		if(!hConnect->LoginComplete)
			if(!GetLoginData(usr, pwd, Host.AskLogin || askPwd))
				break;

		//Firewall
		if(Host.UseFirewall && *Opt.Firewall)
		{
			strcat(usr,"@");
			StrCat(usr,hst,ARRAYSIZE(usr));
			StrCpy(hst,Opt.Firewall,ARRAYSIZE(hst));
		}

		// Find port
		m = strrchr(hst,':');

		if(m)
		{
			*(char *)m = 0;
			m++;
		}
		else
			m = "0";

		//Connect
		Log(("Connecting"));

		if(hConnect->Init(hst,m,usr,pwd))
		{
			Log(("Connecting succ %d",hConnect->GetResultCode()));

			if(hConnect->GetResultCode() > 420)
			{
				Log(("Connect error from server [%d]",hConnect->GetResultCode()));
				return FALSE;
			}

			FtpSystemInfo(hConnect,NULL,-1);

			if(!FtpGetFtpDirectory(hConnect))
			{
				Log(("!Connect - get dir"));
				return FALSE;
			}

			hConnect->CheckResume();
			CurrentState = fcsFTP;
			return TRUE;
		}

		Log(("!Init"));

		if(!hConnect->LoginComplete &&
		        Opt.AskLoginFail && hConnect->GetResultCode() == 530)
		{
			Log(("Reask password"));
			hConnect->Host.ExtCmdView = TRUE;
			hConnect->ConnectMessage(MNone__,hst,MNone__);
			askPwd = TRUE;
			continue;
		}

		//!Connected
		WINPORT(SetLastError)(hConnect->ErrorCode);

		//!Init
		if(hConnect->SocketError != INVALID_SOCKET)
			hConnect->ConnectMessage(MWSANotInit,GetSocketErrorSTR(hConnect->SocketError),-MOk);
		else

			//!Cancel, but error
			if(hConnect->ErrorCode != ERROR_CANCELLED)
				hConnect->ConnectMessage(MCannotConnectTo,Host.Host,-MOk);

		break;
	}
	while(true);

	CurrentState = fcsNormal;
	delete hConnect;
	hConnect = NULL;
	return FALSE;
}

int FTP::Connect()
{
	PROC(("FTP::Connect",NULL))
	ConnectionState  cst;
	FP_Screen        _scr;
	LogCmd("-------- CONNECTING (plugin: " __DATE__ ", " __TIME__ ") --------",ldInt);

	do
	{
//Close old
		if(hConnect)
		{
			Log(("old connection %p",hConnect));
			hConnect->GetState(&cst);
			Log(("del connection %p",hConnect));
			delete hConnect;
			hConnect = NULL;
			Log(("del connection done"));
		}

//Connect
		if(Opt.ShowIdle && IS_SILENT(FP_LastOpMode))
		{
			Log(("Say connecting"));
			WINPORT(SetLastError)(ERROR_SUCCESS);
			IdleMessage(FP_GetMsg(MConnecting),Opt.ProcessColor);
		}

		if(!DoFtpConnect(cst.Inited ? cst.Blocked : (-1)) ||
		        !hConnect)
		{
			Log(("!Connected"));
			break;
		}

		if(cst.Inited)
		{
			//Restore old connection values or set defaults
			Log(("Restore connection datas"));
			hConnect->SetState(&cst);
		}
		else
		{
			//Init new caonnection values
			Log(("Set connection defaults"));
			hConnect->SetTable(TableNameToValue((*Host.HostTable) ? Host.HostTable : Opt.Table));
			hConnect->Host.PassiveMode = Host.PassiveMode;
		}

//Set start FTP mode
		ShowHosts       = FALSE;
		SwitchingToFTP  = TRUE;
		SelectFile      = "";
		FP_Info->Control(this,FCTL_REDRAWANOTHERPANEL,NULL);

//Set base directory
		if(hConnect && *Host.Home)
		{
			if(Host.Home[0]=='/'&&Host.Home[1]=='\'')
				memmove(Host.Home,Host.Home+1,sizeof(Host.Home)-1);

			Log(("HomeDir [%s]",Host.Home));
			FtpSetCurrentDirectory(hConnect,Host.Home);
		}

		IdleMessage(NULL,0);
		return TRUE;
	}
	while(0);

	if(hConnect)
	{
		hConnect->ConnectMessage(MCannotConnectTo, Host.Host, -MOk);
		delete hConnect;
		hConnect = NULL;
	}

	Host.Init();
	IdleMessage(NULL,0);
	return FALSE;
}

BOOL FTP::FullConnect()
{
	if(Connect())
	{
		if(!ShowHosts)
		{
			BOOL isSaved = FP_Screen::isSaved() != 0;
			FP_Screen::FullRestore();
			FP_Info->Control(this,FCTL_SETVIEWMODE,&StartViewMode);
			FP_Info->Control(this,FCTL_UPDATEPANEL,NULL);
			PanelRedrawInfo ri;
			ri.CurrentItem = ri.TopPanelItem = 0;
			FP_Info->Control(this,FCTL_REDRAWPANEL,&ri);

			if(isSaved)
				FP_Screen::Save();

			SwitchingToFTP = FALSE;
			return TRUE;
		}
	}

	return FALSE;
}
