// 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_OBJECT_H_
#define _JS_OBJECT_H_

class CJS_Object;
class CJS_Timer;
class CJS_Context;

class CJS_EmbedObj : public CFX_Object
{
public:
	CJS_EmbedObj(CJS_Object* pJSObject);
	virtual ~CJS_EmbedObj();

	virtual void				TimerProc(CJS_Timer* pTimer){};

	CJS_Timer*					BeginTimer(CPDFDoc_Environment * pApp, FX_UINT nElapse);
	void						EndTimer(CJS_Timer* pTimer);

	CJS_Object*					GetJSObject(){return m_pJSObject;};
	operator					CJS_Object* (){return m_pJSObject;};

	CPDFSDK_PageView *			JSGetPageView(IFXJS_Context* cc);
	int							MsgBox(CPDFDoc_Environment* pApp, CPDFSDK_PageView* pPageView, FX_LPCWSTR swMsg, FX_LPCWSTR swTitle = NULL, FX_UINT nType = 0, FX_UINT nIcon = 0);
	void						Alert(CJS_Context* pContext, FX_LPCWSTR swMsg);
	FX_BOOL						IsSafeMode(IFXJS_Context* cc);

protected:

	CJS_Object*					m_pJSObject;
};

class CJS_Object : public CFX_Object
{
public:
	CJS_Object(JSFXObject pObject);
	virtual ~CJS_Object(void);
	
	void						MakeWeak();

	virtual FX_BOOL				IsType(FX_LPCSTR sClassName){return TRUE;};
	virtual CFX_ByteString		GetClassName(){return "";};

	virtual FX_BOOL				InitInstance(IFXJS_Context* cc){return TRUE;};
	virtual FX_BOOL				ExitInstance(){return TRUE;};

	operator					JSFXObject () {return v8::Local<v8::Object>::New(m_pIsolate, m_pObject);}
	operator					CJS_EmbedObj* (){return m_pEmbedObj;};

	void						SetEmbedObject(CJS_EmbedObj* pObj){m_pEmbedObj = pObj;};
	CJS_EmbedObj *				GetEmbedObject(){return m_pEmbedObj;};

	static CPDFSDK_PageView *	JSGetPageView(IFXJS_Context* cc);
	static int					MsgBox(CPDFDoc_Environment* pApp, CPDFSDK_PageView* pPageView, FX_LPCWSTR swMsg, FX_LPCWSTR swTitle = NULL, FX_UINT nType = 0,FX_UINT nIcon = 0);
	static void					Alert(CJS_Context* pContext, FX_LPCWSTR swMsg);

	v8::Isolate*					GetIsolate() {return m_pIsolate;}
protected:
	CJS_EmbedObj *				m_pEmbedObj;
	v8::Persistent<v8::Object>			m_pObject;
	v8::Isolate*					m_pIsolate;
};

struct JS_TIMER_MAP
{
	FX_UINT nID;
	CJS_Timer * pTimer;
};

typedef CFX_ArrayTemplate<JS_TIMER_MAP*>	CTimerMapArray;

struct JS_TIMER_MAPARRAY
{
public:
	JS_TIMER_MAPARRAY()
	{
	}

	~JS_TIMER_MAPARRAY()
	{
		Reset();
	}

	void Reset()
	{
		for (int i=0,sz=m_Array.GetSize(); i<sz; i++)
			delete m_Array.GetAt(i);

		m_Array.RemoveAll();
	}

	void SetAt(FX_UINT nIndex,CJS_Timer * pTimer)
	{
		int i = Find(nIndex);

		if (i>=0)
		{
			if (JS_TIMER_MAP * pMap = m_Array.GetAt(i))
				pMap->pTimer = pTimer;
		}
		else
		{
			if (JS_TIMER_MAP * pMap = new JS_TIMER_MAP)
			{
				pMap->nID = nIndex;
				pMap->pTimer = pTimer;
				m_Array.Add(pMap);
			}
		}
	}

	CJS_Timer * GetAt(FX_UINT nIndex)
	{
		int i = Find(nIndex);

		if (i>=0)
		{
			if (JS_TIMER_MAP * pMap = m_Array.GetAt(i))
				return pMap->pTimer;
		}
		return NULL;
	}

	void RemoveAt(FX_UINT nIndex)
	{
		int i = Find(nIndex);

		if (i>=0)
		{
			delete m_Array.GetAt(i);
			m_Array.RemoveAt(i);
		}
		//To prevent potential fake memory leak reported by vc6.
		if(m_Array.GetSize() == 0)
			m_Array.RemoveAll();
	}

	int Find(FX_UINT nIndex)
	{		
		for (int i=0,sz=m_Array.GetSize(); i<sz; i++)
		{			
			if (JS_TIMER_MAP * pMap = m_Array.GetAt(i))
			{
				if (pMap->nID == nIndex)
					return i;
			}
		}

		return -1;
	}

	CTimerMapArray		m_Array;
};

static JS_TIMER_MAPARRAY	m_sTimeMap;

class CJS_Runtime;

class CJS_Timer
{
public:
	CJS_Timer(CJS_EmbedObj * pObj,CPDFDoc_Environment* pApp): m_pEmbedObj(pObj), 
		m_nTimerID(0), 
		m_bProcessing(FALSE),
		m_dwStartTime(0),
		m_dwTimeOut(0),
		m_dwElapse(0),
		m_pRuntime(NULL),
		m_nType(0),
		m_pApp(pApp)
	{
	}
	
	virtual ~CJS_Timer()
	{
		KillJSTimer();
	}

public:
	FX_UINT SetJSTimer(FX_UINT nElapse)
	{	
		if (m_nTimerID)KillJSTimer();
		IFX_SystemHandler* pHandler = m_pApp->GetSysHandler();
		m_nTimerID = pHandler->SetTimer(nElapse,TimerProc);
		m_sTimeMap.SetAt(m_nTimerID,this);
		m_dwElapse = nElapse;
		return m_nTimerID;
	};

	void KillJSTimer()
	{
		if (m_nTimerID)
		{
			IFX_SystemHandler* pHandler = m_pApp->GetSysHandler();
			pHandler->KillTimer(m_nTimerID);
			m_sTimeMap.RemoveAt(m_nTimerID);
			m_nTimerID = 0;
		}
	};

	void SetType(int nType)
	{
		m_nType = nType;
	}

	int GetType() const
	{
		return m_nType;
	}

	void SetStartTime(FX_DWORD dwStartTime)
	{
		m_dwStartTime = dwStartTime;
	}

	FX_DWORD GetStartTime() const
	{
		return m_dwStartTime;
	}

	void SetTimeOut(FX_DWORD dwTimeOut)
	{
		m_dwTimeOut = dwTimeOut;
	}

	FX_DWORD GetTimeOut() const
	{
		return m_dwTimeOut;
	}

	void SetRuntime(CJS_Runtime* pRuntime)
	{
		m_pRuntime = pRuntime;
	}
	
	CJS_Runtime* GetRuntime() const
	{
		return m_pRuntime;
	}

	void SetJScript(const CFX_WideString& script)
	{
		m_swJScript = script;
	}

	CFX_WideString GetJScript() const
	{
		return m_swJScript;
	}

	static void TimerProc(int idEvent)
	{
		if (CJS_Timer * pTimer = m_sTimeMap.GetAt(idEvent))
		{
			if (!pTimer->m_bProcessing)
			{
				pTimer->m_bProcessing = TRUE;
				if (pTimer->m_pEmbedObj) pTimer->m_pEmbedObj->TimerProc(pTimer);
				pTimer->m_bProcessing = FALSE;
			}
			else
			{
			//	TRACE(L"BUSY!\n");
			}
		}
	};

private:
	FX_UINT							m_nTimerID;	
	CJS_EmbedObj*					m_pEmbedObj;
	FX_BOOL							m_bProcessing;

	//data
	FX_DWORD							m_dwStartTime;
	FX_DWORD							m_dwTimeOut;
	FX_DWORD						m_dwElapse;
	CJS_Runtime*					m_pRuntime;
	CFX_WideString					m_swJScript;
	int								m_nType; //0:Interval; 1:TimeOut

	CPDFDoc_Environment*			m_pApp;
};
#endif //_JS_OBJECT_H_
