// NotesView.cpp : implementation file
//

#include "stdafx.h"
#include "psm.h"
#include "NotesView.h"
#include "PSMDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CNotesView
#define APL_SEPARATOR _T("{\\rtf1\\ansi\\ansicpg1251\\deff0\\deflang1049{\\fonttbl{\\f0\\fnil\\b\\fcharset0 Arial;}}{\\colortbl ;\\red0\\green0\\blue128;}\\uc1\\pard\\ql\\cf1\\lang1033\\fs20\\line\\b ======================================================== \\b0\\line\\line\\par }")
#define APL_SEPARATOR_LEVEL _T("{\\rtf1\\ansi\\ansicpg1251\\deff0\\deflang1049{\\fonttbl{\\f0\\fnil\\b\\fcharset0 Arial;}}{\\colortbl ;\\red0\\green0\\blue128;}\\uc1\\pard\\ql\\cf1\\lang1033\\fs20\\line ---------------------------------------------------------------------------------------------------------------- \\line\\line\\par }")
#define APL_AUTOR_DATE(id,author, date, size) _T("{\\rtf1\\ansi\\ansicpg1251\\deff0\\deflang1049{\\fonttbl{\\f0\\fnil\\fcharset1 Arial;}}{\\colortbl ;\\red0\\green0\\blue0;}\\uc1\\pard\\ql\\cf1\\lang1033\\fs")+size+_T("\\b ")+id+_T(". ")+author+_T(" (")+date+_T(")\\b0\\line\\line\\par }")

IMPLEMENT_DYNCREATE(CNotesView, CRichEditView)

CNotesView::CNotesView()
{
}

CNotesView::~CNotesView()
{
}


BEGIN_MESSAGE_MAP(CNotesView, CRichEditView)
	//{{AFX_MSG_MAP(CNotesView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNotesView drawing

void CNotesView::OnDraw(CDC* pDC)
{
	CPSMDoc* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CNotesView diagnostics

#ifdef _DEBUG
void CNotesView::AssertValid() const
{
	CRichEditView::AssertValid();
}

void CNotesView::Dump(CDumpContext& dc) const
{
	CRichEditView::Dump(dc);
}

CPSMDoc* CNotesView::GetDocument()
{
	ASSERT(m_pDocument);
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPSMDoc)));
	return (CPSMDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CNotesView message handlers

void CNotesView::OnInitialUpdate() 
{
	CRichEditView::OnInitialUpdate();
	
	GetRichEditCtrl().SetReadOnly();
}

DWORD CALLBACK CNotesView::CBStreamIn(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
	CString *pstr = (CString *) dwCookie;
	
	/* AY переделал т.к. не работал под Unicode
	if (pstr->GetLength() < (int)(cb/sizeof(TCHAR)))
	{
		*pcb = pstr->GetLength()*sizeof(TCHAR);
		memcpy(pbBuff, (LPCTSTR) *pstr, *pcb);
		pstr->Empty();
	}
	else
	{
		*pcb = cb;
		memcpy(pbBuff, (LPCTSTR) *pstr, *pcb);
		*pstr = pstr->Right(pstr->GetLength() - cb/sizeof(TCHAR));
	}*/

	CStringA  ansiStr((char*)CaplStringAdapter(*pstr));
	if (ansiStr.GetLength()  < (int)cb)
	{
		*pcb = pstr->GetLength();
		memcpy(pbBuff, (LPCSTR) ansiStr, *pcb);
		pstr->Empty();
	}
	else
	{
		*pcb = cb;
		memcpy(pbBuff, (LPCSTR) ansiStr, *pcb);
		*pstr = pstr->Right(pstr->GetLength() - cb);
	}

	
	return 0;
}

bool CNotesView::SetRTF(CString sBuf, UINT Flags)
{
	EDITSTREAM es;
	es.dwError = 0;
	es.pfnCallback = CBStreamIn;
	es.dwCookie = (DWORD) &sBuf;
	GetRichEditCtrl().StreamIn(Flags, es);	// Do it.	
	
	return true;
}

void CNotesView::AddNotes(CaplInstance *inst)
{
	aplExtent notes;
	CaplAPI *api = &GetDocument()->m_api;
	
	api->m_appr_mgr.FindAssociatedNotes(inst, notes);
	int l=0, i=0;
	CString rev_date;
	CaplInstance*par=NULL;
	GetRichEditCtrl().SetWindowText(_T(""));
	while(1)
	{
		l++;
		bool find = false;
		for(i=0; i<notes.GetSize();i++)
		{
			api->m_data.GetAttr(notes[i],  api->m_appr_mgr.a_note_parent,par);
			if(par==0) {find = true;break;}
		}
		if(!find) return;
		CaplInstance *tmp = notes[i];
		CString level;
		level.Format(_T("%d"),l);
		long size;
		if(!api->m_data.NET_GetBlobSize(tmp, api->m_appr_mgr.a_note_source, size))return;
		BYTE *c =  new BYTE[size];
		if(c==NULL)
		{
			AfxMessageBox( APL_T("Недостаточно памяти для загрузки примечания!"));
			return;
		}
		api->m_data.NET_LoadBlob2Memory(tmp, api->m_appr_mgr.a_note_source,c,size);
		CString rtf;
		rtf += (const char*)c;
		if(l>1)
		{
			SetRTF(APL_SEPARATOR, APL_RC_SELECTION);
		}
		CString date, author;
		api->m_data.GetAttr(tmp, api->m_appr_mgr.a_note_date, date);
		COleDateTime time;
		aplString2Date(date,time);
		date = time.Format();
		CaplInstance *pers;
		api->m_data.GetAttr(tmp, api->m_appr_mgr.a_note_author, pers);
		api->m_appr_mgr.GetPersonName(pers,author);
		CString fsize = _T("24");

		api->m_data.GetAttr(tmp ,api->m_appr_mgr.a_note_date_revocation,rev_date);
		if(rev_date!=_T(""))
		{
			date+=APL_T("   Отменено! (");
			COleDateTime odt;
			aplString2Date(rev_date,odt);
			date+=odt.Format(_T("%d.%m.%y %H:%M"));
		}

		author = APL_AUTOR_DATE(level,author, date, fsize);
		SetRTF(author, APL_RC_SELECTION);
		SetRTF(rtf, APL_RC_SELECTION);
		delete c;
		
		if(!AddNotesRec(notes[i], notes, level+_T("."))) return;
		notes.Remove(i);
	}
	Invalidate();
}

bool CNotesView::GetChildNote(CaplInstance *parent, aplExtent &notes, aplExtent &childs)
{
	childs.Clear();
	CaplInstance* par=0;
	for(int i=0; i<notes.GetSize();i++)
	{
		GetDocument()->m_api.m_data.GetAttr(notes[i], GetDocument()->m_api.m_appr_mgr.a_note_parent,par);
		if(par==parent) childs.Add(notes[i]);
	}
	return NULL;
}

bool CNotesView::AddNotesRec(CaplInstance *note, aplExtent &notes, CString level)
{
	if(note==0) return false;
	aplExtent childs;
	GetChildNote(note, notes, childs);
	for(int i=0; i<childs.Size;i++)
	{
		CaplInstance *tmp = childs[i];
		long size;
		if(!GetDocument()->m_api.m_data.NET_GetBlobSize(tmp, GetDocument()->m_api.m_appr_mgr.a_note_source, size)) continue;
		BYTE *c =  new BYTE[size];
		if(c==NULL)
		{
			AfxMessageBox( APL_T("Недостаточно памяти для загрузки примечания!"));
			return false;
		}
		GetDocument()->m_api.m_data.NET_LoadBlob2Memory(tmp, GetDocument()->m_api.m_appr_mgr.a_note_source,c,size);
		CString rtf;
		rtf += (const char*)c;
		CString t, s;
		t.Format(_T("%s %i"),level,i+1);
		SetRTF(APL_SEPARATOR_LEVEL,APL_RC_SELECTION);
		CString date, author;
		GetDocument()->m_api.m_data.GetAttr(tmp, GetDocument()->m_api.m_appr_mgr.a_note_date, date);
		COleDateTime time;
		aplString2Date(date,time);
		date = time.Format();
		CaplInstance *pers;
		GetDocument()->m_api.m_data.GetAttr(tmp, GetDocument()->m_api.m_appr_mgr.a_note_author, pers);
		GetDocument()->m_api.m_appr_mgr.GetPersonName(pers, author);
		CString fsize;
		fsize.Format(_T("%d"),24-level.GetLength());
		author = APL_AUTOR_DATE(t,author, date, fsize);
		SetRTF(author,APL_RC_SELECTION);
		SetRTF(rtf,APL_RC_SELECTION);

		delete c;
		AddNotesRec(tmp, notes, t+_T("."));
	}
	return true;
}

LRESULT CNotesView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	if(message==((CPSMApp*)AfxGetApp())->m_view_update)
	{
		if(wParam==APL_UPDATE_INST_ITEM)
		{
			CaplUpdateItem* ui = (CaplUpdateItem*)lParam;
			SetRTF(_T(""));
			AddNotes(ui->inst);
		}
	}
	
	return CRichEditView::WindowProc(message, wParam, lParam);
}

BOOL CNotesView::PreCreateWindow(CREATESTRUCT& cs) 
{
	cs.style |=ES_AUTOVSCROLL|WS_VSCROLL;
	
	return CRichEditView::PreCreateWindow(cs);
}
