// == LICENSE INFORMATION ==
/*
 * First author tiritomato 2013.
 * This program is distributed under the GNU General Public License(GPL).
 * support blog (Japanese only) http://d.hatena.ne.jp/tiri_tomato/
 */
// == LICENSE INFORMATION ==

#include "CustomControls/CustomControls.hpp"

static bool initialResult = (UVTexIntegra::CustomAssemblyResolver::Singleton() != nullptr) && (MQCLI::Initialize(gcnew UVTexIntegra::CustomControls::Plugin()));

//! @brief ファイルのアップデートコピーにトライします
//! @details コピー先のファイルサイズが異なるか、バージョンまたは更新日時が異なる時、ファイルはコピー元からコピー先へコピーされます。
void TryUpdateFile(System::String^ srcFile, System::String^ destDir)
{
    bool isEqual = false;
	if (System::IO::File::Exists(srcFile))
	{
		System::String^ fileName = System::IO::Path::GetFileName(srcFile);
		System::String^ destFile = System::IO::Path::Combine(destDir, fileName);
		try
		{
			if (System::IO::File::Exists(destFile))
			{
				System::IO::FileInfo^ srcInfo = gcnew System::IO::FileInfo(srcFile);
				System::IO::FileInfo^ destInfo = gcnew System::IO::FileInfo(destFile);
				if ((srcInfo->Length == destInfo->Length) && (srcInfo->LastWriteTimeUtc == destInfo->LastWriteTimeUtc))
				{
					System::Diagnostics::FileVersionInfo^ srcVer = System::Diagnostics::FileVersionInfo::GetVersionInfo(srcFile);
					System::Diagnostics::FileVersionInfo^ destVer = System::Diagnostics::FileVersionInfo::GetVersionInfo(destFile);
					isEqual = (srcVer->FileVersion == destVer->FileVersion);
				}
			}
		}
		catch (System::Exception^) { isEqual = false; }
		if (isEqual == false)
		{
			try
			{
				System::IO::File::Copy(srcFile, destFile, true);
				isEqual = true;
			}
			catch (System::Exception^) { isEqual = false; }
		}
	}
	if (isEqual == false) System::Windows::Forms::MessageBox::Show(srcFile, "File Update Failed");
}

UVTexIntegra::CustomAssemblyResolver::CustomAssemblyResolver()
{
	System::Reflection::Assembly^ ExecutingAssembly = System::Reflection::Assembly::GetExecutingAssembly();
	try
	{
		DllLoadDirectory = System::IO::Path::Combine(
			System::IO::Path::GetDirectoryName(ExecutingAssembly->Location),
			System::IO::Path::GetFileNameWithoutExtension(ExecutingAssembly->Location) + "\\lib");
	}
	catch (System::Exception^) { DllLoadDirectory = nullptr; }
	System::AppDomain::CurrentDomain->AssemblyResolve += gcnew System::ResolveEventHandler(this,&CustomAssemblyResolver::CustomAssemblyResolve);

	HMODULE hGdiPlus = LoadLibrary("GdiPlus");
#if _DEBUG
	std::vector<char> buf(2, '\0');
#else
	std::vector<char> buf(MAX_PATH + 1, '\0');
#endif
	for (DWORD sz = buf.size(); (sz - 1) <= GetModuleFileName(hGdiPlus, &(buf[0]), (sz - 1)); sz = buf.size()) buf.resize(sz * 2, '\0');
	TryUpdateFile(gcnew System::String(&buf[0]), DllLoadDirectory);
}

System::Reflection::Assembly^ UVTexIntegra::CustomAssemblyResolver::CustomAssemblyResolve(System::Object^ sender, System::ResolveEventArgs^ args)
{
	System::Reflection::AssemblyName^ TargetName = gcnew System::Reflection::AssemblyName(args->Name);
	System::Reflection::Assembly^ ExecutingAssembly = System::Reflection::Assembly::GetExecutingAssembly();
	array<System::Reflection::AssemblyName^>^ ReferencedAssemblies = ExecutingAssembly->GetReferencedAssemblies();

	for each (System::Reflection::AssemblyName^ name in ReferencedAssemblies)
	{
		if (System::Reflection::AssemblyName::ReferenceMatchesDefinition(TargetName, name))
		{
			// check preloaded assembly
			for each (System::Reflection::Assembly^ assm in System::AppDomain::CurrentDomain->GetAssemblies())
			{
				if (System::Reflection::AssemblyName::ReferenceMatchesDefinition(TargetName, assm->GetName())) return assm;
			}

			// check custom dll folder
			if (System::IO::Directory::Exists(DllLoadDirectory) == false) return nullptr;

			System::String^ DllPath = System::IO::Path::Combine(DllLoadDirectory, TargetName->Name + ".dll");
			if (System::IO::File::Exists(DllPath))
			{
				try { return System::Reflection::Assembly::LoadFrom( DllPath ); }
				catch ( System::Exception^ ) { break; }
			}
		}
	}
	
	return nullptr;
}


