//
// DynamicCodeLoader.h
//
// $Id: //poco/Main/WebWidgets/include/Poco/WebWidgets/DynamicCodeLoader.h#2 $
//
// Library: WebWidgets
// Package: Core
// Module:  DynamicCodeLoader
//
// Definition of the DynamicCodeLoader class.
//
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//


#ifndef WebWidgets_DynamicCodeLoader_INCLUDED
#define WebWidgets_DynamicCodeLoader_INCLUDED


#include "Poco/WebWidgets/Renderable.h"
#include "Poco/WebWidgets/RequestProcessor.h"
#include "Poco/WebWidgets/View.h"
#include "Poco/URI.h"
#include "Poco/FIFOEvent.h"
#include <vector>


namespace Poco {
namespace WebWidgets {


class WebWidgets_API DynamicCodeLoader: public Renderable, public RequestProcessor
	/// A DynamicCodeLoader loads Javascript GUI code from an URL
	/// and adds a creator function to the Page
{
public:
	typedef Poco::AutoPtr<DynamicCodeLoader> Ptr;
	
	static const std::string EV_LOAD;
	
	Poco::FIFOEvent<View::Ptr> beforeLoad; /// Thrown before a load
	Poco::FIFOEvent<DynamicCodeLoader*> generateCode;

	DynamicCodeLoader(View* pParent, const Poco::URI& uri, const std::string& fctName, View::Ptr pView);
		/// Makes the code available at URI, containing JS code
		/// Adds a factory function named fctName() to the js file
		/// which will return the JS GUI component.
		/// fctName and pView must not be empty
		/// pParent must not be empty, defines the View to which the dynamic code is added
		
	bool operator < (const DynamicCodeLoader& other) const;
		/// Compares loaders by fctname
		
	const std::string& functionName() const;
		/// Returns the function name
		
	const std::string& loaderFunctionName() const;
		/// Returns the function name used to load the js. Loads only the parent,
		/// none of the dependent Children

	const std::string& loadAllFunctionName() const;
		/// Returns the function name used to load the js. Loads all the dependent children
		
	View::Ptr view() const;
		/// Returns the view
		
	void setViewCode(const std::string& jsCode);
		/// Sets the JS code for the view
	
	const std::string& getViewCode() const;
		/// Returns the JS code for the view
		
	const Poco::URI& uri() const;
	
	View* parent() const;
		
	// RequestProcessor
	void handleForm(const std::string& field, const std::string& value);
		/// Handles a form field submitted by the client.
		///
		/// The default implementation does nothing.
	
	void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
		/// Handles onload
		
	bool serializeJSON(std::ostream& out, const std::string& name);
		/// Sends the view as js to out, param name is ignored
		
	void setSuccessCall(const std::string& jsFct);
		/// The JS fucntion which should be called on success
		
	const std::string& getSuccessCall() const;
	
	void setErrorCall(const std::string& jsFct);
		/// The JS fucntion which should be called on success
		
	const std::string& getErrorCall() const;

	void addDependency(DynamicCodeLoader* pLoader);
		/// Tells this loader that it should first invoke pLoader
		/// before loading itself

	const std::vector<const DynamicCodeLoader*>& dependentParents() const;
		/// Gets all parents that depend on the success of the child

	const std::vector<const DynamicCodeLoader*>& dependencies() const;
		/// Gets all children that must be loaded before this code
protected:
	~DynamicCodeLoader();
		/// Destroys the DynamicCodeLoader.

	void addDependentParent(const DynamicCodeLoader* pLoader);
		/// Adds another DynamicCodeLoader that depends on the success of this loader
		/// For example, if loader1 uses a panel from loader2,
		/// you add loader1 to loader2:
		///     loader2->addDependendParent(loader1);

private:
	View*       _pParent;
	Poco::URI   _uri;
	std::string _fctName;
	std::string _loaderFct;
	std::string _loadAllFct;
	View::Ptr   _pView;
	std::string _code;
	std::string _success;
	std::string _error;
	std::vector<const DynamicCodeLoader*> _dependencies;
	std::vector<const DynamicCodeLoader*> _dependentParents;
};


inline View* DynamicCodeLoader::parent() const
{
	return _pParent;
}


inline const std::string& DynamicCodeLoader::functionName() const
{
	return _fctName;
}

		
inline View::Ptr DynamicCodeLoader::view() const
{
	return _pView;
}


inline void DynamicCodeLoader::setViewCode(const std::string& jsCode)
{
	_code = jsCode;
}

	
inline const std::string& DynamicCodeLoader::getViewCode() const
{
	return _code;
}


inline const std::string& DynamicCodeLoader::loaderFunctionName() const
{
	return _loaderFct;
}


inline const std::string& DynamicCodeLoader::loadAllFunctionName() const
{
	return _loadAllFct;
}


inline bool DynamicCodeLoader::operator < (const DynamicCodeLoader& other) const
{
	return _fctName < other._fctName;
}


inline const Poco::URI& DynamicCodeLoader::uri() const
{
	return _uri;
}


inline void DynamicCodeLoader::setSuccessCall(const std::string& jsFct)
{
	_success = jsFct;
}

		
inline const std::string& DynamicCodeLoader::getSuccessCall() const
{
	return _success;
}
	
	
inline void DynamicCodeLoader::setErrorCall(const std::string& jsFct)
{
	_error = jsFct;
}

		
inline const std::string& DynamicCodeLoader::getErrorCall() const
{
	return _error;
}


inline void DynamicCodeLoader::addDependency(DynamicCodeLoader* pLoader)
{
	if (pLoader) 
	{
		pLoader->addDependentParent(this);
		_dependencies.push_back(pLoader);
	}
}


inline void DynamicCodeLoader::addDependentParent(const DynamicCodeLoader* pLoader)
{
	if (pLoader) _dependentParents.push_back(pLoader);
}


inline const std::vector<const DynamicCodeLoader*>& DynamicCodeLoader::dependentParents() const
{
	return _dependentParents;
}


inline const std::vector<const DynamicCodeLoader*>& DynamicCodeLoader::dependencies() const
{
	return _dependencies;
}

	
} } // namespace Poco::WebWidgets


#endif // WebWidgets_DynamicCodeLoader_INCLUDED
