// 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

#include "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_Caret.h"
#include "../../include/pdfwindow/PWL_Utils.h"

#define PWL_CARET_FLASHINTERVAL		500

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPWL_Caret::CPWL_Caret() :
	m_bFlash(false),
	m_ptHead(0,0),
	m_ptFoot(0,0),
	m_fWidth(0.4f),
	m_nDelay(0)
{
}

CPWL_Caret::~CPWL_Caret()
{
}

CFX_ByteString CPWL_Caret::GetClassName() const
{
	return "CPWL_Caret";
}

void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	GetCaretApp(sAppStream,CPDF_Point(0.0f,0.0f));
}

void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	if (IsVisible() && m_bFlash)
	{
		CPDF_Rect rcRect = GetCaretRect();
		CPDF_Rect rcClip = GetClipRect();

		CFX_PathData path;

		path.SetPointCount(2);

		FX_FLOAT fCaretX = rcRect.left + m_fWidth * 0.5f;
		FX_FLOAT fCaretTop = rcRect.top;
		FX_FLOAT fCaretBottom = rcRect.bottom;

		if (!rcClip.IsEmpty())
		{
			rcRect.Intersect(rcClip);
			if (!rcRect.IsEmpty())
			{
				fCaretTop = rcRect.top;
				fCaretBottom = rcRect.bottom;
				path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO);
				path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO);
			}
			else
			{
				return;
			}
		}
		else
		{
			path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO);
			path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO);
		}

		CFX_GraphStateData gsd;
		gsd.m_LineWidth = m_fWidth;

		pDevice->DrawPath(&path, pUser2Device, &gsd,0,  ArgbEncode(255,0,0,0), FXFILL_ALTERNATE);
	}
}

void CPWL_Caret::GetCaretApp(CFX_ByteTextBuf & sAppStream,const CPDF_Point & ptOffset)
{
	if (IsVisible() && m_bFlash)
	{
		CFX_ByteTextBuf sCaret;

		CPDF_Rect rcRect = GetCaretRect();
		CPDF_Rect rcClip = GetClipRect();

		rcRect = CPWL_Utils::OffsetRect(rcRect,ptOffset.x,ptOffset.y);
		rcClip = CPWL_Utils::OffsetRect(rcClip,ptOffset.x,ptOffset.y);

		sCaret << "q\n";
		if (!rcClip.IsEmpty())
		{
			sCaret << rcClip.left << " " << rcClip.bottom + 2.5f << " "
				<< rcClip.right - rcClip.left << " " << rcClip.top - rcClip.bottom - 4.5f << " re W n\n";
		}
		sCaret << m_fWidth << " w\n0 G\n";
		sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.bottom << " m\n";
		sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.top << " l S\nQ\n";

		sAppStream << sCaret;
	}
}

CFX_ByteString CPWL_Caret::GetCaretAppearanceStream(const CPDF_Point & ptOffset)
{
	CFX_ByteTextBuf sCaret;
	GetCaretApp(sCaret,ptOffset);
	return sCaret.GetByteString();
}

void CPWL_Caret::TimerProc()
{
	if (m_nDelay > 0)
	{
		m_nDelay--;
	}
	else
	{
		m_bFlash = !m_bFlash;
		InvalidateRect();
	}
}

CPDF_Rect CPWL_Caret::GetCaretRect() const
{
	return CPDF_Rect(m_ptFoot.x,
			m_ptFoot.y,
			m_ptHead.x + m_fWidth,
			m_ptHead.y);
}

void CPWL_Caret::SetCaret(bool bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot)
{
	if (bVisible)
	{
		if (IsVisible())
		{
			if (m_ptHead.x != ptHead.x || m_ptHead.y != ptHead.y ||
					m_ptFoot.x != ptFoot.x || m_ptFoot.y != ptFoot.y)
			{
				m_ptHead = ptHead;
				m_ptFoot = ptFoot;

				m_bFlash = true;
				//Move(GetCaretRect(),false,true);
				Move(m_rcInvalid, false, true);
			}
		}
		else
		{
			m_ptHead = ptHead;
			m_ptFoot = ptFoot;

			EndTimer();
			BeginTimer(PWL_CARET_FLASHINTERVAL);

			CPWL_Wnd::SetVisible(true);
			m_bFlash = true;

			//Move(GetCaretRect(),false,true);
			Move(m_rcInvalid, false, true);
		}
	}
	else
	{
		m_ptHead = CPDF_Point(0, 0);
		m_ptFoot = CPDF_Point(0, 0);

		m_bFlash = false;
		if (IsVisible())
		{
			EndTimer();
			CPWL_Wnd::SetVisible(false);
		}
	}
}

void CPWL_Caret::InvalidateRect(CPDF_Rect * pRect)
{
	if (pRect)
	{
		CPDF_Rect rcRefresh = CPWL_Utils::InflateRect(*pRect,0.5f);
		rcRefresh.top += 1;
		rcRefresh.bottom -= 1;

		CPWL_Wnd::InvalidateRect(&rcRefresh);
	}
	else
		CPWL_Wnd::InvalidateRect(pRect);
}

