// 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_EditCtrl.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_Caret.h"
#include "../../include/pdfwindow/PWL_FontMap.h"

#define IsFloatZero(f)                      ((f) < 0.0001 && (f) > -0.0001)
#define IsFloatBigger(fa,fb)                ((fa) > (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatSmaller(fa,fb)               ((fa) < (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatEqual(fa,fb)                 IsFloatZero((fa)-(fb))

/* ---------------------------- CPWL_EditCtrl ------------------------------ */

CPWL_EditCtrl::CPWL_EditCtrl() :
    m_pEdit(NULL),
    m_pEditCaret(NULL),
    m_bMouseDown(false),
    m_pEditNotify(NULL),
    m_nCharSet(DEFAULT_CHARSET),
    m_nCodePage(0)
{
    m_pEdit = IFX_Edit::NewEdit();
    ASSERT(m_pEdit != NULL);
}

CPWL_EditCtrl::~CPWL_EditCtrl()
{
    IFX_Edit::DelEdit(m_pEdit);
}

void CPWL_EditCtrl::OnCreate(PWL_CREATEPARAM& cp)
{
    cp.eCursorType = FXCT_VBEAM;
}

void CPWL_EditCtrl::OnCreated()
{
    SetFontSize(GetCreationParam().fFontSize);

    m_pEdit->SetFontMap(GetFontMap());
    m_pEdit->SetNotify(this);
    m_pEdit->Initialize();
}

bool CPWL_EditCtrl::IsWndHorV()
{
    CPDF_Matrix mt = GetWindowMatrix();
    CPDF_Point point1(0,1);
    CPDF_Point point2(1,1);

    mt.Transform(point1.x, point1.y);
    mt.Transform(point2.x, point2.y);

    return point2.y == point1.y;
}

void CPWL_EditCtrl::SetCursor()
{
    if (IsValid())
    {
        if (IFX_SystemHandler* pSH = GetSystemHandler())
        {
            if (IsWndHorV())
                pSH->SetCursor(FXCT_VBEAM);
            else
                pSH->SetCursor(FXCT_HBEAM);
        }
    }
}

void CPWL_EditCtrl::RePosChildWnd()
{
    m_pEdit->SetPlateRect(GetClientRect());
}

void CPWL_EditCtrl::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, intptr_t wParam, intptr_t lParam)
{
    CPWL_Wnd::OnNotify(pWnd,msg,wParam,lParam);

    switch (msg)
    {
        case PNM_SETSCROLLINFO:
            switch (wParam)
            {
                case SBT_VSCROLL:
                    if (CPWL_Wnd * pChild = GetVScrollBar())
                    {
                        pChild->OnNotify(pWnd,PNM_SETSCROLLINFO,wParam,lParam);
                    }
                    break;
            }
            break;
        case PNM_SETSCROLLPOS:
            switch (wParam)
            {
                case SBT_VSCROLL:
                    if (CPWL_Wnd * pChild = GetVScrollBar())
                    {
                        pChild->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam);
                    }
                    break;
            }
            break;
        case PNM_SCROLLWINDOW:
            {
                FX_FLOAT fPos = *(FX_FLOAT*)lParam;
                switch (wParam)
                {
                    case SBT_VSCROLL:
                        m_pEdit->SetScrollPos(CPDF_Point(m_pEdit->GetScrollPos().x,fPos));
                        break;
                }
            }
            break;
        case PNM_SETCARETINFO:
            {
                if (PWL_CARET_INFO * pCaretInfo = (PWL_CARET_INFO *)wParam)
                {
                    SetCaret(pCaretInfo->bVisible,
                        pCaretInfo->ptHead,
                        pCaretInfo->ptFoot);
                }
            }
            break;
    }
}

void CPWL_EditCtrl::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
    if (!IsReadOnly())
        CreateEditCaret(cp);
}

void CPWL_EditCtrl::CreateEditCaret(const PWL_CREATEPARAM & cp)
{
    if (!m_pEditCaret)
    {
        m_pEditCaret = new CPWL_Caret;
        m_pEditCaret->SetInvalidRect(GetClientRect());

        PWL_CREATEPARAM ecp = cp;
        ecp.pParentWnd = this;
        ecp.dwFlags = PWS_CHILD | PWS_NOREFRESHCLIP;
        ecp.dwBorderWidth = 0;
        ecp.nBorderStyle = PBS_SOLID;
        ecp.rcRectWnd = CPDF_Rect(0,0,0,0);

        m_pEditCaret->Create(ecp);
    }
}

void CPWL_EditCtrl::SetFontSize(FX_FLOAT fFontSize)
{
    m_pEdit->SetFontSize(fFontSize);
}

FX_FLOAT CPWL_EditCtrl::GetFontSize() const
{
    return m_pEdit->GetFontSize();
}

bool CPWL_EditCtrl::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
{
    if (m_bMouseDown) return true;

    bool bRet = CPWL_Wnd::OnKeyDown(nChar,nFlag);

    //FILTER
    switch (nChar)
    {
    default:
        return false;
    case FWL_VKEY_Delete:
    case FWL_VKEY_Up:
    case FWL_VKEY_Down:
    case FWL_VKEY_Left:
    case FWL_VKEY_Right:
    case FWL_VKEY_Home:
    case FWL_VKEY_End:
    case FWL_VKEY_Insert:
    case 'C':
    case 'V':
    case 'X':
    case 'A':
    case 'Z':
    case 'c':
    case 'v':
    case 'x':
    case 'a':
    case 'z':
        break;
    }

    if (nChar == FWL_VKEY_Delete)
    {
        if (m_pEdit->IsSelected())
            nChar = FWL_VKEY_Unknown;
    }

    switch (nChar)
    {
        case FWL_VKEY_Delete:
            Delete();
            return true;
        case FWL_VKEY_Insert:
            if (IsSHIFTpressed(nFlag))
                PasteText();
            return true;
        case FWL_VKEY_Up:
            m_pEdit->OnVK_UP(IsSHIFTpressed(nFlag),false);
            return true;
        case FWL_VKEY_Down:
            m_pEdit->OnVK_DOWN(IsSHIFTpressed(nFlag),false);
            return true;
        case FWL_VKEY_Left:
            m_pEdit->OnVK_LEFT(IsSHIFTpressed(nFlag),false);
            return true;
        case FWL_VKEY_Right:
            m_pEdit->OnVK_RIGHT(IsSHIFTpressed(nFlag),false);
            return true;
        case FWL_VKEY_Home:
            m_pEdit->OnVK_HOME(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
            return true;
        case FWL_VKEY_End:
            m_pEdit->OnVK_END(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
            return true;
        case FWL_VKEY_Unknown:
            if (!IsSHIFTpressed(nFlag))
                Clear();
            else
                CutText();
            return true;
        default:
            break;
    }

    return bRet;
}

bool CPWL_EditCtrl::OnChar(FX_WORD nChar, FX_DWORD nFlag)
{
    if (m_bMouseDown) return true;

    CPWL_Wnd::OnChar(nChar,nFlag);

    //FILTER
    switch (nChar)
    {
        case 0x0A:
        case 0x1B:
            return false;
        default:
            break;
    }

    bool bCtrl = IsCTRLpressed(nFlag);
    bool bAlt = IsALTpressed(nFlag);
    bool bShift = IsSHIFTpressed(nFlag);

    FX_WORD word = nChar;

    if (bCtrl && !bAlt)
    {
        switch (nChar)
        {
            case 'C' - 'A' + 1:
                CopyText();
                return true;
            case 'V' - 'A' + 1:
                PasteText();
                return true;
            case 'X' - 'A' + 1:
                CutText();
                return true;
            case 'A' - 'A' + 1:
                SelectAll();
                return true;
            case 'Z' - 'A' + 1:
                if (bShift)
                    Redo();
                else
                    Undo();
                return true;
            default:
                if (nChar < 32)
                    return false;
        }
    }

    if (IsReadOnly()) return true;

    if (m_pEdit->IsSelected() && word ==  FWL_VKEY_Back)
        word = FWL_VKEY_Unknown;

    Clear();

    switch (word)
    {
    case FWL_VKEY_Back:
        Backspace();
        break;
    case FWL_VKEY_Return:
        InsertReturn();
        break;
    case FWL_VKEY_Unknown:
        break;
    default:
        if (IsINSERTpressed(nFlag))
            Delete();
        InsertWord(word, GetCharSet());
        break;
    }

    return true;
}

bool CPWL_EditCtrl::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)
{
    CPWL_Wnd::OnLButtonDown(point,nFlag);

    if (ClientHitTest(point))
    {
        if (m_bMouseDown)
            InvalidateRect();

        m_bMouseDown = true;
        SetCapture();

        m_pEdit->OnMouseDown(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
    }

    return true;
}

bool CPWL_EditCtrl::OnLButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
{
    CPWL_Wnd::OnLButtonUp(point,nFlag);

    if (m_bMouseDown)
    {
        //can receive keybord message
        if (ClientHitTest(point) && !IsFocused())
            SetFocus();

        ReleaseCapture();
        m_bMouseDown = false;
    }

    return true;
}

bool CPWL_EditCtrl::OnMouseMove(const CPDF_Point & point, FX_DWORD nFlag)
{
    CPWL_Wnd::OnMouseMove(point,nFlag);

    if (m_bMouseDown)
        m_pEdit->OnMouseMove(point,false,false);

    return true;
}

CPDF_Rect CPWL_EditCtrl::GetContentRect() const
{
    return m_pEdit->GetContentRect();
}

void CPWL_EditCtrl::SetEditCaret(bool bVisible)
{
    CPDF_Point ptHead(0,0),ptFoot(0,0);

    if (bVisible)
    {
        GetCaretInfo(ptHead,ptFoot);
    }

    CPVT_WordPlace wpTemp = m_pEdit->GetCaretWordPlace();
    IOnSetCaret(bVisible,ptHead,ptFoot,wpTemp);
}

void CPWL_EditCtrl::GetCaretInfo(CPDF_Point & ptHead, CPDF_Point & ptFoot) const
{
    if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
    {
        pIterator->SetAt(m_pEdit->GetCaret());
        CPVT_Word word;
        CPVT_Line line;
        if (pIterator->GetWord(word))
        {
            ptHead.x = word.ptWord.x + word.fWidth;
            ptHead.y = word.ptWord.y + word.fAscent;
            ptFoot.x = word.ptWord.x + word.fWidth;
            ptFoot.y = word.ptWord.y + word.fDescent;
        }
        else if (pIterator->GetLine(line))
        {
            ptHead.x = line.ptLine.x;
            ptHead.y = line.ptLine.y + line.fLineAscent;
            ptFoot.x = line.ptLine.x;
            ptFoot.y = line.ptLine.y + line.fLineDescent;
        }
    }
}

void CPWL_EditCtrl::GetCaretPos(int32_t& x, int32_t& y) const
{
    CPDF_Point ptHead(0,0), ptFoot(0,0);

    GetCaretInfo(ptHead,ptFoot);

    PWLtoWnd(ptHead, x, y);
}

void CPWL_EditCtrl::SetCaret(bool bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot)
{
    if (m_pEditCaret)
    {
        if (!IsFocused() || m_pEdit->IsSelected())
            bVisible = false;

        m_pEditCaret->SetCaret(bVisible, ptHead, ptFoot);
    }
}

bool CPWL_EditCtrl::IsModified() const
{
    return m_pEdit->IsModified();
}

CFX_WideString CPWL_EditCtrl::GetText() const
{
    return m_pEdit->GetText();
}

void CPWL_EditCtrl::SetSel(int32_t nStartChar,int32_t nEndChar)
{
    m_pEdit->SetSel(nStartChar, nEndChar);
}

void CPWL_EditCtrl::GetSel(int32_t & nStartChar, int32_t & nEndChar ) const
{
    m_pEdit->GetSel(nStartChar, nEndChar);
}

void CPWL_EditCtrl::Clear()
{
    if (!IsReadOnly())
        m_pEdit->Clear();
}

void CPWL_EditCtrl::SelectAll()
{
    m_pEdit->SelectAll();
}

void CPWL_EditCtrl::Paint()
{
    if (m_pEdit)
        m_pEdit->Paint();
}

void CPWL_EditCtrl::EnableRefresh(bool bRefresh)
{
    if (m_pEdit)
        m_pEdit->EnableRefresh(bRefresh);
}

int32_t CPWL_EditCtrl::GetCaret() const
{
    if (m_pEdit)
        return m_pEdit->GetCaret();

    return -1;
}

void CPWL_EditCtrl::SetCaret(int32_t nPos)
{
    if (m_pEdit)
        m_pEdit->SetCaret(nPos);
}

int32_t CPWL_EditCtrl::GetTotalWords() const
{
    if (m_pEdit)
        return m_pEdit->GetTotalWords();

    return 0;
}

void CPWL_EditCtrl::SetScrollPos(const CPDF_Point& point)
{
    if (m_pEdit)
        m_pEdit->SetScrollPos(point);
}

CPDF_Point CPWL_EditCtrl::GetScrollPos() const
{
    if (m_pEdit)
        return m_pEdit->GetScrollPos();

    return CPDF_Point(0.0f, 0.0f);
}

CPDF_Font * CPWL_EditCtrl::GetCaretFont() const
{
    int32_t nFontIndex = 0;

    if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
    {
        pIterator->SetAt(m_pEdit->GetCaret());
        CPVT_Word word;
        CPVT_Section section;
        if (pIterator->GetWord(word))
        {
            nFontIndex = word.nFontIndex;
        }
        else if (HasFlag(PES_RICH))
        {
            if (pIterator->GetSection(section))
            {
                nFontIndex = section.WordProps.nFontIndex;
            }
        }
    }

    if (IFX_Edit_FontMap* pFontMap = GetFontMap())
        return pFontMap->GetPDFFont(nFontIndex);

    return NULL;
}

FX_FLOAT CPWL_EditCtrl::GetCaretFontSize() const
{
    FX_FLOAT fFontSize = GetFontSize();

    if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
    {
        pIterator->SetAt(m_pEdit->GetCaret());
        CPVT_Word word;
        CPVT_Section section;
        if (pIterator->GetWord(word))
        {
            fFontSize = word.fFontSize;
        }
        else if (HasFlag(PES_RICH))
        {
            if (pIterator->GetSection(section))
            {
                fFontSize = section.WordProps.fFontSize;
            }
        }
    }

    return fFontSize;
}

void CPWL_EditCtrl::SetText(const FX_WCHAR* csText)
{
    m_pEdit->SetText(csText);
}

void CPWL_EditCtrl::CopyText()
{
}

void CPWL_EditCtrl::PasteText()
{
}

void CPWL_EditCtrl::CutText()
{
}

void CPWL_EditCtrl::ShowVScrollBar(bool bShow)
{
}

void CPWL_EditCtrl::InsertText(const FX_WCHAR* csText)
{
    if (!IsReadOnly())
        m_pEdit->InsertText(csText);
}

void CPWL_EditCtrl::InsertWord(FX_WORD word, int32_t nCharset)
{
    if (!IsReadOnly())
        m_pEdit->InsertWord(word, nCharset);
}

void CPWL_EditCtrl::InsertReturn()
{
    if (!IsReadOnly())
        m_pEdit->InsertReturn();
}

void CPWL_EditCtrl::Delete()
{
    if (!IsReadOnly())
        m_pEdit->Delete();
}

void CPWL_EditCtrl::Backspace()
{
    if (!IsReadOnly())
        m_pEdit->Backspace();
}

bool CPWL_EditCtrl::CanUndo() const
{
    return !IsReadOnly() && m_pEdit->CanUndo();
}

bool CPWL_EditCtrl::CanRedo() const
{
    return !IsReadOnly() && m_pEdit->CanRedo();
}

void CPWL_EditCtrl::Redo()
{
    if (CanRedo())
        m_pEdit->Redo();
}

void CPWL_EditCtrl::Undo()
{
    if (CanUndo())
        m_pEdit->Undo();
}

void CPWL_EditCtrl::IOnSetScrollInfoY(FX_FLOAT fPlateMin, FX_FLOAT fPlateMax,
                                                FX_FLOAT fContentMin, FX_FLOAT fContentMax,
                                                FX_FLOAT fSmallStep, FX_FLOAT fBigStep)
{
    PWL_SCROLL_INFO Info;

    Info.fPlateWidth = fPlateMax - fPlateMin;
    Info.fContentMin = fContentMin;
    Info.fContentMax = fContentMax;
    Info.fSmallStep = fSmallStep;
    Info.fBigStep = fBigStep;

    OnNotify(this,PNM_SETSCROLLINFO,SBT_VSCROLL,(intptr_t)&Info);

    if (IsFloatBigger(Info.fPlateWidth,Info.fContentMax-Info.fContentMin)
        || IsFloatEqual(Info.fPlateWidth,Info.fContentMax-Info.fContentMin))
    {
        ShowVScrollBar(false);
    }
    else
    {
        ShowVScrollBar(true);
    }
}

void CPWL_EditCtrl::IOnSetScrollPosY(FX_FLOAT fy)
{
    OnNotify(this, PNM_SETSCROLLPOS,SBT_VSCROLL, (intptr_t)&fy);
}

void CPWL_EditCtrl::IOnSetCaret(bool bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot, const CPVT_WordPlace& place)
{
    PWL_CARET_INFO cInfo;
    cInfo.bVisible = bVisible;
    cInfo.ptHead = ptHead;
    cInfo.ptFoot = ptFoot;

    OnNotify(this, PNM_SETCARETINFO, (intptr_t)&cInfo, (intptr_t)NULL);
}

void CPWL_EditCtrl::IOnCaretChange(const CPVT_SecProps & secProps, const CPVT_WordProps & wordProps)
{
}

void CPWL_EditCtrl::IOnContentChange(const CPDF_Rect& rcContent)
{
    if (IsValid())
    {
        if (m_pEditNotify)
        {
            m_pEditNotify->OnContentChange(rcContent);
        }
    }
}

void CPWL_EditCtrl::IOnInvalidateRect(CPDF_Rect * pRect)
{
    InvalidateRect(pRect);
}

int32_t CPWL_EditCtrl::GetCharSet() const
{
    return m_nCharSet < 0 ? DEFAULT_CHARSET : m_nCharSet;
}

void CPWL_EditCtrl::GetTextRange(const CPDF_Rect& rect, int32_t & nStartChar, int32_t & nEndChar) const
{
    nStartChar = m_pEdit->WordPlaceToWordIndex(m_pEdit->SearchWordPlace(CPDF_Point(rect.left, rect.top)));
    nEndChar = m_pEdit->WordPlaceToWordIndex(m_pEdit->SearchWordPlace(CPDF_Point(rect.right, rect.bottom)));
}

CFX_WideString CPWL_EditCtrl::GetText(int32_t & nStartChar, int32_t & nEndChar) const
{
    CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStartChar);
    CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEndChar);
    return m_pEdit->GetRangeText(CPVT_WordRange(wpStart, wpEnd));
}

void    CPWL_EditCtrl::SetReadyToInput()
{
    if (m_bMouseDown)
    {
        ReleaseCapture();
        m_bMouseDown = false;
    }
}
