// GanttView.cpp : implementation file
//

#include "stdafx.h"

#include "GanttView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CGanttView

IMPLEMENT_DYNCREATE(CGanttView, CView)

CGanttView::CGanttView()
{
	m_tree_view=0;
	m_TLInitialized=FALSE;
	m_bShrinkToFit=true;
	m_bShowPrognoz=false;
	m_bShowRelations = true;
	m_bShowFact = true; 
}

CGanttView::~CGanttView()
{
}


BEGIN_MESSAGE_MAP(CGanttView, CView)
	//{{AFX_MSG_MAP(CGanttView)
	ON_WM_MOUSEACTIVATE()
	ON_WM_SIZE()
	ON_WM_HSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGanttView drawing

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

/////////////////////////////////////////////////////////////////////////////
// CGanttView diagnostics

#ifdef _DEBUG
void CGanttView::AssertValid() const
{
	CView::AssertValid();
}

void CGanttView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CGanttView message handlers

void CGanttView::Initialize()
{
	CRect m_wndRect;
	GetWindowRect(&m_wndRect);
	CRect m_ganttRect;

	// create the ctrl itself
	{
		GetWindowRect(&m_wndRect);

		m_ganttRect.left=0;
		//m_ganttRect.top = m_gantt.m_headerHeight+1;
		m_ganttRect.top = 1;;
		m_ganttRect.right = m_wndRect.Width()-5;
		m_ganttRect.bottom = m_wndRect.Height()-GetSystemMetrics(SM_CYHSCROLL)-4;

		m_gantt.Create(NULL,NULL,WS_CHILD | WS_VISIBLE ,m_ganttRect, this, ID_GANTT_CTRL);
		m_gantt.m_gantt_view=this;
	}
	// finally, create the horizontal scroll bar
	{
		CRect m_scrollRect;
		m_scrollRect.left=0;
		m_scrollRect.top = m_ganttRect.bottom;
		m_scrollRect.right = m_ganttRect.Width()-GetSystemMetrics(SM_CXVSCROLL);
		m_scrollRect.bottom = m_wndRect.bottom;

		m_horScrollBar.Create(WS_CHILD | WS_VISIBLE | WS_DISABLED | SBS_HORZ | SBS_TOPALIGN, m_scrollRect, this, ID_GANTT_SCROLLBAR);
	}

}

void CGanttView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	Initialize();	

	//m_gantt.SetImageList(&m_cImageList, TVSIL_NORMAL);

	CRect m_wndRect;
	GetClientRect(&m_wndRect);
	MoveWindow(0, 0, m_wndRect.Width(), m_wndRect.Height());
	m_TLInitialized = TRUE;	
}

int CGanttView::OnMouseActivate( CWnd* pDesktopWnd, 
                                  UINT nHitTest, 
                                  UINT message )
{
  return MA_ACTIVATE;
}

void CGanttView::Update(bool bUpdateCalendar)
{
	COleDateTime old_max_date,new_max_date;
	m_gantt.GetMaxDate(old_max_date);
	COleDateTime old_min_date,new_min_date;
	m_gantt.GetMinDate(old_min_date);
	int old_pix_in_day=m_gantt.GetPixelsInDay();
	int old_dlit=m_gantt.GetDlitDays(old_min_date,old_max_date);
	int m_nCurPos = m_horScrollBar.GetScrollPos();
	int old_min_pos,old_max_pos;
	m_horScrollBar.GetScrollRange(&old_min_pos,&old_max_pos);
	if(bUpdateCalendar) m_gantt.UpdateCalendar();
	if(m_tree_view)
	{
		HTREEITEM hRoot=m_tree_view->m_tree.GetRootItem();
		CRect rect;
		if(hRoot) 
		{
			m_tree_view->m_tree.GetItemRect(hRoot,rect,false);
			m_gantt.m_blockHeight= rect.Height();
		}
	}
	m_gantt.GetMaxDate(new_max_date);
	m_gantt.GetMinDate(new_min_date);
	bool bNeedScroll=false;
	if(old_max_date!=new_max_date || old_min_date!=new_min_date) 
	{
		ResetScrollBar();
		bNeedScroll=true;
		if(m_bShrinkToFit) m_gantt.AutoResizeDiagram(false,false);
	}
	if(bNeedScroll)
	{
		int new_min_pos,new_max_pos;
		m_horScrollBar.GetScrollRange(&new_min_pos,&new_max_pos);
		int new_pix_in_day=m_gantt.GetPixelsInDay();
		int new_min_date_delta=m_gantt.GetDlitDays(old_min_date,new_min_date);
		int scrolling_day=(int)m_nCurPos/old_pix_in_day;
		m_nCurPos=scrolling_day*new_pix_in_day-new_min_date_delta*new_pix_in_day;
		if(m_nCurPos>new_max_pos) m_nCurPos=new_max_pos;
		if(m_nCurPos<new_min_pos) m_nCurPos=new_min_pos;
		m_gantt.m_nOffset = -m_nCurPos;
		m_horScrollBar.SetScrollPos(m_nCurPos);
		CRect m_scrollRect;
		m_gantt.GetClientRect(&m_scrollRect);
		m_gantt.ScrollWindow(m_nCurPos, 0, &m_scrollRect, &m_scrollRect);
	}
	
	Invalidate();
}

BOOL CGanttView::VerticalScrollVisible()
{	
	int sMin, sMax;
	m_gantt.GetScrollRange(SB_VERT, &sMin, &sMax);	
	return sMax!=0;
}

BOOL CGanttView::HorizontalScrollVisible()
{
	int sMin, sMax;
	m_horScrollBar.GetScrollRange(&sMin, &sMax);
	return sMax!=0;
}

int CGanttView::StretchWidth(int m_nWidth, int m_nMeasure)
{	
	return ((m_nWidth/m_nMeasure)+1)*m_nMeasure;//put the fixed for +1 in brackets f/0 error
}


void CGanttView::ResetScrollBar()
{
	// resetting the horizontal scroll bar

	int m_nTotalWidth=0, m_nPageWidth;

	CRect m_ganttRect;
	m_gantt.GetClientRect(&m_ganttRect);

	CRect m_wndRect;
	GetClientRect(&m_wndRect);

/*	CRect m_headerRect;
	m_gantt.m_wndHeader.GetClientRect(&m_headerRect);*/

	CRect m_barRect;
	m_horScrollBar.GetClientRect(m_barRect);

	m_nPageWidth = m_ganttRect.Width();

	m_nTotalWidth = m_gantt.GetColumnsWidth();

	if(m_nTotalWidth > m_nPageWidth)
	{
		// show the scroll bar and adjust it's size
		{
			m_horScrollBar.EnableWindow(TRUE);

			m_horScrollBar.ShowWindow(SW_SHOW);

			// the tree becomes smaller
			//m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height()-m_gantt.m_headerHeight, SWP_NOMOVE);
			m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height(), SWP_NOMOVE);

			if(!VerticalScrollVisible())
				// i.e. vertical scroll bar isn't visible
			{
				m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_barRect.Height(), SWP_NOMOVE);
			}
			else
			{
				m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL), m_barRect.Height(), SWP_NOMOVE);
			}
		}

		m_horScrollBar.SetScrollRange(0, m_nTotalWidth-m_nPageWidth);

		// recalculate the offset
		{
		/*	CRect m_wndHeaderRect;
			m_gantt.m_wndHeader.GetWindowRect(&m_wndHeaderRect);
			ScreenToClient(&m_wndHeaderRect);

			m_gantt.m_nOffset = m_wndHeaderRect.left;
			m_horScrollBar.SetScrollPos(-m_gantt.m_nOffset);*/
			m_gantt.m_nOffset = 0;
			m_horScrollBar.SetScrollPos(0);
		}
	}
	else
	{
		m_horScrollBar.EnableWindow(FALSE);

		// we no longer need it, so hide it!
		{
			m_horScrollBar.ShowWindow(SW_HIDE);

			//m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height() - m_gantt.m_headerHeight, SWP_NOMOVE);
			m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height(), SWP_NOMOVE);
			// the tree takes scroll's place
		}

		m_horScrollBar.SetScrollRange(0, 0);

		// set scroll offset to zero
		{
			m_gantt.m_nOffset = 0;
			m_gantt.Invalidate();
/*			CRect m_headerRect;
			m_gantt.m_wndHeader.GetWindowRect(&m_headerRect);*/
			CRect m_wndRect;
			GetClientRect(&m_wndRect);
		//	m_gantt.m_wndHeader.SetWindowPos(&wndTop, m_gantt.m_nOffset, 0, max(StretchWidth(m_gantt.GetColumnsWidth(),m_wndRect.Width()),m_wndRect.Width()), m_headerRect.Height(), SWP_SHOWWINDOW);
			
		}
	}
}





void CGanttView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	SetScrollRange(SB_HORZ, 0, 0);
	SetScrollRange(SB_VERT, 0, 0);

	if(m_TLInitialized)
	{	
		// resize all the controls	
		CRect m_wndRect;
		GetClientRect(&m_wndRect);

		CRect m_scrollRect;
		m_horScrollBar.GetClientRect(&m_scrollRect);

		m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height() - m_scrollRect.Height(), SWP_NOMOVE);

		CRect m_ganttRect;
		m_gantt.GetClientRect(&m_ganttRect);
		m_horScrollBar.MoveWindow(0, m_ganttRect.bottom, m_wndRect.Width(), m_scrollRect.Height());

		if(m_gantt.GetColumnsWidth() > m_ganttRect.Width())
		{
			// show the horz scroll bar
			{
				CRect m_barRect;
				m_horScrollBar.GetClientRect(&m_barRect);			

				m_horScrollBar.EnableWindow(TRUE);

				m_horScrollBar.ShowWindow(SW_SHOW);

				// the tree becomes smaller
				m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height(), SWP_NOMOVE);

				int tfdsfsd=m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL);
				m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL), m_barRect.Height(), SWP_NOMOVE);
				
			}

			m_horScrollBar.SetScrollRange(0, m_gantt.GetColumnsWidth()-m_ganttRect.Width());

		}
		else
		{
			// hide the scroll bar
			{
				m_horScrollBar.EnableWindow(FALSE);

				m_horScrollBar.ShowWindow(SW_HIDE);

				// the tree becomes larger
				m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height(), SWP_NOMOVE);				
			}

			m_horScrollBar.SetScrollRange(0, 0);
		}

		m_gantt.ResetVertScrollBar();
		
		// Reset the header control position and scroll
		// the tree control as required.
		int m_nCurPos = m_horScrollBar.GetScrollPos();
		m_gantt.m_nOffset = -m_nCurPos;
	
		// smoothly scroll the tree control
	    {
		CRect m_scrollRect;
		m_gantt.GetClientRect(&m_scrollRect);
		m_gantt.ScrollWindow(m_nCurPos, 0, &m_scrollRect, &m_scrollRect);
		}
		
		GetClientRect(&m_wndRect);

		if(m_bShrinkToFit) m_gantt.AutoResizeDiagram();
	}	
}

void CGanttView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CRect m_ganttRect;
	m_gantt.GetClientRect(&m_ganttRect);
	
	// if horizontal scroll bar 
	if(pScrollBar == &m_horScrollBar)
	{
		int m_nCurPos = m_horScrollBar.GetScrollPos();
		int m_nPrevPos = m_nCurPos;
		// decide what to do for each diffrent scroll event
		switch(nSBCode)
		{
			case SB_LEFT:			m_nCurPos = 0;
									break;
			case SB_RIGHT:			m_nCurPos = m_horScrollBar.GetScrollLimit()-1;
									break;
			case SB_LINELEFT:		m_nCurPos = max(m_nCurPos-6, 0);
									break;
			case SB_LINERIGHT:		m_nCurPos = min(m_nCurPos+6, m_horScrollBar.GetScrollLimit()-1);
									break;
			case SB_PAGELEFT:		m_nCurPos = max(m_nCurPos-m_ganttRect.Width(), 0);
									break;
			case SB_PAGERIGHT:		m_nCurPos = min(m_nCurPos+m_ganttRect.Width(), m_horScrollBar.GetScrollLimit()-1);
									break;
			case SB_THUMBTRACK:
			case SB_THUMBPOSITION:  if(nPos==0)
									    m_nCurPos = 0;
								    else
									    m_nCurPos = min(StretchWidth(nPos, 6), m_horScrollBar.GetScrollLimit()-1);
								    break;
		}		

		m_horScrollBar.SetScrollPos(m_nCurPos);
		m_gantt.m_nOffset = -m_nCurPos;

		// smoothly scroll the control
		/*{
			CRect m_scrollRect;
			m_gantt.GetClientRect(&m_scrollRect);
			m_gantt.ScrollWindow(m_nPrevPos - m_nCurPos, 0, &m_scrollRect, &m_scrollRect);
		}*/

		m_gantt.Invalidate();
	}	
	CView::OnHScroll(nSBCode, nPos, pScrollBar);
}

bool CGanttView::ZoomIn(int step)
{
	int pixelsInDay=m_gantt.GetPixelsInDay();
	if(0!=step) return m_gantt.SetPixelsInDay(pixelsInDay+step);
	
	pixelsInDay=(int)(pixelsInDay*1.4) +1 ;
	return m_gantt.SetPixelsInDay(pixelsInDay);
}

bool CGanttView::ZoomOut(int step)
{
	int pixelsInDay=m_gantt.GetPixelsInDay();
	if(0!=step) return m_gantt.SetPixelsInDay(pixelsInDay-step);

	pixelsInDay=(int)(pixelsInDay*10/14);	
	return m_gantt.SetPixelsInDay(pixelsInDay);
}




void CGanttView::ReloadItemInfo(CGanttItem *item)
{
	if(0==item) return;
	CaplInstance *project=item->prj;
	if(0==project) return;
	if(0==project->GetType()) return;

	CaplProjectManager *m_project_mgr=m_gantt.m_project_mgr;
	CaplAPI *m_api=m_gantt.m_api;

	CString buf,sdate;
	CaplInstance *lock=m_project_mgr->CheckMyLock(project,false);


	if(lock)
	{
		item->instMyLock=lock;
		m_api->m_data.GetAttr(lock,m_project_mgr->a_project_adm_ver_id,item->id);
		m_api->m_data.GetAttr(lock,m_project_mgr->a_project_adm_ver_name,item->name);
		m_api->m_data.GetAttr(lock,m_project_mgr->a_project_adm_ver_date_planned_begin,sdate);
		aplString2Date(sdate,item->pl_date_begin);
		m_api->m_data.GetAttr(lock,m_project_mgr->a_project_adm_ver_date_planned_end,sdate);
		aplString2Date(sdate,item->pl_date_end);
		//m_api->m_data.GetAttr(lock,m_project_mgr->a_project_adm_ver_persentage,item->percentage);
		
	}
	else
	{
		item->instMyLock=0;
		m_api->m_data.GetAttr(project,m_project_mgr->a_project_id,item->id);
		m_api->m_data.GetAttr(project,m_project_mgr->a_project_name,item->name);
		m_api->m_data.GetAttr(project,m_project_mgr->a_project_date_planned_begin,sdate);
		aplString2Date(sdate,item->pl_date_begin);
		m_api->m_data.GetAttr(project,m_project_mgr->a_project_date_planned_end,sdate);
		aplString2Date(sdate,item->pl_date_end);
		//m_api->m_data.GetAttr(project,m_project_mgr->a_project_persentage,item->percentage);
	}

	// 20.03.2023  Убрано использование a_project_adm_ver_persentage  чтобы не было путаницы
	m_api->m_data.GetAttr(project,m_project_mgr->a_project_persentage,item->percentage);

	m_api->m_data.GetAttr(project,m_project_mgr->a_project_date_actual_begin,sdate);
	aplString2Date(sdate,item->act_date_begin);
	m_api->m_data.GetAttr(project,m_project_mgr->a_project_date_actual_end,sdate);
	aplString2Date(sdate,item->act_date_end);

	if(item->act_date_begin.GetStatus()==COleDateTime::valid && item->act_date_end.GetStatus()!=COleDateTime::valid)
	{
		m_project_mgr->GetWorkedProjectEndPrognoz(project,item->act_date_end_prognoz);
	}
}



void CGanttView::UpdateGanttView(bool bUpdateCalendar,bool renum)
{
	int i;

	CaplProjectManager *m_project_mgr=m_gantt.m_project_mgr;

	if(bUpdateCalendar || renum) 
	{
		aplExtent ext_prj;

		for(i=0; i<m_items.GetSize(); i++)
		{
			ReloadItemInfo(m_items[i]);
			ext_prj.Add(m_items[i]->prj);
		}
		int counter=0;
		m_gantt.RenumGanttItems(TVI_ROOT,counter);
		m_gantt.UpdateRelations();

		if(m_bShowPrognoz)
		{
			CaplMap map_prj_index;
			CaplProjectManager::apl_CPrjPrognozItem_array array_progn_items;

			m_project_mgr->CalcProjectsEndPrognoz(ext_prj,map_prj_index, array_progn_items,bUpdateCalendar);
			for(i=0; i<m_items.GetSize(); i++)
			{
				CGanttItem *item=m_items[i];
				if(0==item) continue;
				int k=map_prj_index.GetByIn((long)item->prj);
				if(k<0) return;
				ASSERT(k<array_progn_items.GetSize());
				CaplProjectManager::CPrjPrognozItem *prgn_item=array_progn_items[k];
				item->act_date_end_prognoz=prgn_item->prognoz_end;
				item->act_date_begin_prognoz=prgn_item->prognoz_begin;
				item->prev_progn_prj=prgn_item->prev_progn_prj;
				item->first_progn_sub_prj=prgn_item->first_progn_sub_prj;
				item->last_progn_sub_prj =prgn_item->last_progn_sub_prj;

				m_project_mgr->GetProjectColor(item->prj,item->act_date_end_prognoz,item->color);
				
			}
		}
		else
		{
			for(i=0; i<m_items.GetSize(); i++)
			{
				CGanttItem *item=m_items[i];
				if(0==item) continue;
				m_project_mgr->GetWorkedProjectEndPrognoz(item->prj,item->act_date_end_prognoz);
				m_project_mgr->GetProjectColor(item->prj,item->act_date_end_prognoz,item->color);
			}
		}
	}
	Update(bUpdateCalendar);
}
