class TextBoxElement :
        public Element
{
public:
        TextBoxElement();
        virtual ~TextBoxElement();

        virtual Element* Clone() const;

        virtual ElementType GetType() const;

        virtual void Draw(CDC* pDC);
        virtual bool HitTest(const CPoint& point);
        virtual const CRect* GetAreaPtr() const;

        virtual void SaveToFile(HANDLE hFile) const;
        virtual void LoadFromFile(HANDLE hFile);

        void MoveTo(const CPoint& point);
        void SetSize(const CPoint& endPoint);

        void Activate();
        void Deactivate();

        void SetPageView(PageView* pPageView);

        bool IsValid() const;

private:
        PageView* m_pPageView;
        CString m_str;
        CRect m_area;

        bool m_activate;
};

class TextBoxElementController :
        public ElementController
{
public:
        TextBoxElementController(PageView* pEditorView);
        virtual ~TextBoxElementController();

        virtual bool OnLButtonDown(UINT nFlags, const CPoint& point);
        virtual bool On!@#!@$#!@$MouseMove(UINT nFlags, const CPoint& point);
        virtual bool OnLButtonUp(UINT nFlags, const CPoint& point);
        virtual bool OnLButtonDblClk(UINT nFlags, const CPoint& point);
        virtual bool OnSetCursor(UINT nHitTest, UINT message);
        virtual void OnSetFocus(CWnd* pOldWnd);
        virtual void OnKillFocus(CWnd* pNewWnd);

private:
        TextBoxElement* m_pTextBoxElement;
        bool m_created;
};





TextBoxElement::TextBoxElement()
: m_pPageView(NULL)
, m_activate(false)
{

}

/*virtual */TextBoxElement::~TextBoxElement()
{

}

/*virtual */Element* TextBoxElement::Clone() const
{
        return new TextBoxElement(*this);
}

/*virtual */ElementType TextBoxElement::GetType() const
{
        return TextBoxType;
}

/*virtual */void TextBoxElement::Draw(CDC* pDC)
{
        if (m_activate)
        {
                CRect outlineRect = m_area;
                outlineRect.NormalizeRect();
                outlineRect.InflateRect(10, 10);
                pDC->Rectangle(&outlineRect);
        }

        CRichEditCtrl* pRichEditContext = m_pPageView->GetRichEditContext();
        CRect clientRect;
        m_pPageView->GetClientRect(&clientRect);
        CRect normalizeRect = m_area;
        normalizeRect.NormalizeRect();
        RTFUtil::DrawRTF(pDC, clientRect, m_str, normalizeRect, pRichEditContext);
}

/*virtual */bool TextBoxElement::HitTest(const CPoint& point)
{
        return false;
}

/*virtual */const CRect* TextBoxElement::GetAreaPtr() const
{
        return &m_area;
}

/*virtual */void TextBoxElement::SaveToFile(HANDLE hFile) const
{
        DWORD writeLen;
        // 영역 저장
        ::WriteFile(hFile, &m_area, sizeof(m_area), &writeLen, NULL);
        // 글 개수 저장
        int strLen = m_str.GetLength();
        ::WriteFile(hFile, &strLen, sizeof(strLen), &writeLen, NULL);
        // 글 저장
        ::WriteFile(hFile, (LPCTSTR)m_str, strLen, &writeLen, NULL);
}

/*virtual */void TextBoxElement::LoadFromFile(HANDLE hFile)
{
        DWORD readLen;
        // 영역 로드
        ::ReadFile(hFile, &m_area, sizeof(m_area), &readLen, NULL);
        // 글 개수 로드
        int strLen;
        ::ReadFile(hFile, &strLen, sizeof(strLen), &readLen, NULL);
        // 글 로드
        m_str.GetBufferSetLength(strLen);
        ::ReadFile(hFile, m_str.GetBuffer(strLen), strLen, &readLen, NULL);

}

void TextBoxElement::MoveTo(const CPoint& point)
{
        m_area.left = point.x;
        m_area.top = point.y;
}

void TextBoxElement::SetSize(const CPoint& endPoint)
{
        m_area.right = endPoint.x;
        m_area.bottom = endPoint.y;
}

void TextBoxElement::Activate()
{
        m_activate = true;

        CRichEditCtrl* pRichEditContext = m_pPageView->GetRichEditContext();

        RTFUtil::FOPSetRichText(pRichEditContext, m_str);
        pRichEditContext->SetFocus();
        CRect normalizeArea = m_area;
        normalizeArea.NormalizeRect();
        CRect outlineRect = normalizeArea;
        outlineRect.InflateRect(10, 10);

        m_pPageView->InvalidateRect(&outlineRect);
        m_pPageView->UpdateWindow();

        pRichEditContext->MoveWindow(&normalizeArea, TRUE);
        pRichEditContext->ShowWindow(SW_SHOW);
}

void TextBoxElement::Deactivate()
{
        m_activate = false;

        CRichEditCtrl* pRichEditCtrl = m_pPageView->GetRichEditContext();

        RTFUtil::FOPGetRichText(pRichEditCtrl, &m_str);
        pRichEditCtrl->ShowWindow(SW_HIDE);

        CRect normalizeArea = m_area;
        normalizeArea.NormalizeRect();
        normalizeArea.InflateRect(10, 10);
        m_pPageView->InvalidateRect(&normalizeArea);
        m_pPageView->UpdateWindow();
}

void TextBoxElement::SetPageView(PageView* pPageView)
{
        m_pPageView = pPageView;
}

bool TextBoxElement::IsValid() const
{
        CRect normalizeRect = m_area;
        return normalizeRect.Height() > 10 && normalizeRect.Width() > 10;
}

TextBoxElementController::TextBoxElementController(PageView* pEditorView)
: ElementController(pEditorView)
, m_pTextBoxElement(NULL)
, m_created(false)
{

}

/*virtual */TextBoxElementController::~TextBoxElementController()
{

}

/*virtual */bool TextBoxElementController::OnLButtonDown(UINT nFlags, const CPoint& point)
{
        if (m_pTextBoxElement)
                m_pTextBoxElement->Deactivate();

        m_created = true;
        m_pEditorView->SetCapture();
        m_pTextBoxElement = new TextBoxElement;
        m_pTextBoxElement->SetPageView(m_pEditorView);
        m_pTextBoxElement->MoveTo(point);
        m_pTextBoxElement->SetSize(point);
        ElementMgr* pElementMgr = m_pEditorView->GetElementMgrPtr();
        pElementMgr->AddElement(m_pTextBoxElement);

        return true;
}

/*virtual */bool TextBoxElementController::On!@#$@#$@!#$MouseMove(UINT nFlags, const CPoint& point)
{
        if (nFlags & MK_LBUTTON && m_created)
        {
                const CRect* pRect = m_pTextBoxElement->GetAreaPtr();
                CRect invalidRect = *pRect;
                invalidRect.NormalizeRect();
                invalidRect.InflateRect(5, 5);
                m_pEditorView->InvalidateRect(&invalidRect);
                m_pEditorView->UpdateWindow();

                m_pTextBoxElement->SetSize(point);
                CDC* pDC = m_pEditorView->GetDC();

                CPen pen;
                pen.CreatePen(PS_DOT, 1, RGB(0, 0, 0));
                CPen* pOldPen = pDC->SelectObject(&pen);

                pDC->Rectangle(pRect);

                pDC->SelectObject(pOldPen);
                pen.DeleteObject();
                        
                m_pEditorView->ReleaseDC(pDC);
        }

        return true;
}

/*virtual */bool TextBoxElementController::OnLButtonUp(UINT nFlags, const CPoint& point)
{
        ::ReleaseCapture();
        if (m_created)
        {
                if (m_pTextBoxElement->IsValid())
                {
                        m_pTextBoxElement->Activate();
                }
                else
                {
                        const CRect* pRect = m_pTextBoxElement->GetAreaPtr();
                        CRect invalidateRect = *pRect;

                        ElementMgr* pElementMgr = m_pEditorView->GetElementMgrPtr();
                        pElementMgr->PopElement();
                        m_pTextBoxElement = NULL;

                        invalidateRect.NormalizeRect();
                        invalidateRect.InflateRect(5, 5);
                        m_pEditorView->InvalidateRect(&invalidateRect);
                        m_pEditorView->UpdateWindow();
                }
        }

        m_created = false;

        return true;
}

/*virtual */bool TextBoxElementController::OnLButtonDblClk(UINT nFlags, const CPoint& point)
{
        return true;
}

/*virtual */bool TextBoxElementController::OnSetCursor(UINT nHitTest, UINT message)
{
        return true;
}

/*virtual */void TextBoxElementController::OnSetFocus(CWnd* pOldWnd)
{
        
}

/*virtual */void TextBoxElementController::OnKillFocus(CWnd* pNewWnd)
{

}