#pragma once

#include "Cres.h"
#include "binding/Binding.h"
#include "binding/BindingException.h"
#include "binding/BindingProvider.h"
#include "binding/EvaluationOptions.h"
#include "binding/ReferenceListener.h"
#include "util/Util.h"
#include "binding/BindingProcessor.h"
#include "binding/BindingProvider.h"
#include "util/ThreadPoolCachedEx.h"
#include <list>
#include <set>

class DefaultBindingProcessor : public BindingProcessor
{
private:
    BindingProviderPtr provider;
    EvaluatorPtr evaluator;

    ThreadPoolCachedExPtr executionService;
    bool disableStartupConcurrency;
    bool shareConcurrency;
	std::list<ReferenceListenerPtr>  listeners;

    bool stopped;
	bool enabled;
	void startImpl(bool concurrentProcessing);

	void initBinding(BindingPtr binding, EvaluationOptionsPtr options);
	void addReferenceListener(BindingPtr binding, EvaluationOptionsPtr options, ReferencePtr reference);
    void writeReference(int method, ReferencePtr destination, ReferencePtr cause, AgObjectPtr value, ChangeCachePtr cache);
    bool checkCondition(EvaluationOptionsPtr options, EvaluationEnvironmentPtr evaluationEnvironment);

public:
	bool start();

	void start(bool concurrentProcessing);

	void stop();
	bool isStopped();

    virtual void submit(Callable<int>* task);
    void setExecutionService(ThreadPoolCachedExPtr service);
    ThreadPoolCachedExPtr getExecutorService();
	void setEnabled(bool enabled);	

	BindingProviderPtr getProvider();
	EvaluatorPtr getEvaluator();
	bool isDisableStartupConcurrency();
	void setDisableStartupConcurrency(bool disableStartupConcurrency);

    void processReferenceChange(ReferencePtr cause, std::map<AgString, AgObjectPtr> &environment, ChangeCachePtr cache);

	DefaultBindingProcessor(BindingProviderPtr provider, EvaluatorPtr evaluator);    
    friend class BindingReferenceListener;
};
