/* Refractor - Decompiler Plug-in for Reflector
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#pragma once

using namespace System;
using namespace System::Collections;
using namespace System::Reflection;
using namespace System::Windows::Forms;

using namespace Reflector::Application;
using namespace Reflector::Browser;
using namespace Reflector::ComponentModel;
using namespace Reflector::Library;

namespace Refractor {
namespace Commands {

/*public __gc class MemberHelper {
  public:
	static Assembly *GetAssembly(MemberInfo *memberInfo, Assembly *assemblies[]) {
		Module *module = GetModule(memberInfo, assemblies);
		return module == NULL ? NULL : module->Assembly;
	}

	static Module *GetModule(MemberInfo *memberInfo, Assembly *assemblies[]) {
		Type *type = dynamic_cast<Type *>(memberInfo);
		if (type != NULL)
			return type->Module;

		if (memberInfo->DeclaringType != NULL)
			return memberInfo->DeclaringType->Module;

		for (int i(0); i < assemblies->Length; i++) {
			Module *modules[] = assemblies[i]->GetModules();
			for (int i(0); i < modules->Length; i++) {
				Module *module = modules[i];
				foreach (MethodInfo methodInfo in module.GetMethods())
					if (MemberHelper.Equals(methodInfo, memberInfo))
						return module;
				foreach (FieldInfo fieldInfo in module.GetFields())
					if (MemberHelper.Equals(fieldInfo, memberInfo))
						return module;
			}
		}
		return NULL;
	}
};*/

public __gc class Decompiler : public ICommand {
  private:
	IApplication *application;
	NavigationPanel *panel;

  public:
	Decompiler() :
		application(NULL),
		panel(NULL)
	{}

	__property String *get_Name() {
		return S"Refractor Decompiler";
	}

	__property String *get_Description() {
		return S"The Exemplar decompiler in a crummy window.";
	}

	__property String *get_Url() {
		return S"http://www.ninetjer.org/refractor/";
	}

	__property String *get_Copyright() {
		return S"Jay Freeman (saurik)";
	}

	__property void set_Application(IApplication *value) {
		application = value;
	}

	__property IApplication *get_Application() {
		return application;
	}

	__property bool get_Enabled() {
		if (application == NULL) return false;
		IBrowserNode *node = application->Browser->Current;
		if (node == NULL || node->Value == NULL) return false;
		MethodBase *method = dynamic_cast<MethodBase *>(node->Value);
		return method != NULL;
	}

	void ContextPanel_Navigate(Object *s, MemberEventArgs *e) {      
		if (application != NULL && application->Browser != NULL)
			application->Browser->GoToMember(e->Member);
	}

	void Run() {
		if (panel == NULL) {
			panel = new NavigationPanel();
			panel->Activate();
			panel->Dock = DockStyle::Fill;
			panel->Navigate += new MemberEventHandler(this, ContextPanel_Navigate);
		}

		/*Module *module = GetCurrentModule();
		if (module == NULL) return;*/

		IBrowserNode *node = application->Browser->Current;
		MethodBase *method = dynamic_cast<MethodBase *>(node->Value);

		if (method != NULL) {
			panel->Formatter = NULL;

			application->ToolForm->Text = S"Refractor Decompiler";
			application->ToolForm->Open(panel);
		}
	}

	/*Module *GetCurrentModule() {
		MethodBase *method = dynamic_cast<MethodBase *>(application->Browser->Current);
		return method == NULL ? NULL : MemberHelper->GetModule(method, application->AssemblyManager->Assemblies);
	}*/
};

} }