//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


// SearchDlg.cpp : implementation file
//

#include "stdafx.h"
#include "emule.h"
#include "SearchDlg.h"
#include "packets.h"
#include "server.h"
#include "opcodes.h"
#include "otherfunctions.h"
#include "ED2KLink.h"
#include "CustomAutoComplete.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define	SEARCH_STRINGS_PROFILE	_T("AC_SearchStrings.dat")

// CSearchDlg dialog

IMPLEMENT_DYNAMIC(CSearchDlg, CDialog)
CSearchDlg::CSearchDlg(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CSearchDlg::IDD, pParent){
	m_nSearchID = 0;
	m_pacSearchString = NULL;
}

CSearchDlg::~CSearchDlg(){
	if (globsearch) delete searchpacket;
	DestroyIcon(icon_search);
	if (m_pacSearchString){
		m_pacSearchString->Unbind();
		m_pacSearchString->Release();
	}
}

BOOL CSearchDlg::OnInitDialog(){
	CResizableDialog::OnInitDialog();
	theApp.searchlist->SetOutputWnd(&searchlistctrl);
	searchlistctrl.Init(theApp.searchlist);
	Localize();
	searchprogress.SetStep(1);
	global_search_timer = 0;
	globsearch = false;
	m_guardCBPrompt=false;

	m_ctrlSearchFrm.Init(IDI_NORMALSEARCH);
	m_ctrlDirectDlFrm.Init(IDI_DIRECTDOWNLOAD);

	icon_search=(HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_SEARCHRESULTS), IMAGE_ICON, 16, 16, 0);
	((CStatic*)GetDlgItem(IDC_SEARCHLST_ICO))->SetIcon(icon_search);
	
	m_ImageList.Create(16,16,theApp.m_iDfltImageListColorFlags|ILC_MASK,0,10);
	m_ImageList.SetBkColor(CLR_NONE);
	m_ImageList.Add(theApp.LoadIcon(IDI_BN_SEARCH));
	searchselect.SetImageList(&m_ImageList);

	AddAnchor(IDC_SDOWNLOAD,BOTTOM_LEFT);
	AddAnchor(IDC_SEARCHLIST,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_PROGRESS1,BOTTOM_LEFT,BOTTOM_RIGHT);

	AddAnchor(IDC_DDOWN_FRM, TOP_LEFT, TOP_RIGHT);
	AddAnchor(IDC_ELINK, TOP_LEFT, TOP_RIGHT);
	AddAnchor(IDC_STARTS, TOP_RIGHT);
	AddAnchor(IDC_CANCELS, TOP_RIGHT);
	AddAnchor(IDC_CLEARALL, TOP_RIGHT);
	AddAnchor(IDC_SEARCH_RESET, TOP_LEFT);
	AddAnchor(searchselect.m_hWnd,TOP_LEFT,TOP_RIGHT);
	AddAnchor(IDC_STATIC_DLTOof,BOTTOM_LEFT);
	AddAnchor(IDC_CATTAB2,BOTTOM_LEFT);
	ShowSearchSelector(false);
	m_lastclpbrd="";

	m_pacSearchString = new CCustomAutoComplete();
	m_pacSearchString->AddRef();
	if (m_pacSearchString->Bind(::GetDlgItem(m_hWnd, IDC_SEARCHNAME), ACO_UPDOWNKEYDROPSLIST | ACO_AUTOSUGGEST))
		m_pacSearchString->LoadList(CString(theApp.glob_prefs->GetConfigDir()) +  _T("\\") SEARCH_STRINGS_PROFILE);

	return true;
}

void CSearchDlg::DoDataExchange(CDataExchange* pDX){
	CResizableDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_SEARCHLIST, searchlistctrl);
	DDX_Control(pDX, IDC_PROGRESS1, searchprogress);
	DDX_Control(pDX, IDC_COMBO1, methodBox);
	DDX_Control(pDX, IDC_TypeSearch, Stypebox);
	DDX_Control(pDX, IDC_TAB1, searchselect);
	DDX_Control(pDX, IDC_SEARCH_FRM, m_ctrlSearchFrm);
	DDX_Control(pDX, IDC_DDOWN_FRM, m_ctrlDirectDlFrm);
	DDX_Control(pDX, IDC_CATTAB2, m_cattabs);
}


BEGIN_MESSAGE_MAP(CSearchDlg, CResizableDialog)
	ON_BN_CLICKED(IDC_STARTS, OnBnClickedStarts)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_CANCELS, OnBnClickedCancels)
	ON_BN_CLICKED(IDC_SDOWNLOAD, OnBnClickedSdownload)
	ON_NOTIFY(NM_DBLCLK, IDC_SEARCHLIST, OnNMDblclkSearchlist)
	ON_BN_CLICKED(IDC_CLEARALL, OnBnClickedClearall)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnTcnSelchangeTab1)
	ON_EN_CHANGE(IDC_SEARCHNAME, OnEnChangeSearchname)
	ON_CBN_SELCHANGE(IDC_TypeSearch, OnEnChangeSearchname)
	ON_MESSAGE(WM_CLOSETAB, OnCloseTab)
	ON_EN_CHANGE(IDC_SEARCHAVAIL , OnEnChangeSearchname)
	ON_EN_CHANGE(IDC_SEARCHEXTENTION, OnEnChangeSearchname)
	ON_EN_CHANGE(IDC_SEARCHMINSIZE, OnEnChangeSearchname)
	ON_EN_CHANGE(IDC_SEARCHMAXSIZE, OnEnChangeSearchname)
	ON_BN_CLICKED(IDC_SEARCH_RESET, OnBnClickedSearchReset)
	ON_EN_KILLFOCUS(IDC_ELINK, OnEnKillfocusElink)
END_MESSAGE_MAP()


// CSearchDlg message handlers

void CSearchDlg::OnBnClickedStarts(){
	searchprogress.SetPos(0);

	// ed2k-links
	if (GetDlgItem(IDC_ELINK)->GetWindowTextLength()){
		CString strlink;
		GetDlgItem(IDC_ELINK)->GetWindowText(strlink);
		GetDlgItem(IDC_ELINK)->SetWindowText("");

		AddEd2kLinksToDownload(strlink);
		return;
	}

	// start "normal" server-search
	if (GetDlgItem(IDC_SEARCHNAME)->GetWindowTextLength())
	{
		if (m_pacSearchString){
			CString strSearch;
			if (GetDlgItemText(IDC_SEARCHNAME, strSearch))
				m_pacSearchString->AddItem(strSearch, 0);
		}
		switch (methodBox.GetCurSel())
		{
		case 0:
		case 1:
			StartNewSearch();
			break;

		case 2:
		case 3:
			ShellOpenFile(CreateWebQuery());
			return;
		default:
			return;
		}
	}
}

void CSearchDlg::OnTimer(UINT nIDEvent){
	CResizableDialog::OnTimer(nIDEvent);
	if (theApp.serverconnect->IsConnected()){
		CServer* toask = theApp.serverlist->GetNextSearchServer();
		if (toask == theApp.serverlist->GetServerByAddress(theApp.serverconnect->GetCurrentServer()->GetAddress(),theApp.serverconnect->GetCurrentServer()->GetPort()))
			toask = theApp.serverlist->GetNextSearchServer();

		if (toask && theApp.serverlist->GetServerCount()-1 != servercount){
			servercount++;
			theApp.serverconnect->SendUDPPacket(searchpacket,toask,false);
			searchprogress.StepIt();
		}
		else
			OnBnClickedCancels();
	}
	else
		OnBnClickedCancels();
}

void CSearchDlg::OnBnClickedCancels(){
	canceld = true;
	if (globsearch){
		delete searchpacket;
		searchpacket = NULL;
	}
	globsearch = false;
	if (global_search_timer){
		KillTimer(global_search_timer);
		global_search_timer = 0;
		searchprogress.SetPos(0);
	}
	this->GetDlgItem(IDC_CANCELS)->EnableWindow(false);
	this->GetDlgItem(IDC_STARTS)->EnableWindow(true);
}


void CSearchDlg::LocalSearchEnd(uint16 count){
	if (!canceld && count > MAX_RESULTS)
		OnBnClickedCancels();
	if (!canceld){	
		if (!globsearch){
			this->GetDlgItem(IDC_STARTS)->EnableWindow(true);
			this->GetDlgItem(IDC_CANCELS)->EnableWindow(false);
		}
		else
			global_search_timer = SetTimer(1, 750, 0);

	}
}
void CSearchDlg::AddUDPResult(uint16 count){
	if (!canceld && count > MAX_RESULTS)
		OnBnClickedCancels();
}

void CSearchDlg::OnBnClickedSdownload(){
	//start download(s)
	DownloadSelected();
}

BOOL CSearchDlg::PreTranslateMessage(MSG* pMsg) 
{
	if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE))
	   	return FALSE;

	if( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_DELETE) && (pMsg->hwnd == GetDlgItem(IDC_SEARCHNAME)->m_hWnd) && (GetAsyncKeyState(VK_MENU)<0) )
		m_pacSearchString->Clear();

   	if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN)){
	   	if (pMsg->hwnd == GetDlgItem(IDC_SEARCHLIST)->m_hWnd)
			OnBnClickedSdownload();
	   	else if (pMsg->hwnd == GetDlgItem(IDC_SEARCHNAME)->m_hWnd || 
				 pMsg->hwnd == GetDlgItem(IDC_TypeSearch)->m_hWnd || 
				 pMsg->hwnd == GetDlgItem(IDC_EDITSEARCHMIN)->m_hWnd || 
				 pMsg->hwnd == GetDlgItem(IDC_EDITSEARCHMAX)->m_hWnd || 
				 pMsg->hwnd == GetDlgItem(IDC_EDITSEARCHAVAIBILITY)->m_hWnd || 
				 pMsg->hwnd == GetDlgItem(IDC_COMBO1)->m_hWnd || 
				 pMsg->hwnd == GetDlgItem(IDC_EDITSEARCHEXTENSION)->m_hWnd){
			if (m_pacSearchString && m_pacSearchString->IsBound() && pMsg->hwnd == GetDlgItem(IDC_SEARCHNAME)->m_hWnd){
				CString strText;
				GetDlgItem(IDC_SEARCHNAME)->GetWindowText(strText);
				if (!strText.IsEmpty()){
					GetDlgItem(IDC_SEARCHNAME)->SetWindowText(_T("")); // this seems to be the only chance to let the dropdown list to disapear
					GetDlgItem(IDC_SEARCHNAME)->SetWindowText(strText);
					((CEdit*)GetDlgItem(IDC_SEARCHNAME))->SetSel(strText.GetLength(), strText.GetLength());
				}
			}
			OnBnClickedStarts();
   		}
	}

	return CResizableDialog::PreTranslateMessage(pMsg);
}

void CSearchDlg::OnNMDblclkSearchlist(NMHDR *pNMHDR, LRESULT *pResult){
	OnBnClickedSdownload();
	*pResult = 0;
}

CString	CSearchDlg::CreateWebQuery()
{
	CString query,tosearch;
	unsigned long num;
	switch (methodBox.GetCurSel())
	{
	case 2:
		query = "http://www.filedonkey.com/search.html?";
		GetDlgItem(IDC_SEARCHNAME)->GetWindowText(tosearch);
		query += "pattern="+ToQueryString(tosearch);
		GetDlgItem(IDC_TypeSearch)->GetWindowText(tosearch);
		if (GetResString(IDS_SEARCH_AUDIO)==tosearch)
			tosearch="Audio";
		else if (GetResString(IDS_SEARCH_VIDEO)==tosearch)
			tosearch="Video";
		else if (GetResString(IDS_SEARCH_PRG)==tosearch)
			tosearch="Pro";
		else
			tosearch="All";
		query +="&media=" + tosearch + "&requestby=emule";

		GetDlgItem(IDC_EDITSEARCHMIN)->GetWindowText(tosearch);
		if (atol(tosearch)>0) query +="&min_size=" + tosearch+"M";
		GetDlgItem(IDC_EDITSEARCHMAX)->GetWindowText(tosearch);
		if (atol(tosearch)>0) query +="&max_size=" + tosearch+"M";

		break;
	case 3:
		// www.jigle.com
		//
		// Type				ID
		// --------------------------
		//   Any			0
		//   Audio			1
		//   Video			2
		//   Image			3
		//   Program		4
		//   Document		5
		//   Collection		6

		query = "http://www.jigle.com/search?";
		GetDlgItem(IDC_SEARCHNAME)->GetWindowText(tosearch);
		query += "p="+ToQueryString(tosearch) + "&ma=";
		GetDlgItem(IDC_EDITSEARCHAVAIBILITY)->GetWindowText(tosearch);
		if (atol(tosearch)>1000) tosearch="1000";
		else if (atoi(tosearch)>500) tosearch="500";
		else if (atoi(tosearch)>200) tosearch="200";
		else if (atoi(tosearch)>100) tosearch="100";
		else if (atoi(tosearch)>50) tosearch="50";
		else if (atoi(tosearch)>20) tosearch="20";
		else if (atoi(tosearch)>10) tosearch="10";
		else tosearch="1";
		query += tosearch +"&v=0&d=1&a=0&l=10";		//Cax2 might want to change to l=25 for more results per page... 
		GetDlgItem(IDC_TypeSearch)->GetWindowText(tosearch);
		if (GetResString(IDS_SEARCH_AUDIO)==tosearch)
			tosearch="1";
		else if (GetResString(IDS_SEARCH_VIDEO)==tosearch)
			tosearch="2";
		else if (GetResString(IDS_SEARCH_PICS)==tosearch)
			tosearch="3";
		else if (GetResString(IDS_SEARCH_PRG)==tosearch)
			tosearch="4";
		else
			tosearch="0";
		query +="&t=" +tosearch;
		GetDlgItem(IDC_EDITSEARCHEXTENSION)->GetWindowText(tosearch);
		query +="&x=" + ToQueryString(tosearch);
		GetDlgItem(IDC_EDITSEARCHMIN)->GetWindowText(tosearch);
		num=atol(tosearch);
		tosearch.Format("%u",((num>0)?num *1048576:1));
		query +="&sl=" +tosearch;
		GetDlgItem(IDC_EDITSEARCHMAX)->GetWindowText(tosearch);
		num=atol(tosearch);
		tosearch.Format(((num>0)?"%u":""),num * 1048576);
		query +="&su=" + tosearch;
		break;
	default:
		return "";
	}
	return query;
}


void CSearchDlg::DownloadSelected() {
	int index = -1; 
	POSITION pos = searchlistctrl.GetFirstSelectedItemPosition(); 
	while(pos != NULL) 
	{ 
		index = searchlistctrl.GetNextSelectedItem(pos); 
		if(index > -1) {
			theApp.downloadqueue->AddSearchToDownload((CSearchFile*)searchlistctrl.GetItemData(index ),m_cattabs.GetCurSel());
			searchlistctrl.Update(index);
		}
	} 
}


void CSearchDlg::Localize(){
	searchlistctrl.Localize();

	m_ctrlSearchFrm.SetWindowText(GetResString(IDS_SW_SEARCHBOX));
	m_ctrlDirectDlFrm.SetWindowText(GetResString(IDS_SW_DIRECTDOWNLOAD));

	GetDlgItem(IDC_MSTATIC3)->SetWindowText(GetResString(IDS_SW_NAME));
	GetDlgItem(IDC_MSTATIC7)->SetWindowText(GetResString(IDS_SW_TYPE));
	GetDlgItem(IDC_STATIC_FILTER)->SetWindowText(GetResString(IDS_FILTER));
	GetDlgItem(IIDC_FSTATIC2)->SetWindowText(GetResString(IDS_SW_LINK));
	GetDlgItem(IDC_STARTS)->SetWindowText(GetResString(IDS_SW_START));
	GetDlgItem(IDC_CANCELS)->SetWindowText(GetResString(IDS_CANCEL));
	GetDlgItem(IDC_CLEARALL)->SetWindowText(GetResString(IDS_REMOVEALLSEARCH));
	GetDlgItem(IDC_RESULTS_LBL)->SetWindowText(GetResString(IDS_SW_RESULT));
	GetDlgItem(IDC_SDOWNLOAD)->SetWindowText(GetResString(IDS_SW_DOWNLOAD));
	GetDlgItem(IDC_MSTATIC7)->SetWindowText(GetResString(IDS_TYPE));
	GetDlgItem(IDC_SEARCH_RESET)->SetWindowText(GetResString(IDS_PW_RESET));	
	GetDlgItem(IDC_SEARCHMINSIZE)->SetWindowText(GetResString(IDS_SEARCHMINSIZE)+":");
	GetDlgItem(IDC_SEARCHMAXSIZE)->SetWindowText(GetResString(IDS_SEARCHMAXSIZE)+":");
	GetDlgItem(IDC_SEARCHEXTENTION)->SetWindowText(GetResString(IDS_SEARCHEXTENTION)+":");
	GetDlgItem(IDC_SEARCHAVAIL)->SetWindowText(GetResString(IDS_SEARCHAVAIL)+":");
	GetDlgItem(IDC_METH)->SetWindowText(GetResString(IDS_METHOD));
	GetDlgItem(IDC_SD_MB1)->SetWindowText(GetResString(IDS_MBYTES));
	GetDlgItem(IDC_SD_MB2)->SetWindowText(GetResString(IDS_MBYTES));

	while (methodBox.GetCount()>0) methodBox.DeleteString(0);
	methodBox.AddString(GetResString(IDS_SERVER));
	methodBox.AddString(GetResString(IDS_GLOBALSEARCH));
	methodBox.AddString("Filedonkey");
	methodBox.AddString("Jigle");
	methodBox.SetCurSel(0);

	while (Stypebox.GetCount()>0) Stypebox.DeleteString(0);
	Stypebox.AddString(GetResString(IDS_SEARCH_ANY));
	Stypebox.AddString(GetResString(IDS_SEARCH_ARC));
	Stypebox.AddString(GetResString(IDS_SEARCH_AUDIO));
	Stypebox.AddString(GetResString(IDS_SEARCH_CDIMG));
	Stypebox.AddString(GetResString(IDS_SEARCH_PICS));
	Stypebox.AddString(GetResString(IDS_SEARCH_PRG));
	Stypebox.AddString(GetResString(IDS_SEARCH_VIDEO));
	Stypebox.SetCurSel(Stypebox.FindString(-1,GetResString(IDS_SEARCH_ANY)));
}

void CSearchDlg::OnBnClickedClearall()
{
	OnBnClickedCancels();
	DeleteAllSearchs();
}

void CSearchDlg::DoNewSearch(CString searchString, CString typeText,unsigned long min, unsigned long max, 
		int avaibility,CString extension, bool doGlobal){

	if (!theApp.serverconnect->IsConnected()) return;

		m_nSearchID++;
		theApp.searchlist->NewSearch(&searchlistctrl,typeText,m_nSearchID);
		canceld = false;

		long typeNemonic=      0x00030001;
		long extensionNemonic= 0x00040001;
		long avaibilityNemonic=0x15000101;
		long minNemonic=       0x02000101;
		long maxNemonic=	   0x02000102;
		byte stringParameter=1;
		byte typeParameter=2;
		byte numericParameter=3;
		int andParameter=0x0000;
		//int orParameter=0x0100;

		CString type="";
		if (GetResString(IDS_SEARCH_AUDIO)==typeText) type.Format("Audio"); 
		if (GetResString(IDS_SEARCH_VIDEO)==typeText) type.Format("Video"); 
		if (GetResString(IDS_SEARCH_PRG)==typeText) type.Format("Pro"); 
		if (GetResString(IDS_SEARCH_PICS)==typeText) type.Format("Image"); 

		CSafeMemFile data(100);
		uint16 nSize;
		char* formatC;

		if (extension.GetLength()>0 && extension.GetAt(0)!='.' ) extension="."+extension;

		if ( searchString.GetLength()==0 && extension.GetLength()==0) 
		{
			return;
		}

		int parametercount=0; //must be written parametercount-1 parmeter headers

		if ( searchString.GetLength()>0)
		{
		  parametercount++;
		  if (parametercount>1)
		      data.Write(&andParameter,2);
		}

		if (type.GetLength()>0)
		{
		  parametercount++;
		  if (parametercount>1)
		      data.Write(&andParameter,2);
		}
	  
		if (min>0)
		{
		  parametercount++;
		  if (parametercount>1)
			  data.Write(&andParameter,2);
		}
        
		if (max>0)
		{
		  parametercount++;
		  if (parametercount>1)
			  data.Write(&andParameter,2);
		}
        
		if (avaibility>0)
		{
		  parametercount++;
		  if (parametercount>1)
			  data.Write(&andParameter,2);
		}
        
		if (extension.GetLength()>0)
		{
		  parametercount++;
		  if (parametercount>1)
		      data.Write(&andParameter,2);
		}

        //body
		if (searchString.GetLength()>0) //search a string
		{
			data.Write(&stringParameter,1); //write the parameter type
			nSize = searchString.GetLength(); 
			data.Write(&nSize,2);  // write parameter length
			data.Write(searchString.GetBuffer() ,nSize); //write the searched string 
		}

		if (type.GetLength()>0)
		{
			data.Write(&typeParameter,1); //write the parameter type
			nSize=type.GetLength(); 
			data.Write(&nSize,2);   //write the length
			formatC=type.GetBuffer(); 
			data.Write(formatC,nSize); //write parameter
			data.Write(&typeNemonic,3); //nemonic for this kind of parameter (only 3 bytes!!)
		}

		if (min>0)
		{
			data.Write(&numericParameter,1); //write the parameter type
			data.Write(&min,4);		   //write the parameter
			data.Write(&minNemonic,4);    //nemonic for this kind of parameter
		}

		if (max>0)
		{
			data.Write(&numericParameter,1); //write the parameter type
			data.Write(&max,4);		   //write the parameter
			data.Write(&maxNemonic,4);    //nemonic for this kind of parameter
		}

		if (avaibility>0)
		{
			data.Write(&numericParameter,1); //write the parameter type
			data.Write(&avaibility,4);    //write the parameter
			data.Write(&avaibilityNemonic,4);  //nemonic for this kind of parameter
		}

		if (extension.GetLength()>0)
		{
			data.Write(&stringParameter,1); //write the parameter type
			nSize=extension.GetLength(); 
			data.Write(&nSize,2);   //write the length
			formatC=extension.GetBuffer(); 
			data.Write(formatC,nSize); //write parameter
			data.Write(&extensionNemonic,3); //nemonic for this kind of parameter (only 3 bytes!!)
		}


		Packet* packet = new Packet(&data);
		packet->opcode = OP_SEARCHREQUEST;
		theApp.uploadqueue->AddUpDataOverheadServer(packet->size);
		theApp.serverconnect->SendPacket(packet,false);

		if (doGlobal){
			if( theApp.glob_prefs->Score() ){
				theApp.serverlist->ResetSearchServerPos();
			}

			if (globsearch){
				delete searchpacket;
				searchpacket = NULL;
			}
			searchpacket = packet;
			searchpacket->opcode = OP_GLOBSEARCHREQ;
			servercount = 0;
			searchprogress.SetRange32(0,theApp.serverlist->GetServerCount()-1);
			globsearch = true;
		}
		else{
			globsearch = false;
			delete packet;
		}
		CreateNewTab(searchString,m_nSearchID);
	
}

void CSearchDlg::StartNewSearch(){
	if (!theApp.serverconnect->IsConnected())
		AfxMessageBox(GetResString(IDS_ERR_NOTCONNECTED),MB_ICONASTERISK);
	else{
		CString typeText;
		CString searchString;

		GetDlgItem(IDC_SEARCHNAME)->GetWindowText(searchString);
		GetDlgItem(IDC_TypeSearch)->GetWindowText(typeText);

		this->GetDlgItem(IDC_STARTS)->EnableWindow(false);
		this->GetDlgItem(IDC_CANCELS)->EnableWindow(true);

		CString sizeMin,sizeMax,extension,avaibilitystr,type;
		GetDlgItem(IDC_EDITSEARCHMIN)->GetWindowText(sizeMin);
		GetDlgItem(IDC_EDITSEARCHMAX)->GetWindowText(sizeMax);
		unsigned long max=atol(sizeMax.GetString())*1048576; 
		unsigned long min=atol(sizeMin.GetString())*1048576; 
		if (max==0 || max<min) max=2147483646;//max file size 

		GetDlgItem(IDC_EDITSEARCHEXTENSION)->GetWindowText(extension);
		GetDlgItem(IDC_EDITSEARCHAVAIBILITY)->GetWindowText(avaibilitystr); 

		DoNewSearch(searchString,typeText,min,max,atol(avaibilitystr.GetString()),extension,(methodBox.GetCurSel()==1));
	}
}

bool CSearchDlg::CreateNewTab(CString searchString,uint32 nSearchID){
    int iTabItems = searchselect.GetItemCount();
    for (int i = 0; i < iTabItems; i++){
        TCITEM tci;
        tci.mask = TCIF_PARAM;
        if (searchselect.GetItem(i, &tci) && tci.lParam == nSearchID)
			return false;
    }
	// add new tab
	TCITEM newitem;
	if (searchString.GetLength() == 0)
		searchString = "-";
	newitem.mask = TCIF_PARAM|TCIF_TEXT|TCIF_IMAGE;
	newitem.lParam = (LPARAM)nSearchID;
	newitem.pszText = searchString.GetBuffer();
	newitem.cchTextMax = (int)searchString.GetLength()+10;
	newitem.iImage = 0;
	uint16 itemnr = searchselect.InsertItem(searchselect.GetItemCount(),&newitem);
	if (!searchselect.IsWindowVisible())
		ShowSearchSelector(true);
	searchselect.SetCurSel(itemnr);
	searchlistctrl.ShowResults(nSearchID);
	return true;
}

void CSearchDlg::DeleteSearch(uint32 nSearchID){
	TCITEM item;
	item.mask = TCIF_PARAM;
	item.lParam = -1;
	int i;
	for (i = 0; i != searchselect.GetItemCount();i++){
		searchselect.GetItem(i,&item);
		if (item.lParam == nSearchID)
			break;
	}
	if (item.lParam != nSearchID)
		return;
	if ((!canceld) && (nSearchID == m_nSearchID))
		OnBnClickedCancels();  //Sony - cancel active search before closing active tab
	theApp.searchlist->RemoveResults(nSearchID);
	searchselect.DeleteItem(i);
	if (searchselect.GetItemCount()){
		searchselect.SetCurSel(0);
		item.mask = TCIF_PARAM;
		searchselect.GetItem(0,&item);
		searchlistctrl.ShowResults(item.lParam);
	}
	else{
		searchlistctrl.DeleteAllItems();
		ShowSearchSelector(false);
		searchlistctrl.NoTabs();
	}
}

void CSearchDlg::DeleteAllSearchs(){
	theApp.searchlist->Clear();
	searchlistctrl.DeleteAllItems();
	ShowSearchSelector(false);
	searchselect.DeleteAllItems();
}

void CSearchDlg::OnTcnSelchangeTab1(NMHDR *pNMHDR, LRESULT *pResult)
{
	TCITEM item;
	item.mask = TCIF_PARAM;
	int cur_sel = searchselect.GetCurSel();
	if (cur_sel == (-1))
		return;
	searchselect.GetItem(cur_sel,&item);
	searchlistctrl.ShowResults(item.lParam);
	*pResult = 0;
}


LRESULT CSearchDlg::OnCloseTab(WPARAM wparam, LPARAM lparam) {
	TCITEM item;
	item.mask = TCIF_PARAM;
	int i = (int)wparam;
	searchselect.GetItem(i,&item);
	int nSearchID = item.lParam;

	if ((!canceld) && (nSearchID == m_nSearchID))
		OnBnClickedCancels();  //Sony - cancel active search before closing active tab
	DeleteSearch(nSearchID);
	//theApp.searchlist->RemoveResults(nSearchID);

	return true;

}

void CSearchDlg::OnEnChangeSearchname()
{
		this->GetDlgItem(IDC_STARTS)->EnableWindow(true);
}

void CSearchDlg::OnBnClickedSearchReset()
{
	GetDlgItem(IDC_EDITSEARCHAVAIBILITY)->SetWindowText("");	
	GetDlgItem(IDC_EDITSEARCHEXTENSION)->SetWindowText("");	
	GetDlgItem(IDC_EDITSEARCHMIN)->SetWindowText("");	
	GetDlgItem(IDC_EDITSEARCHMAX)->SetWindowText("");	
	GetDlgItem(IDC_SEARCHNAME)->SetWindowText("");
	Stypebox.SetCurSel(Stypebox.FindString(-1,GetResString(IDS_SEARCH_ANY)));
	methodBox.SetCurSel(0);

	OnEnChangeSearchname();
}

void CSearchDlg::UpdateCatTabs() {
	int oldsel=m_cattabs.GetCurSel();
	m_cattabs.DeleteAllItems();
	for (int ix=0;ix<theApp.glob_prefs->GetCatCount();ix++)
		m_cattabs.InsertItem(ix,(ix==0)?GetResString(IDS_ALL):theApp.glob_prefs->GetCategory(ix)->title);
	if (oldsel<m_cattabs.GetItemCount()) oldsel=0;

	m_cattabs.SetCurSel(oldsel);
	int flag;
	flag=(m_cattabs.GetItemCount()>1) ? SW_SHOW:SW_HIDE;
	
	this->GetDlgItem(IDC_CATTAB2)->ShowWindow(flag);
	this->GetDlgItem(IDC_STATIC_DLTOof)->ShowWindow(flag);
}

void CSearchDlg::SearchClipBoard() {
	if (m_guardCBPrompt) return;

	CString clpbrd=theApp.CopyTextFromClipboard();
	if (clpbrd=="") return;

	if (clpbrd.Compare(m_lastclpbrd)==0) return;

	if (clpbrd.Left(13).CompareNoCase("ed2k://|file|")==0) {
		m_guardCBPrompt=true;
		if (AfxMessageBox(GetResString(IDS_ADDDOWNLOADSFROMCB)+clpbrd,MB_YESNO)==IDYES)
			AddEd2kLinksToDownload(clpbrd,0);
	}
	m_lastclpbrd=clpbrd;
	m_guardCBPrompt=false;

}

void CSearchDlg::AddEd2kLinksToDownload(CString strlink,uint8 cat){
	CString resToken;
	int curPos=0;

	resToken= strlink.Tokenize("\t\n\r",curPos);
	while (resToken != "")
	{
		
		if (resToken.Right(1)!="/") resToken+="/";
		try {
			CED2KLink* pLink = CED2KLink::CreateLinkFromUrl(resToken.Trim());
			_ASSERT( pLink !=0 );
			if ( pLink->GetKind() == CED2KLink::kFile) {
				theApp.downloadqueue->AddFileLinkToDownload(pLink->GetFileLink(),cat);
			} else {
				delete pLink; // [i_a] memleak
				throw CString("bad link");
			}
			delete pLink;
		} catch(CString error){
			OUTPUT_DEBUG_TRACE();
			char buffer[200];
			sprintf(buffer,GetResString(IDS_ERR_INVALIDLINK),error.GetBuffer());
			theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_LINKERROR), buffer);
		}
		resToken= strlink.Tokenize("\t\n\r",curPos);
	}
}

void CSearchDlg::OnEnKillfocusElink()
{
	CString content;
	GetDlgItem(IDC_ELINK)->GetWindowText(content);
	if (content.GetLength()==0 || content.Find('\n')==-1) return;
	content.Replace("\n","\r\n");
	content.Replace("\r\r","\r");
	GetDlgItem(IDC_ELINK)->SetWindowText(content);
}
CString	CSearchDlg::ToQueryString(CString str){
	CString sTmp = URLEncode(str);
	sTmp.Replace("%20","+");
	return sTmp;
}

void CSearchDlg::ShowSearchSelector(bool visible){
	WINDOWPLACEMENT wpSearchWinPos;
	WINDOWPLACEMENT wpSelectWinPos;
	searchselect.GetWindowPlacement(&wpSelectWinPos);
	searchlistctrl.GetWindowPlacement(&wpSearchWinPos);
	if (visible)
		wpSearchWinPos.rcNormalPosition.top = wpSelectWinPos.rcNormalPosition.bottom;
	else
		wpSearchWinPos.rcNormalPosition.top = wpSelectWinPos.rcNormalPosition.top;
	searchselect.ShowWindow( ((visible)? SW_SHOW : SW_HIDE) );
	RemoveAnchor(searchlistctrl);
	searchlistctrl.SetWindowPlacement(&wpSearchWinPos);
	AddAnchor(searchlistctrl,TOP_LEFT,BOTTOM_RIGHT);
	GetDlgItem(IDC_CLEARALL)->ShowWindow((visible) ? SW_SHOW:SW_HIDE);
}

BOOL CSearchDlg::SaveSearchStrings()
{
	if (m_pacSearchString == NULL)
		return FALSE;
	return m_pacSearchString->SaveList(CString(theApp.glob_prefs->GetConfigDir()) + _T("\\") SEARCH_STRINGS_PROFILE);
}
