// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
 
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#ifndef _JS_CONTEXT_H_
#define _JS_CONTEXT_H_

class CJS_EventHandler;
class CJS_Runtime;

class CJS_Context : public IFXJS_Context
{
public:
	CJS_Context(CJS_Runtime* pRuntime);
	virtual ~CJS_Context();

public:
	virtual FX_BOOL				Compile(const CFX_WideString& script, CFX_WideString& info);
	virtual FX_BOOL				RunScript(const CFX_WideString& script, CFX_WideString& info);

public:
	virtual void				OnApp_Init();

	virtual void				OnDoc_Open(CPDFSDK_Document* pDoc, const CFX_WideString& strTargetName);
	virtual void				OnDoc_WillPrint(CPDFSDK_Document* pDoc);
	virtual void				OnDoc_DidPrint(CPDFSDK_Document* pDoc);
	virtual void				OnDoc_WillSave(CPDFSDK_Document* pDoc);
	virtual void				OnDoc_DidSave(CPDFSDK_Document* pDoc);
	virtual void				OnDoc_WillClose(CPDFSDK_Document* pDoc);

	virtual void				OnPage_Open(CPDFSDK_Document* pTarget);
	virtual void				OnPage_Close(CPDFSDK_Document* pTarget);
	virtual void				OnPage_InView(CPDFSDK_Document* pTarget);
	virtual void				OnPage_OutView(CPDFSDK_Document* pTarget);
	
	virtual void				OnField_MouseDown(FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField *pTarget);
	virtual void				OnField_MouseEnter(FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField *pTarget);
	virtual void				OnField_MouseExit(FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField *pTarget);
	virtual void				OnField_MouseUp(FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField *pTarget);
	virtual void				OnField_Focus(FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField* pTarget, const CFX_WideString& Value);
	virtual void				OnField_Blur(FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField* pTarget, const CFX_WideString& Value);

	virtual void				OnField_Calculate(CPDF_FormField* pSource, CPDF_FormField* pTarget, CFX_WideString& Value, FX_BOOL& bRc);
	virtual void				OnField_Format(int nCommitKey, CPDF_FormField* pTarget, CFX_WideString& Value, FX_BOOL bWillCommit);
	virtual void				OnField_Keystroke(int nCommitKey, CFX_WideString& strChange, const CFX_WideString& strChangeEx,
									FX_BOOL bKeyDown, FX_BOOL bModifier, int &nSelEnd,int &nSelStart, FX_BOOL bShift,
									CPDF_FormField* pTarget, CFX_WideString& Value, FX_BOOL bWillCommit, 
									FX_BOOL bFieldFull, FX_BOOL &bRc);
	virtual void				OnField_Validate(CFX_WideString& strChange, const CFX_WideString& strChangeEx, FX_BOOL bKeyDown,
									FX_BOOL bModifier, FX_BOOL bShift, CPDF_FormField* pTarget, CFX_WideString& Value, FX_BOOL& bRc);

	virtual void				OnScreen_Focus(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_Blur(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_Open(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_Close(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_MouseDown(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_MouseUp(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_MouseEnter(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_MouseExit(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_InView(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);
	virtual void				OnScreen_OutView(FX_BOOL bModifier, FX_BOOL bShift, CPDFSDK_Annot* pScreen);

	virtual void				OnBookmark_MouseUp(CPDF_Bookmark* pBookMark);
	virtual void				OnLink_MouseUp(CPDFSDK_Document* pTarget);

	virtual void				OnMenu_Exec(CPDFSDK_Document* pTarget, const CFX_WideString& strTargetName);
	virtual void				OnBatchExec(CPDFSDK_Document* pTarget);
	virtual void				OnConsole_Exec();
	virtual void				OnExternal_Exec();

	virtual void				EnableMessageBox(FX_BOOL bEnable) {m_bMsgBoxEnable = bEnable;}
	FX_BOOL						IsMsgBoxEnabled() const {return m_bMsgBoxEnable;}

public:
	CPDFDoc_Environment*			GetReaderApp();
	CJS_Runtime*				GetJSRuntime(){return m_pRuntime;}

	FX_BOOL						DoJob(int nMode, const CFX_WideString& script, CFX_WideString& info);

	CJS_EventHandler*			GetEventHandler(){return m_pEventHandler;};	
	CPDFSDK_Document*			GetReaderDocument();

private:
	CJS_Runtime*				m_pRuntime;	
	CJS_EventHandler*			m_pEventHandler;	

	FX_BOOL						m_bBusy;	
	FX_BOOL						m_bMsgBoxEnable;
};

// static CFX_WideString JSGetStringFromID(CJS_Context* pContext, UINT ID)
// {
// 	ASSERT(pContext != NULL);
// 
// 	return JS_LoadString(pContext->GetReaderApp(), ID);
// }

#endif //_JS_CONTEXT_H_

