#include <all_far.h>

#include "Int.h"

#ifdef _DEBUG
void ProcError(int v = 0)
{
	int sel;
	// Assert( 0 );
	// ProcError();
	void (*p)(int) = 0;
	p(v);
	sel = 0;
	sel/= sel;
}
#endif

BOOL InsertHostsCmd(HANDLE h, BOOL full)
{
	PanelInfo pi;
	FTPHost *p;
	LPCSTR m;

	if (!FP_Info->Control(h, FCTL_GETPANELINFO, &pi) || !pi.ItemsNumber || pi.CurrentItem < 0
			|| pi.CurrentItem >= pi.ItemsNumber
			|| (p = FTPHost::Convert(&pi.PanelItems[pi.CurrentItem])) == NULL)
		return FALSE;

	if (full)
		m = p->HostName;
	else
		m = p->Host;

	if (StrCmp(m, "ftp://", 6, FALSE) != 0 && StrCmp(m, "http://", 7, FALSE) != 0)
		FP_Info->Control(h, FCTL_INSERTCMDLINE, (void *)(p->Folder ? "" : "ftp://"));

	return FP_Info->Control(h, FCTL_INSERTCMDLINE, (HANDLE)m);
}

int FTP::ProcessKey(int Key, unsigned int ControlState)
{
	PROC(("FTP::ProcessKey", "k:%08X(%c), sh:%08X", Key, __isascii(Key) && isprint(Key) ? ((char)Key) : ' ',
			ControlState))
	PanelRedrawInfo ri;
	PanelInfo pi, otherPI;
	FTPHost h, *p;

	// Skip arrows
	if (ControlState == 0)
		switch (Key) {
			case VK_END:
			case VK_HOME:
			case VK_UP:
			case VK_DOWN:	// Get info

				if (!FP_Info->Control(this, FCTL_GETPANELSHORTINFO, &pi)
						&& !FP_Info->Control(this, FCTL_GETPANELINFO, &pi)) {
					Log(("!GetPanelInfo"));
					return FALSE;
				}

				// Skip self processing for QView work correctly
				if (!FP_Info->Control(this, FCTL_GETANOTHERPANELSHORTINFO, &otherPI)
						|| (otherPI.PanelType == PTYPE_QVIEWPANEL || otherPI.PanelType == PTYPE_TREEPANEL))
					return FALSE;

				// Get current
				ri.TopPanelItem = pi.TopPanelItem;

				switch (Key) {
					case VK_END:
						ri.CurrentItem = pi.ItemsNumber - 1;
						break;
					case VK_HOME:
						ri.CurrentItem = 0;
						break;
					case VK_UP:
						ri.CurrentItem = pi.CurrentItem - 1;
						break;
					case VK_DOWN:
						ri.CurrentItem = pi.CurrentItem + 1;
						break;
				}

				// Move cursor
				if (ri.CurrentItem == pi.CurrentItem || ri.CurrentItem < 0
						|| ri.CurrentItem >= pi.ItemsNumber)
					return TRUE;
				else
					return FP_Info->Control(this, FCTL_REDRAWPANEL, &ri);
		}

	// Check for empty command line
	if (!ShowHosts && ControlState == PKF_CONTROL && Key == VK_INSERT) {
		char str[1024];
		FP_Info->Control(this, FCTL_GETCMDLINE, str);

		if (!str[0])
			ControlState = PKF_CONTROL | PKF_SHIFT;
	}

	// --------------------------------------------------------------------------
	// Ctrl+BkSlash
	if (Key == 0xDC && ControlState == 1) {
		Log(("CDROOT"));

		if (ShowHosts)
			SetDirectory("/", 0);
		else {
			FP_Screen _scr;
			SetDirectory("/", 0);
		}

		Reread();
		Invalidate();
		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Drop full url
	if (ShowHosts && ControlState == PKF_CONTROL) {
		if (Key == 'F')
			return InsertHostsCmd(this, TRUE);
		else if (Key == VK_RETURN)
			return InsertHostsCmd(this, FALSE);
	}

	// --------------------------------------------------------------------------
	// Utils menu
	if (ControlState == PKF_SHIFT && Key == VK_F1) {
		static LPCSTR strings[] = {NULL, "", FMSG(MHostParams), FMSG(MCloseConnection), FMSG(MUtilsDir),
				FMSG(MUtilsCmd), "", FMSG(MUtilsLog),
				NULL,		// Sites list
				FMSG(MShowQueue),
#ifdef _DEBUG
				"", FMSG("Generate DIVIDE BY ZERO &Bug (Plugin traps!)"),
#endif
				NULL};
#ifdef _DEBUG
		strings[0] = Message("%s \"" __DATE__ "\" " __TIME__ " (DEBUG) ", FP_GetMsg(MVersionTitle));
#else
		strings[0] = Message("%s \"" __DATE__ "\" " __TIME__ " ", FP_GetMsg(MVersionTitle));
#endif
		strings[8] = isBackup() ? FMSG(MRemoveFromites) : FMSG(MAddToSites);
		//
		FP_MenuEx mnu(strings);
		int prev = 0, sel = (ShowHosts || !hConnect) ? 7 : 2, file;
		mnu.Item(0)->isGrayed(TRUE);

		do {
			if (ShowHosts || !hConnect) {
				mnu.Item(2)->isGrayed(TRUE);
				mnu.Item(3)->isGrayed(TRUE);
				mnu.Item(4)->isGrayed(TRUE);
				mnu.Item(5)->isGrayed(TRUE);
			}

			if (!Opt.UseBackups)
				mnu.Item(8)->isGrayed(TRUE);

			mnu.Item(sel)->isSelected(TRUE);
			sel = mnu.Execute(FMSG(MUtilsCaption), FMENU_WRAPMODE, NULL, "FTPUtils");
			mnu.Item(prev)->isSelected(FALSE);
			prev = sel;

			switch (sel) {
				case -1:
					return TRUE;
					// Version
				case 0:
					break;
					// Host parameters
				case 2:

					if (ShowHosts || !hConnect)
						break;

					do {
						FTPHost tmp = Host;

						if (!GetHost(MEditFtpTitle, &tmp, FALSE))
							break;

						// Reconnect
						if (!Host.CmpConnected(&tmp)) {
							Host = tmp;

							if (!FullConnect()) {
								BackToHosts();
								Invalidate();
							}

							break;
						}

						Host = tmp;
						// Change connection paras
						hConnect->InitData(&Host, -1);
						hConnect->InitIOBuff();
						Invalidate();
					} while (0);

					return TRUE;
					// Switch to hosts
				case 3:

					if (ShowHosts || !hConnect)
						break;

					BackToHosts();
					Invalidate();
					return TRUE;
					// Dir listing
				case 4:

					if (ShowHosts || !hConnect)
						break;

					{
						char str[MAX_PATH];		// Must be static buff because of MkTemp
						FP_FSF->MkTemp(str, "FTP");
						sdc_mkdir(str, 0777);
						AddEndSlash(str, '/', ARRAYSIZE(str));
						StrCat(str, "FTPDir.txt", ARRAYSIZE(str));
						file = creat(str, S_IREAD | S_IWRITE | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

						if (file == -1) {
							hConnect->ConnectMessage(MErrorTempFile, str, -MOk);
							return TRUE;
						}
						if (write(file, hConnect->Output, hConnect->OutputSize) != hConnect->OutputSize) {
							perror("write");
						}
						close(file);
						FP_Info->Viewer(str, Message("%s: %s {%s}", FP_GetMsg(MDirTitle), PanelTitle, str), 0,
								0, -1, -1, VF_NONMODAL | VF_DELETEONCLOSE);
					}
					return TRUE;
					// Show CMD
				case 5:

					if (ShowHosts || !hConnect)
						break;

					file = hConnect->Host.ExtCmdView;
					hConnect->Host.ExtCmdView = TRUE;
					WINPORT(SetLastError)(ERROR_SUCCESS);
					hConnect->ConnectMessage(MNone__, NULL, MOk);
					hConnect->Host.ExtCmdView = file;
					return TRUE;
					// ------------------------------------------------------------
					// Show LOG
				case 7:

					if (IsCmdLogFile())
						FP_Info->Viewer(GetCmdLogFile(), FP_GetMsg(MLogTitle), 0, 0, -1, -1,
								VF_NONMODAL | VF_ENABLE_F6);

					return TRUE;
					// Add\Remove sites list
				case 8:

					if (isBackup())
						DeleteFromBackup();
					else
						AddToBackup();

					return TRUE;
					// FTP queque
				case 9:
					QuequeMenu();
					return TRUE;
#ifdef _DEBUG
					// ------------------------------------------------------------
				case 11:
					ProcError();
					break;
#endif
			}
		} while (true);
	}

	// --------------------------------------------------------------------------
	// Copy names
	if (!ShowHosts && ControlState == (PKF_CONTROL | PKF_SHIFT) && Key == VK_INSERT) {
		CopyNamesToClipboard();
		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Table
	if (!ShowHosts && ControlState == PKF_SHIFT && Key == VK_F7) {
		SelectTable();
		Invalidate();
		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Attributes
	if (hConnect && !ShowHosts && ControlState == PKF_CONTROL && Key == 'A') {
		SetAttributes();
		Invalidate();
		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Save URL
	if (hConnect && !ShowHosts && ControlState == PKF_ALT && Key == VK_F6) {
		SaveURL();
		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Reread
	if (ControlState == PKF_CONTROL && Key == 'R') {
		ResetCache = TRUE;
		return FALSE;
	}

	// --------------------------------------------------------------------------
	// Drop full name
	if (!ShowHosts && hConnect && ControlState == PKF_CONTROL && Key == 'F') {
		FP_Info->Control(this, FCTL_GETPANELINFO, &pi);

		if (pi.CurrentItem >= pi.ItemsNumber)
			return FALSE;

		String s, path;
		FtpGetCurrentDirectory(hConnect, path);
		Host.MkUrl(s, path.c_str(), FTP_FILENAME(&pi.PanelItems[pi.CurrentItem]));
		QuoteStr(s);
		FP_Info->Control(this, FCTL_INSERTCMDLINE, s.c_str());
		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Select
	if (ControlState == 0 && Key == VK_RETURN) {
		PluginPanelItem *cur;
		FP_Info->Control(this, FCTL_GETPANELINFO, &pi);

		if (pi.CurrentItem >= pi.ItemsNumber)
			return FALSE;

		cur = &pi.PanelItems[pi.CurrentItem];

		// Switch to FTP
		if (ShowHosts && !IS_FLAG(cur->FindData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
			p = FTPHost::Convert(cur);

			if (!p)
				return FALSE;

			Log(("SelectFileItem [%s] [%s]", p->RegKey, p->HostName));
			Host.Assign(p);
			FullConnect();
			return TRUE;
		}	/*FTP SWITCH*/

		// Change directory
		if (!ShowHosts && hConnect) {
			if (StrCmp(FTP_FILENAME(cur), ".") != 0 && StrCmp(FTP_FILENAME(cur), "..") != 0)
				if (IS_FLAG(cur->FindData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)
						|| IS_FLAG(cur->FindData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
					if (SetDirectoryFAR(IS_FLAG(cur->FindData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)
										? cur->CustomColumnData[FTP_COL_LINK]
										: FTP_FILENAME(cur),
								0)) {
						FP_Info->Control(this, FCTL_UPDATEPANEL, NULL);
						struct PanelRedrawInfo RInfo;
						RInfo.CurrentItem = RInfo.TopPanelItem = 0;
						FP_Info->Control(this, FCTL_REDRAWPANEL, &RInfo);
						return TRUE;
					} else
						return TRUE;
				}
		}	/*CHANGE DIR*/
	}		/*ENTER*/

			// --------------------------------------------------------------------------
	// New entry
	if (ShowHosts
			&& ((ControlState == PKF_SHIFT && Key == VK_F4) || (ControlState == PKF_ALT && Key == VK_F6))) {
		Log(("New host"));
		h.Init();

		if (GetHost(MEnterFtpTitle, &h, FALSE)) {
			Log(("bw: [%s] [%s] [%s], sf: %s", h.Host, h.User, h.Password, h.RegKey));
			h.Write(HostsPath);
			SelectFile = h.RegKey;
			Invalidate();
		}

		return TRUE;
	}

	// --------------------------------------------------------------------------
	// Edit
	if (ShowHosts
			&& ((ControlState == 0 && Key == VK_F4) || (ControlState == PKF_SHIFT && Key == VK_F6)
					|| (ControlState == PKF_CONTROL && Key == 'Z'))) {
		FP_Info->Control(this, FCTL_GETPANELINFO, &pi);

		if (pi.CurrentItem >= pi.ItemsNumber)
			return TRUE;

		p = FTPHost::Convert(&pi.PanelItems[pi.CurrentItem]);

		if (!p)
			return TRUE;

		Log(("EditHost: [%s] [%s]", p->RegKey, p->Host));

		if (p->Folder) {
			String s(p->Host);

			if (!EditDirectory(s, p->HostDescr, FALSE))
				return TRUE;

			StrCpy(p->Host, s.c_str(), ARRAYSIZE(p->Host));
		} else {
			if (!GetHost(MEditFtpTitle, p, Key == 'Z'))
				return TRUE;
		}

		if (p->Write(HostsPath)) {
			SelectFile = p->RegKey;
			Log(("SetLastHost: [%s]", SelectFile.c_str()));
			FP_Info->Control(this, FCTL_UPDATEPANEL, NULL);
			FP_Info->Control(this, FCTL_REDRAWPANEL, NULL);
		}

		return TRUE;
	}	/*Edit*/

		// --------------------------------------------------------------------------
	// Copy/Move
	if (!ShowHosts && (ControlState == 0 || ControlState == PKF_SHIFT) && Key == VK_F6) {
		FTP *ftp = OtherPlugin(this);
		int rc;

		if (!ftp && ControlState == 0 && Key == VK_F6)
			return FALSE;

		FP_Info->Control(this, FCTL_GETPANELINFO, &pi);
		FP_Info->Control(this, FCTL_GETANOTHERPANELINFO, &otherPI);

		if (pi.SelectedItemsNumber > 0 && pi.CurrentItem >= 0 && pi.CurrentItem < pi.ItemsNumber) {
			do {
				String s;

				if (ControlState == PKF_SHIFT) {
					s = FTP_FILENAME(&pi.PanelItems[pi.CurrentItem]);
					rc = GetFiles(&pi.PanelItems[pi.CurrentItem], 1, Key == VK_F6, s, 0);
				} else {
					s = otherPI.CurDir;
					rc = GetFiles(pi.SelectedItems, pi.SelectedItemsNumber, Key == VK_F6, s, 0);
				}

				if (rc == TRUE || rc == -1) {
					FP_Screen::FullRestore();
					FP_Info->Control(this, FCTL_UPDATEPANEL, NULL);
					FP_Info->Control(this, FCTL_REDRAWPANEL, NULL);
					FP_Screen::FullRestore();
					FP_Info->Control(this, FCTL_UPDATEANOTHERPANEL, NULL);
					FP_Info->Control(this, FCTL_REDRAWANOTHERPANEL, NULL);
					FP_Screen::FullRestore();
				}

				return TRUE;
			} while (0);
		}
	}

	return FALSE;
}
