//------------------------------------------------------------------------------
// emFpPlugin.h
//
// Copyright (C) 2006-2008 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// 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 version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#ifndef emFpPlugin_h
#define emFpPlugin_h

#ifndef emRec_h
#include <emCore/emRec.h>
#endif

#ifndef emPanel_h
#include <emCore/emPanel.h>
#endif


//==============================================================================
//================================= emFpPlugin =================================
//==============================================================================

class emFpPlugin : public emStructRec {

public:

	// Record class for a file panel plugin. Such a plugin is able to create
	// a panel for showing (and maybe editing) a file. An instance of this
	// record class holds the configuration of such a plugin. It is usually
	// loaded from a configuration file (see emFpPluginList).

	emFpPlugin();
		// Construct empty.

	virtual ~emFpPlugin();
		// Destructor.


	// - - - - - Member Records - - - - -

	emTArrayRec<emStringRec> FileTypes;
		// Array of file types the plugin is able to handle. Each entry
		// must be a file name suffix including the leading dot, or the
		// special string "file" for accepting all regular files, or the
		// special string "directory" for accepting directories.

	emDoubleRec Priority;
		// Priority of the plugin. If there are two plugins able to
		// handle a file, the one with the higher priority is taken
		// first.

	emStringRec Library;
		// Name of the dynamic library containing the plugin function
		// (just the pure name, read comments on emTryOpenLib).

	emStringRec Function;
		// Name of the plugin function. It must match the interface
		// defined by emFpPluginFunc.

	class PropertyRec : public emStructRec {
	public:
		PropertyRec();
		virtual ~PropertyRec();
		emStringRec Name;
		emStringRec Value;
	};
	emTArrayRec<PropertyRec> Properties;
		// Any number of plugin-defined properties in form of name/value
		// pairs.

	// - - - - - End of Member Records - - - - -


	PropertyRec * GetProperty(const char * name);
		// Search for a plugin-defined property. Returns NULL if not
		// found.

	emPanel * TryCreateFilePanel(
		emPanel::ParentArg parent, const emString & name,
		const emString & path
	) throw(emString);
		// Create a file panel via this plugin.
		// Arguments:
		//   parent - Parent of the panel.
		//   name   - Name of the panel.
		//   path   - Path name of the file to be shown.
		// Returns: The created panel.
		// Throws: An error message on failure.

	virtual const char * GetFormatName() const;
		// The file format name of this record file format.

private:
	void * CachedFunc;
	emString CachedFuncLib;
	emString CachedFuncName;
};


//==============================================================================
//=============================== emFpPluginFunc ===============================
//==============================================================================


extern "C" {
	typedef emPanel * (*emFpPluginFunc) (
		emPanel::ParentArg parent, const emString & name,
		const emString & path, emFpPlugin * plugin,
		emString * errorBuf
	);
		// Type of the plugin function of an emFpPlugin. Such a function
		// creates a panel for showing a file.
		// Arguments:
		//   parent   - Parent of the panel.
		//   name     - Name of the panel.
		//   path     - Path name of the file to be shown.
		//   plugin   - The plugin record (mainly for reading the
		//              plugin-defined properties).
		//   errorBuf - For returning an error message on failure.
		// Returns: The created panel, or NULL on failure.
}


//==============================================================================
//=============================== emFpPluginList ===============================
//==============================================================================

class emFpPluginList : public emModel {

public:

	// Class for a model containing a list of all the configured file panel
	// plugins. The plugins configurations are loaded from a certain
	// directory.

	static emRef<emFpPluginList> Acquire(emRootContext & rootContext);
		// Acquire the emFpPluginList.

	emPanel * CreateFilePanel(
		emPanel::ParentArg parent, const emString & name,
		const emString & path, int alternative=0
	);
		// Create a panel for a file. This calls the appropriate plugin.
		// On failure, a panel showing the error message is created.
		// Arguments:
		//   parent      - Parent of the panel.
		//   name        - Name of the panel.
		//   path        - Path name of the file to be shown.
		//   alternative - If there are multiple plugins able to show
		//                 the file, the one with the highest priority
		//                 is chosen if this argument is 0. If this
		//                 argument is 1, the one with the
		//                 second-highest priority is chosen, and so on.
		// Returns: The created panel.

	emPanel * CreateFilePanel(
		emPanel::ParentArg parent, const emString & name,
		const emString & absolutePath, int statErr, long statMode,
		int alternative=0
	);
		// This method exists for optimization. It's like above, but the
		// caller knows more about the file.
		// Arguments:
		//   parent       - Parent of the panel.
		//   name         - Name of the panel.
		//   absolutePath - Absolute path name of the file to be shown.
		//   statErr      - Zero if calling stat on the file was
		//                  successful, otherwise the resulting value of
		//                  errno.
		//   statMode     - st.st_mode from calling stat on the file.
		//   alternative  - Like with the above method.
		// Returns: The created panel.

protected:

	emFpPluginList(emContext & context, const emString & name);
	virtual ~emFpPluginList();

private:

	static int CmpReversePluginPriorities(
		emFpPlugin * const * obj1, emFpPlugin * const * obj2,
		void * context
	);

	emArray<emFpPlugin*> Plugins;
		// Sorted by descending priority, secondly by file name.
};


#endif
