/*******************************************************************************
  TPI - flexible but useless plug-in framework.
  Copyright (C) 2002-2009 Silky

  This library is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free
  Software Foundation; either version 2.1 of the License, or (at your option)
  any later version.

  This library 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 Lesser General Public License
  for more details.

  You should have received a copy of the GNU Lesser General Public License along
  with this library; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  $Id: functions.cpp 253 2010-02-24 05:34:17Z sirakaba $
*******************************************************************************/

//******************************************************************************
//    ファイル読み込み
//******************************************************************************

#include "lychee.h"
#include "frm_main.h"
#include "dlg_make.h"
#include "functions.h"

//******************************************************************************
//    コントロール処理系関数
//******************************************************************************

bool TreeView_CheckNewerItem(wxTreeCtrl * tree_ctrl, wxTreeItemId idParent, const wxString & szDirPath, bool bReallyMake)
{
	// 最初の子アイテムを取得。
	wxTreeItemIdValue idv;
	wxTreeItemId idChild = tree_ctrl->GetFirstChild(idParent, idv);
	wxChar cSep = wxFileName::GetPathSeparator();
	while (idChild.IsOk())
	{
		// アイテムと名前が同じならOK。
		if (tree_ctrl->GetItemText(idChild) == szDirPath.BeforeFirst(cSep))
		{
			// これ以下の階層が無い場合。
			if (szDirPath.Find(cSep) == wxNOT_FOUND)
			{
				return bReallyMake;
			}

			// まだ階層が有る場合、再帰。
			return TreeView_CheckNewerItem(tree_ctrl, idChild, szDirPath.AfterFirst(cSep), bReallyMake);
		}

		idChild = tree_ctrl->GetNextSibling(idChild);
	}

	// 対象が無い場合には作成。
	if (! szDirPath.IsEmpty())
	{
		if (! bReallyMake)
		{
			// 確認するだけならここで終了。
			return true;
		}

		// 2階層以上深い場合にも対応。
		wxString szTemp = szDirPath;
		wxTreeItemId idTemp = idParent;
		do
		{
			// 展開してから作成。
			idTemp = tree_ctrl->AppendItem(idTemp, szTemp.BeforeFirst(cSep), 0, 1);
			szTemp = szTemp.AfterFirst(cSep);
		}
		while (szTemp.Find(cSep) != wxNOT_FOUND);

		// 最後に空でない場合にはもう1階層作成。
		if (! szTemp.IsEmpty())
		{
			tree_ctrl->AppendItem(idTemp, szTemp, 0, 1);
		}
	}

	return false;
}

wxString TreeView_GetItemPath(wxTreeCtrl * tree_ctrl, wxTreeItemId idItem)
{
	wxString szItemName = tree_ctrl->GetItemText(idItem), szNodePath = wxEmptyString;
	wxChar cSep = wxFileName::GetPathSeparator();

	// アイテムの名前を取得。
	while (! szItemName.IsEmpty())
	{
		if (szItemName == wxT("-----"))
		{
			break;
		}

		// パスに追加。
		szNodePath = szItemName + cSep + szNodePath;

		// 親アイテムに遡る。
		idItem = tree_ctrl->GetItemParent(idItem);
		if (idItem == tree_ctrl->GetRootItem())
		{
			// ここにくるのは書庫内全表示時。
			szNodePath = wxT("*");
			break;
		}
		szItemName = tree_ctrl->GetItemText(idItem);
	}

	return (szNodePath.Find(cSep) == wxNOT_FOUND) ? szNodePath : szNodePath.BeforeLast(cSep);
}

//******************************************************************************
//    諸処理関数
//******************************************************************************

// ディレクトリを新規に作成。
wxFileName MakeDirPath(wxFileName fnPath, wxString szBase, bool bAct)
{
	// とりあえず作ってみる。
	wxFileName fnDir = fnPath;
	fnDir.AppendDir(szBase);
	if (! fnDir.DirExists() && ! ::wxFileExists(fnDir.GetPath()))
	{
		if (! bAct || fnDir.Mkdir())
		{
			return fnDir;
		}
	}

	// ダメなら"_%d"を付加して試行。
	for (int i = 0; i < 255; i++)
	{
		fnDir = fnPath;
		fnDir.AppendDir(szBase + wxString::Format(wxT("_%d"), i));
		if (! fnDir.DirExists() && ! ::wxFileExists(fnDir.GetPath()))
		{
			if (! bAct || fnDir.Mkdir())
			{
				return fnDir;
			}
		}
	}

	// エラー終了。
	fnDir.Clear();
	return fnDir;
}

wxArrayString MakeTargetFileList(MainFrame * frm, bool fOnlyOneFile)
{
	wxArrayString as;
	const int nState = frm->list_ctrl->GetSelectedItemCount() == 0 ? wxLIST_STATE_DONTCARE : wxLIST_STATE_SELECTED;
	long nId = frm->list_ctrl->GetNextItem(-1, wxLIST_NEXT_ALL, nState);
	while (nId != -1)
	{
		as.Add(frm->list_ctrl->showFileInfo[nId].szStoredName);
		if (fOnlyOneFile)
		{
			break;
		}
		nId = frm->list_ctrl->GetNextItem(nId, wxLIST_NEXT_ALL, nState);
	}

	return as;
}

bool WillMakeDirByArcName(MainFrame * frm, MakeDialog * mk)
{
	if (mk->chDirMake->GetSelection() != 2)
	{
		return mk->chDirMake->GetSelection() == 1;
	}

	// ルートにディレクトリとファイル合わせて2個以上あるとき、ディレクトリを作成。
	wxTreeItemId tiArcRoot = frm->tree_ctrl->GetLastChild(frm->tree_ctrl->GetRootItem());
	switch (frm->tree_ctrl->GetChildrenCount(tiArcRoot, false))
	{
	case 0:
	{
		// ディレクトリがないので、ルートにファイルが2個以上あるかどうかを判定。
		bool fFlag = false;
		for (size_t i = 0; i < frm->fileinfo.GetCount(); i++)
		{
			if (frm->fileinfo[i].fnFileName.GetPath().IsEmpty())
			{
				// ファイルはルートにある。
				if (fFlag)
				{
					return true;
				}

				fFlag = true;
			}
		}
		break;
	}
	case 1:
		// ディレクトリが1個なので、ルートにファイルがないかどうかを判定。
		for (size_t i = 0; i < frm->fileinfo.GetCount(); i++)
		{
			// ディレクトリメンバが格納されている場合には、その名前がツリービューのアイテム名に一致した場合はカウントしない。
			if (frm->fileinfo[i].fnFileName.GetPath().IsEmpty() && frm->fileinfo[i].fnFileName.GetFullName() != frm->tree_ctrl->GetItemText(frm->tree_ctrl->GetLastChild(tiArcRoot)))
			{
				return true;
			}
		}
		break;
	default:
		// ディレクトリだけで2個以上あるので、自動的に展開先ディレクトリを作成。
		return true;
	}

	return false;
}

wxString GetFileTypeName(wxFileName fn)
{
	wxString szExt = fn.GetExt().MakeUpper();
	wxString sz = szExt + (szExt.IsEmpty() ? wxEmptyString : wxT(" ")) + _("file");
	wxFileType * ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(szExt);
	if (ftFile)
	{
		ftFile->GetDescription(& sz);
	}
	return sz;
}

wxIcon GetFileTypeIcon(wxFileName fn)
{
	wxIcon icon;
	wxIconLocation ilFile;
	wxFileType * ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(fn.GetExt());
	if (ftFile && ftFile->GetIcon(& ilFile))
	{
		if (! ::wxFileExists(ilFile.GetFileName()))
		{
			icon.CopyFromBitmap(wxBitmap((ilFile.GetFileName() == wxT("%1") || ilFile.GetFileName() == wxT("\"%1\"")) ? L_DIR_S_ICO wxT("exe.png") : L_DIR_S_ICO wxT("file.png"), wxBITMAP_TYPE_ANY));
		}
		else
		{
			icon = wxIcon(ilFile);
		}
	}
	else
	{
		icon.CopyFromBitmap(wxBitmap(L_DIR_S_ICO wxT("file.png"), wxBITMAP_TYPE_ANY));
	}
	return icon;
}
