// DLoaderView.cpp : implementation of the CDLoaderView class
//

#include "stdafx.h"
#include "DLoader.h"

#ifdef _DOWNLOAD_FOR_PRODUCTION
#include "atlconv.h"

#include "./phasecheck/PhaseCheckBuild.h"
#endif

#define START_ICON_SIZE 25

#include "MainFrm.h"
#include "DLoaderView.h"

#define COLOR_PASS    RGB(0,202,0)
#define COLOR_FAILED  RGB(255,0,0)
#define COLOR_WAIT    RGB(0,0,255)

#define BUTTON_POS    2

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

#define MAXHEIGHT 30

static CString StatusString[] = 
{
    "Waiting",
    "Checking baudrate",
    "Connecting",
    "Erasing flash",
    "Downloading...",
    "Reading Flash",
    "Reseting",
    "Read Chip Type",
    "Read NV Item",
    "Change Baud",
    "Finish",
    "Unplugged",
#ifdef _DOWNLOAD_FOR_PRODUCTION
	"Paused"
#endif
};


#define   DL_TIMER   0x10000
/////////////////////////////////////////////////////////////////////////////
// CDLoaderView


IMPLEMENT_DYNCREATE(CDLoaderView, CListView)

BEGIN_MESSAGE_MAP(CDLoaderView, CListView)
	//{{AFX_MSG_MAP(CDLoaderView)
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_SIZE()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
    ON_NOTIFY(HDN_ENDTRACK,0,OnEndTrack)
    ON_WM_MEASUREITEM_REFLECT()
    ON_MESSAGE( BM_CHECK_BAUDRATE, OnBMCheckBaud )
    ON_MESSAGE( BM_CONNECT, OnBMConnect )
    ON_MESSAGE( BM_ERASE_FLASH, OnBMEraseFlash )
    ON_MESSAGE( BM_DOWNLOAD, OnBMDownLoad )
    ON_MESSAGE( BM_DOWNLOAD_PROCESS, OnBMDLoadProcess )
    ON_MESSAGE( BM_READ_FLASH, OnBMReadFlash )
    ON_MESSAGE( BM_READ_FLASH_PROCESS, OnBMReadFlashProcess )
    ON_MESSAGE( BM_RESET, OnBMReset )
    ON_MESSAGE( BM_READ_CHIPTYPE, OnBMReadChipType )
    ON_MESSAGE( BM_READ_NVITEM, OnBMReadNVItem )
    ON_MESSAGE( BM_CHANGE_BAUD, OnBMChangeBuad )    
    ON_MESSAGE (BM_BEGIN, OnBMBegin )
    ON_MESSAGE (BM_FILE_BEGIN, OnBMFileBegin )
    ON_MESSAGE (BM_END, OnBMEnd )
#if defined(_DOWNLOAD_FOR_PRODUCTION)
	ON_MESSAGE(WM_REQUIRE_SN, OnAcquireBarcode)
#endif
#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	ON_NOTIFY (HDN_BEGINTRACK, 0, OnBeginTrack)
	ON_COMMAND_RANGE( IDC_BTN_START1, IDC_BTN_START16, OnBtnStart )
#endif
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CDLoaderView construction/destruction

CDLoaderView::CDLoaderView()
{
	m_nHeaderHeight = 0;
#ifdef _DOWNLOAD_FOR_PRODUCTION
	m_bSNDlgShow = FALSE;
	m_pCurBarcodeDlg = NULL;
#endif
}

CDLoaderView::~CDLoaderView()
{
    for(int i=0;i<m_ProgArr.GetSize();i++)
    {
        delete m_ProgArr[i];
    }
#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	for(i=0;i<m_ButtonArr.GetSize();i++)
    {
        delete m_ButtonArr[i];
    }
#endif
}

BOOL CDLoaderView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CListView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CDLoaderView drawing

void CDLoaderView::OnDraw(CDC* /*pDC*/)
{
	CDLoaderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
}

void CDLoaderView::OnInitialUpdate()
{
	CListView::OnInitialUpdate();

    CListCtrl* pListCtrl = &GetListCtrl();
    
    //modify the style
    DWORD dwStyle = pListCtrl->GetStyle();
    dwStyle |= LVS_REPORT | LVS_OWNERDRAWFIXED;
    pListCtrl->ModifyStyle(0,dwStyle);

    DWORD dwExStyle = pListCtrl->GetExtendedStyle();
    dwExStyle |= LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT;
    pListCtrl->SetExtendedStyle(dwExStyle);
    pListCtrl->SetBkColor(RGB(232, 232, 232));	
    //Add columns
    pListCtrl->InsertColumn( 0, _T("Port"), LVCFMT_CENTER, 50 );
	pListCtrl->InsertColumn( STEP_INDEX, _T("Step"), LVCFMT_CENTER, 100 );
	pListCtrl->InsertColumn( STATUS_INDEX, _T("Status"),LVCFMT_CENTER,180);	
    pListCtrl->InsertColumn( PROG_INDEX, _T("Progress"),LVCFMT_CENTER,400);
	pListCtrl->InsertColumn( TIME_INDEX, _T("Time(s)"),LVCFMT_CENTER,100);
	

	m_imgList.Create(1,24,TRUE|ILC_COLOR24,1,0);
	pListCtrl->SetImageList(&m_imgList,LVSIL_SMALL);

    //Get headerCtrl's height
    CHeaderCtrl* pHeader = pListCtrl->GetHeaderCtrl();
    CRect rcHeader;
    pHeader->GetItemRect(0,rcHeader);
    m_nHeaderHeight = rcHeader.Height();


	CFont font;
	LOGFONT lf;
	memset(&lf,0,sizeof(LOGFONT));
	lf.lfHeight = 24;
	_tcscpy(lf.lfFaceName,_T("宋体"));
	font.CreateFontIndirect(&lf);
	SetFont(&font);

    // TODO: You may populate your ListView with items by directly accessing
	//  its list control through a call to GetListCtrl().
}

/////////////////////////////////////////////////////////////////////////////
// CDLoaderView diagnostics

#ifdef _DEBUG
void CDLoaderView::AssertValid() const
{
	CListView::AssertValid();
}

void CDLoaderView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}

CDLoaderDoc* CDLoaderView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDLoaderDoc)));
	return (CDLoaderDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDLoaderView message handlers
int CDLoaderView::IsValidPort( int nPort)
{
    int nItem = GetPortIndex( nPort );
    if(nItem == -1)
        return -1;
    
    if( nItem > m_ProgArr.GetSize() - 1)
        return -1;   
    
    return nItem;
}


BOOL CDLoaderView::StartProg(int nPort,int nMin,int nMax)
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    CListCtrl* pList = &GetListCtrl();

    CRect rc;
    pList->GetSubItemRect(nItem,PROG_INDEX,LVIR_BOUNDS,rc);

	BOOL bLastSuccess = TRUE;
	m_ItemLatestRltMap.Lookup(nItem,bLastSuccess);
	if(g_theApp.m_bColorFlag)
	{
		if(bLastSuccess)
		{
			m_ProgArr[nItem]->SetBitmap(IDB_BMP_PROG_BLOCK);
		}
		else
		{
			m_ProgArr[nItem]->SetBitmap(IDB_BMP_PROG_BROWN);
		}
	}

    m_ProgArr[nItem]->SetRange(nMin,nMax);

    m_ProgArr[nItem]->MoveWindow(rc);

    m_ProgArr[nItem]->ShowWindow(SW_SHOW);

    return TRUE;
}

BOOL CDLoaderView::StepProg(int nPort,int nStep)
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    m_ProgArr[nItem]->OffsetPos( nStep );

    return TRUE;
}

BOOL CDLoaderView::EndProg(int nPort)
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    m_ProgArr[nItem]->SetPos(0);
    m_ProgArr[nItem]->ShowWindow(SW_HIDE);

    return TRUE;
}

BOOL CDLoaderView::SetProgStep(int nPort,int nStep)
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    if(nStep <= 0)
        nStep = 1;

    m_ProgArr[nItem]->SetStep(nStep);

    return TRUE;
}

BOOL CDLoaderView::SetProgPos(int nPort,int nPos)
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    m_ProgArr[nItem]->SetPos(nPos);	
	m_ProgArr[nItem]->Invalidate(FALSE);


    return TRUE;
}


void CDLoaderView::ResizeProg()
{
    CListCtrl* pList = &GetListCtrl();

    for(int i=0;i<m_ProgArr.GetSize();i++)
    {
        CRect rc;
        pList->GetSubItemRect(i,PROG_INDEX,LVIR_BOUNDS,rc);
        rc.DeflateRect(0,1);

        m_ProgArr[i]->MoveWindow(rc);
        m_ProgArr[i]->Invalidate();
    }
}

BOOL CDLoaderView::AddProg( int nPort,BOOL bOpen )
{
    CListCtrl* pListCtrl = &GetListCtrl();

	int nIndex = -1;
	if(m_PortMap.Lookup(nPort,nIndex))
	{
		if(nIndex>=0)
		{
			CString strPort;
			if( bOpen )
			{
				strPort.Format( _T("%d"), nPort );
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
				if(g_theApp.m_bManual && m_ButtonArr.GetSize()>nIndex)
				{
					if(!m_ButtonArr[nIndex]->IsWindowEnabled())
					{
						m_ButtonArr[nIndex]->ShowWindow(SW_SHOW);
						m_ButtonArr[nIndex]->EnableWindow(TRUE);
					}
				}
#endif
			}
			else
			{
				if( nPort < 0 )
				{
					strPort = _T("   ");
				}
				else
				{
					strPort.Format( _T("%d"), nPort );
					strPort += STRING_BADPORT;
				}
			}
			pListCtrl->SetItemText( nIndex,0,strPort );
		}
		return TRUE;
	}
    
    int nCount = m_PortMap.GetCount();
    m_PortMap.SetAt(nPort,nCount);
    m_StepMap.SetAt( nPort,DL_NO_FILE  );
    
    //Create progress controls
    //CProgressCtrl* pProg = new CProgressCtrl;
	CProgressCtrlST * pProg = new CProgressCtrlST;
    BOOL bRet;
    bRet = pProg->Create( PBS_SMOOTH | WS_CHILD,CRect(0,0,0,0),this,1);
    if(!bRet)
        return bRet;
	
    pProg->SetBitmap(IDB_BMP_PROG_BLOCK,FALSE);
    pProg->SetRange(0,100);
    pProg->SetStep(1);
	
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
#ifdef _SPUPGRADE
	if(g_theApp.m_bManual)
	{
#endif
		UINT nId = IDC_BTN_START1 + m_PortMap.GetCount() - 1;
		CButton* pBtn = new CButton;
		pBtn->Create(_T("Start"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_BITMAP, CRect(0,0,10,10), this, nId);
		CBitmap bitmap ;
		pBtn->SetBitmap(::LoadBitmap(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_START)) );
		if(g_theApp.m_bManual)
		{
			pBtn->ShowWindow(SW_SHOW);
			pBtn->EnableWindow(TRUE);
		}
		else
		{
			pBtn->ShowWindow(SW_HIDE);
			pBtn->EnableWindow(FALSE);
		}
		CListCtrl* pList = &GetListCtrl();
		CRect rc;
		pList->GetSubItemRect(m_PortMap.GetCount()-1, BUTTON_POS, LVIR_BOUNDS, rc);
		rc.right = rc.left + START_ICON_SIZE; 
		rc.top     = rc.top + (rc.Height() - START_ICON_SIZE)/2;
		rc.bottom  = rc.top + START_ICON_SIZE;
		pBtn->MoveWindow(rc);	
		m_ButtonArr.Add(pBtn);
#ifdef _SPUPGRADE
	}
#endif
#endif

    //Add to array
    int num = m_ProgArr.Add(pProg);
    num++;

    //To recalculate the window's rect and the item height of
    //the list control
//    CRect rc;
//    GetClientRect(rc);
//    MoveWindow(rc);    
//
//    m_Font.DeleteObject();
//    int height = rc.Height() / num - 2;
//    if(height > MAXHEIGHT)
//        height = MAXHEIGHT;
//
//    m_Font.CreateFont(height/2, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, _T("Courier"));


    CString strText;
    if( bOpen )
    {
        strText.Format( _T("%d"), nPort );
    }
    else
    {
        if( nPort < 0 )
        {
            strText = _T("   ");
        }
        else
        {
            strText.Format( _T("%d"), nPort );
			strText += STRING_BADPORT;
        }
    }
    pListCtrl->InsertItem( nCount,strText );
    m_ItemLatestRltMap.SetAt( nCount, TRUE );  

    return TRUE;
}

BOOL CDLoaderView::RemoveAll()
{
    m_PortMap.RemoveAll();
    m_StepDescription.RemoveAll();
    m_ItemLatestRltMap.RemoveAll();
    
    for(int i=0;i<m_ProgArr.GetSize();i++)
    {
        m_ProgArr[i]->DestroyWindow();
        delete m_ProgArr[i];
    }

    m_ProgArr.RemoveAll();

#if defined( _DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	// if g_theApp.m_bManual is false for _SPUPGRADE
	// m_ButtonArr is empty, so the code sector is not bad
	for(i=0;i<m_ButtonArr.GetSize();i++)
    {
        m_ButtonArr[i]->DestroyWindow();
        delete m_ButtonArr[i];
    }

    m_ButtonArr.RemoveAll();
#endif

    GetListCtrl().DeleteAllItems();

    return TRUE;
}

void CDLoaderView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
    ResizeProg();
#if defined( _DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	ResizeButton();
#endif
	CListView::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CDLoaderView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
    ResizeProg();
#if defined( _DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	ResizeButton();
#endif 
	CListView::OnVScroll(nSBCode, nPos, pScrollBar);
}


void CDLoaderView::OnEndTrack(NMHDR* /*pNMHDR*/, LRESULT* pResult) 
{
    ResizeProg();
	TRACE(_T("On End Track!\n"));

#if defined( _DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	ResizeButton();
	// if g_theApp.m_bManual is false for _SPUPGRADE
	// m_ButtonArr is empty, so the code sector is not bad
	for(int i=0; i<m_ButtonArr.GetSize();i++)
    {
		if(m_ButtonArr[i]->IsWindowEnabled())
		{
		   m_ButtonArr[i]->ShowWindow(SW_SHOW);  
		}
    }
#endif

	*pResult = 0;
}

void CDLoaderView::MeasureItem( LPMEASUREITEMSTRUCT pMeasureItem )
{
    //pMeasureItem->itemHeight = 30;
    int size = m_ProgArr.GetSize();

    if(size == 0)
    {
        //have no progress ctrl,use default
        return;
    }

    //Adjust the list view to just contain progress ctrls
    CRect rc;
    GetClientRect(rc);

    int Height = ( rc.Height() - m_nHeaderHeight ) / size;
    if(Height > MAXHEIGHT)
        Height = MAXHEIGHT;

    pMeasureItem->itemHeight = Height;
}


void CDLoaderView::OnSize(UINT nType, int cx, int cy) 
{
	CListView::OnSize(nType, cx, cy);
	
    ResizeProg();	

#if defined( _DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	ResizeButton();
#endif
}

void CDLoaderView::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CListCtrl* pList = &GetListCtrl();

    CRect rc;
    CString str;

    ::SetBkMode(lpDrawItemStruct->hDC,OPAQUE);

    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    COLORREF color = ::GetSysColor(COLOR_WINDOW);
    COLORREF colorText = ::GetSysColor(COLOR_WINDOWTEXT);

    //draw the fisrt subitem based on second sub item
    pList->GetSubItemRect(lpDrawItemStruct->itemID,STEP_INDEX,LVIR_BOUNDS,rc);
    CRect rcFirst = lpDrawItemStruct->rcItem;
    rcFirst.right = rc.left;
    str = pList->GetItemText(lpDrawItemStruct->itemID,0);
    if(pDC != NULL)
    {
        pDC->FillSolidRect(rcFirst,color);
    }
    ::DrawText(lpDrawItemStruct->hDC,str,str.GetLength(),rcFirst,DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    //Draw the second subitem
    pList->GetSubItemRect(lpDrawItemStruct->itemID,STEP_INDEX,LVIR_BOUNDS,rc);
    str = pList->GetItemText(lpDrawItemStruct->itemID,STEP_INDEX);
    if(pDC != NULL)
    {
        pDC->FillSolidRect(rc,color);
    }
    ::DrawText(lpDrawItemStruct->hDC,str,str.GetLength(),rc,DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    //draw the third subitem
    pList->GetSubItemRect(lpDrawItemStruct->itemID,STATUS_INDEX,LVIR_BOUNDS,rc);
    str = pList->GetItemText(lpDrawItemStruct->itemID,STATUS_INDEX);
    if(pDC != NULL)
    {
        pDC->FillSolidRect(rc,color);
    }
    ::DrawText(lpDrawItemStruct->hDC,str,str.GetLength(),rc,DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    //set font
	CFont* pFont = (CFont*)::SelectObject(lpDrawItemStruct->hDC,HFONT(m_Font));

    //draw the fourth subitem
    pList->GetSubItemRect(lpDrawItemStruct->itemID,PROG_INDEX,LVIR_BOUNDS,rc);
    str = pList->GetItemText(lpDrawItemStruct->itemID,PROG_INDEX);

    
    if(str.Find(STRING_PASS) != -1 )
    {		
		::SetTextColor(lpDrawItemStruct->hDC,COLOR_PASS);		
    }
    else if(str.Find(STRING_FAILED) != -1)
    {
        ::SetTextColor(lpDrawItemStruct->hDC,COLOR_FAILED);  
    }
    else
    {
		BOOL bLastSuccess = TRUE;
        m_ItemLatestRltMap.Lookup( lpDrawItemStruct->itemID, bLastSuccess );
		if(g_theApp.m_bColorFlag && !bLastSuccess)
		{
			::SetTextColor(lpDrawItemStruct->hDC,COLOR_FAILED);
		}
		else
		{
			::SetTextColor(lpDrawItemStruct->hDC,COLOR_WAIT);
		}
    }

    if(pDC != NULL)
    {
        pDC->FillSolidRect(rc,color);
    }
    ::DrawText(lpDrawItemStruct->hDC,str,str.GetLength(),rc,DT_CENTER | DT_VCENTER  | DT_SINGLELINE);

	//draw the 5th subitem
    pList->GetSubItemRect(lpDrawItemStruct->itemID,TIME_INDEX,LVIR_BOUNDS,rc);
    str = pList->GetItemText(lpDrawItemStruct->itemID,TIME_INDEX);
	::SetTextColor(lpDrawItemStruct->hDC,COLOR_WAIT);
    if(pDC != NULL)
    {
        pDC->FillSolidRect(rc,color);
    }
    ::DrawText(lpDrawItemStruct->hDC,str,str.GetLength(),rc,DT_CENTER | DT_VCENTER | DT_SINGLELINE);

	//设置回系统颜色
    ::SetTextColor(lpDrawItemStruct->hDC,colorText);
    
    ::SelectObject(lpDrawItemStruct->hDC,pFont);

}

int CDLoaderView::GetPortIndex(int nPort)
{
    int index;
    BOOL bRet = m_PortMap.Lookup(nPort,index);
    if(bRet)
        return index;
    else
        return -1;
}

BOOL CDLoaderView::SetStatus(int nPort,DL_STAGE stage,BOOL bNeedProg,
                             int nMin /* = 0 */,int nMax /* = 0 */)
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    CListCtrl* pList = &(GetListCtrl());
    
    DL_STAGE oriStage = (DL_STAGE)pList->GetItemData( nItem );
    if( oriStage == DL_FINISH_STAGE && stage == DL_UNPLUGGED_STAGE )
    {
        // Ignore this message
        return TRUE;
    }
#ifdef _DOWNLOAD_FOR_PRODUCTION
	if( oriStage == DL_FINISH_STAGE && stage == DL_NONE_STAGE )
    {
        // Ignore this message
        return TRUE;
    }
#endif


    //save status
    pList->SetItemData( nItem,stage );
    pList->SetItemText( nItem,STATUS_INDEX,StatusString[stage]);
	if(DL_CHK_BAUD == stage)
	{
		pList->SetItemText( nItem,TIME_INDEX,_T("0"));
	}
    
    if(bNeedProg)
    {
        EndProg( nPort );
        StartProg( nPort,nMin,nMax );
    }
    else
    {
        if(stage < DL_CONNECT)
        {
            EndProg( nPort );
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
			// keep the previous result
			if(g_theApp.m_bManual || !g_theApp.m_bResultHolding)
			{
				pList->SetItemText( nItem,PROG_INDEX,STRING_WAIT);
			}
			else
			{
				CString strText = pList->GetItemText(nItem,PROG_INDEX);
				if( !strText.IsEmpty() && ( strText.Find(STRING_PASS)==0  || 
						 strText.Find(STRING_PASS) == 10 || // [Removed]+space
					     strText.Find(STRING_FAILED) != -1) )
				{	
					//if not add "Previous" at head of strText, add it
					if(strText.Find(_T("Previous")) != 0)
					{
						strText.Insert(0,_T("Previous "));
					}
					pList->SetItemText( nItem,PROG_INDEX,strText);
				}
				else
				{
					pList->SetItemText( nItem,PROG_INDEX,STRING_WAIT);
				}
			}
#else
			pList->SetItemText( nItem,PROG_INDEX,STRING_WAIT);
#endif
            
        }
        else if( stage < DL_UNPLUGGED_STAGE )
        {
            EndProg(nPort);
            pList->SetItemText( nItem,PROG_INDEX,STRING_DOING);
        }
    }
    
    return TRUE;    
}

BOOL CDLoaderView::GetStatus( int nPort,DL_STAGE& stage )
{
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    CListCtrl* pList = &GetListCtrl();
    stage = (DL_STAGE)pList->GetItemData( nItem );
    
    return TRUE;
}

void CDLoaderView::ResetStatus( int nPort )
{
    SetStatus( nPort, DL_NONE_STAGE, FALSE );

    int nItem = IsValidPort( nPort );
    if( nItem != -1 )
    {
        m_ItemLatestRltMap.RemoveKey(nItem);
    }
}

BOOL CDLoaderView::SetResult(int nPort,BOOL bSuccess,
							  LPCTSTR lpszErrMsg /* = NULL  */,int nFlag /*= 1*/ )
{    
	UNUSED_ALWAYS(bSuccess);
	
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;

	CListCtrl* pListCtrl = &GetListCtrl();
	
	if(nFlag == 2)
	{
		CString strItemText = pListCtrl->GetItemText( nItem, PROG_INDEX);
		if(strItemText.Find(_T("[Removed]")) !=0)
		{
			strItemText.Insert(0,_T("[Removed] "));
		}
		pListCtrl->SetItemText( nItem, PROG_INDEX, strItemText );
		return TRUE;
	}



    BOOL bSuc = FALSE;
	if((nFlag && lpszErrMsg == NULL) || (!nFlag && bSuccess))
		bSuc = TRUE;      
    
    
    pListCtrl->SetItemData( nItem,DL_FINISH_STAGE );
    pListCtrl->SetItemText( nItem, STATUS_INDEX, StatusString[DL_FINISH_STAGE]);

	CString strTime = pListCtrl->GetItemText(nItem,TIME_INDEX);
	if(!strTime.IsEmpty())
	{
		// "s" is the stop flag, you can see OnTimer function of this view
		if(strTime.Find(_T("s")) == -1)
		{
			strTime += _T("s");
		}
		pListCtrl->SetItemText( nItem, TIME_INDEX, strTime);
	}

    if( bSuc )
    {
        EndProg( nPort );
        pListCtrl->SetItemText( nItem, PROG_INDEX,STRING_PASS);
    }
    else
    {
        EndProg( nPort );
        //pListCtrl->SetItemText( nItem,PROG_INDEX,STRING_FAILED);
		CString strErrText;
		if(nFlag != 2)
		{
			strErrText = STRING_FAILED;
			if( NULL != lpszErrMsg && lpszErrMsg[0] != '\0' )
			{
				strErrText += _T(": ");
				strErrText += lpszErrMsg;                    
			}
		}
		else
			strErrText = STRING_UNPLUGGED;

        pListCtrl->SetItemText( nItem, PROG_INDEX, strErrText );
    }	

    m_StepMap.SetAt( nPort, DL_NO_FILE );

	m_ItemLatestRltMap.SetAt( nItem, bSuc );  

    return TRUE;
}

BOOL CDLoaderView::SetStep( int nPort  )
{
    int nFileStep;
    BOOL bFound = m_StepMap.Lookup( nPort, nFileStep );
    if( !bFound )
    {
        // This value does not exist now,
        // add it to the map
        nFileStep = DL_FIRST_FILE;
    }
    else
    {
        // This value has been found,
        // increce it
        ++nFileStep;
    }
    
    m_StepMap.SetAt( nPort, nFileStep );
    
    int nItem = IsValidPort( nPort );
    if( nItem == -1 )
        return FALSE;
    
    CListCtrl* pListCtrl = &GetListCtrl();
    
    CString strText;
    if( nFileStep > m_StepDescription.GetSize() )
    {
        strText = _T("");
    }
    else
    {
        strText = m_StepDescription[ nFileStep - 1 ];
    }
    pListCtrl->SetItemText( nItem,STEP_INDEX,strText);
    return TRUE;    
}

LRESULT CDLoaderView::OnBMCheckBaud( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_CHK_BAUD, FALSE, 0 , 0 );
}

LRESULT CDLoaderView::OnBMConnect( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_CONNECT, FALSE, 0 , 0 );
}

LRESULT CDLoaderView::OnBMEraseFlash( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_ERASE_FLASH, FALSE, 0 , 0 );
}

LRESULT CDLoaderView::OnBMDownLoad( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    return SetStatus( wParam, DL_DL_STAGE,TRUE, 0, lParam  );
    return 0;
}

LRESULT CDLoaderView::OnBMDLoadProcess( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    return SetProgPos( wParam, lParam );
}

LRESULT CDLoaderView::OnBMReadFlash( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    return SetStatus( wParam, DL_READ_STAGE,TRUE, 0, lParam  );
}

LRESULT CDLoaderView::OnBMReset( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_RESET_STAGE,FALSE, 0, 0  );
}

LRESULT CDLoaderView::OnBMReadChipType( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_READCHIPTYPE_STAGE ,FALSE, 0, 0  );
}

LRESULT CDLoaderView::OnBMReadNVItem( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_READNVITEM_STAGE,FALSE, 0, 0  );
}

LRESULT CDLoaderView::OnBMChangeBuad( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );
    return SetStatus( wParam, DL_CHANGEBUAD_STAGE,FALSE, 0, 0  );
}

LRESULT CDLoaderView::OnBMReadFlashProcess( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    return SetProgPos( wParam, lParam );
}

LRESULT CDLoaderView::OnBMBegin( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );    
    return SetStatus( wParam, DL_NONE_STAGE, FALSE, 0 ,0 );
}


LRESULT CDLoaderView::OnBMFileBegin( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
    UNUSED_ALWAYS( lParam );    
    return SetStep( wParam );
}

LRESULT CDLoaderView::OnBMEnd( WPARAM wParam /* = 0 */, LPARAM lParam /* = 0  */ )
{
   return SetResult( wParam, NULL, (LPCTSTR)lParam );
}

#if defined(_DOWNLOAD_FOR_PRODUCTION ) 
LRESULT CDLoaderView::OnAcquireBarcode(WPARAM wParam,LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);

	m_arrReadyPorts.Add( wParam );

	if(m_bSNDlgShow) 
    {
        // There is already a port waiting for barcode,
        return 0;
    }
    
    while( 1 )
    {
        int nCount = m_arrReadyPorts.GetSize();
        if(0 == nCount)
        {
            // No port is ready
            break;
        }
        
        m_bSNDlgShow = TRUE;
        
        DWORD dwPort = m_arrReadyPorts[0];
        m_arrReadyPorts.RemoveAt( 0 );

		int nIndex = -1;
		m_PortMap.Lookup(dwPort,nIndex);
        
        CBarcodeDlg dlg(dwPort);
		m_pCurBarcodeDlg = &dlg;
		//dlg.SetSNInputMethod(TRUE);
		UINT nRet;
		LPCSTR pSN =NULL;

		if(nIndex != -1)
		{
			GetListCtrl().SetItemText( nIndex,STEP_INDEX,_T(""));
		}
		SetStatus(dwPort, DL_NONE_STAGE, FALSE, 0, 0);		   
		nRet = dlg.DoModal();
		USES_CONVERSION;
		pSN= T2CA(dlg.m_strBarcode);
     
        if( IDOK == nRet )
        {	
            int nSize = PRODUCTION_INFO_SIZE;
			ASSERT(NULL != pSN);
			//PORT_DATA * pPortData = reinterpret_cast<PORT_DATA*>(lParam);
			// not use lParam
			// if while loop run twice the lParam is not changed
			// so must re-get the port information 
			CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
			PORT_DATA* pPortData = pFrame->GetPortDataByPort(dwPort); 
			SAFE_DELETE(pPortData->lpPhaseCheck);
			pPortData->lpPhaseCheck = new BYTE[nSize];
			memset(pPortData->lpPhaseCheck,0xFF,nSize);
			CPhaseCheckBuild ccb;
			BOOL bOK = ccb.Cnst8KBuffer(pSN, pPortData->lpPhaseCheck, nSize);
			if(bOK)
			{				
				m_StepMap.SetAt( dwPort,DL_NO_FILE  );
				SetStatus(dwPort, DL_NONE_STAGE, FALSE, 0, 0);
				SetEvent(pPortData->hSNEvent); 			
			}
			else
			{
				CString strError = _T("Construct phasecheck information fail.");
				OnBMEnd((WPARAM)dwPort,(LPARAM)(LPCTSTR)strError);
				//set this flag,let the port wait
				nRet =  IDIGNORE;
			}
        }
        if ( IDIGNORE == nRet)
        {
			if(nIndex != -1)
			{
				m_ButtonArr[nIndex]->ShowWindow(SW_SHOW);
				m_ButtonArr[nIndex]->EnableWindow(TRUE);
				m_StepMap.SetAt( dwPort,DL_NO_FILE  );			
				SetStatus(dwPort, DL_PAUSED, FALSE, 0, 0);			
				GetListCtrl().SetItemText( nIndex,STEP_INDEX,_T(""));
			}
        }

		m_pCurBarcodeDlg = NULL;        
        m_bSNDlgShow = FALSE;

		//this is for manual download for DOWNLOAD and SPUPGRADE
		//to judge if the user select the IGNORE button.
		if( g_theApp.m_bManual && IDIGNORE == nRet )
		{
			return S_FALSE;
		}
    }
	return S_OK;
}

#endif 

#if defined(_DOWNLOAD_FOR_PRODUCTION ) || defined (_SPUPGRADE)
void CDLoaderView::ClearPortInfo(int nPort)
{
#if defined (_DOWNLOAD_FOR_PRODUCTION )
	//Close the SN Dialog
	if(NULL != m_pCurBarcodeDlg)
	{
		if( m_pCurBarcodeDlg->GetPortNum() == nPort )
		{
			m_pCurBarcodeDlg->Close();
		}
	}
	
	//Remove the port from the SN dlg array;
	for(int i=0; i< m_arrReadyPorts.GetSize(); i++)
	{
		if( m_arrReadyPorts[i] == (DWORD)nPort)
		{
			m_arrReadyPorts.RemoveAt(i);
			break;
		}
	}
#endif

	int nIndex = -1;
	m_PortMap.Lookup(nPort, nIndex);
	if(nIndex >=0 && m_ButtonArr.GetSize()> nIndex)
	{
		m_ButtonArr[nIndex]->ShowWindow(SW_HIDE);
		m_ButtonArr[nIndex]->EnableWindow(FALSE);
	}
}

void CDLoaderView::ResizeButton()
{
	CListCtrl* pList = &GetListCtrl();
	// if g_theApp.m_bManual is false for _SPUPGRADE
	// m_ButtonArr is empty, so the code sector is not bad
    for(int i=0; i<m_ButtonArr.GetSize();i++)
    {
        CRect rc;
        pList->GetSubItemRect(i, BUTTON_POS, LVIR_BOUNDS, rc);
        rc.right = rc.left + START_ICON_SIZE; 
		rc.top     = rc.top + (rc.Height() - START_ICON_SIZE)/2;
		rc.bottom  = rc.top + START_ICON_SIZE;
		
        m_ButtonArr[i]->MoveWindow(rc);
        m_ButtonArr[i]->Invalidate();
    }
}

void CDLoaderView::OnBtnStart(UINT nID)
{
	int nIndex = nID - IDC_BTN_START1;
	int nPort = -1;
    
    if(m_ButtonArr.GetSize() <= nIndex)
    {
        return;
    }

    POSITION pos = m_PortMap.GetStartPosition();

    while( NULL != pos )
    {
        int nMapIndex;   		
        m_PortMap.GetNextAssoc(pos, nPort, nMapIndex);
        if( nMapIndex == nIndex )
        {           
			break;
        }
    }
	m_ButtonArr[nIndex]->ShowWindow(SW_HIDE);
	m_ButtonArr[nIndex]->EnableWindow(FALSE);
    
   CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();   
#if defined(_DOWNLOAD_FOR_PRODUCTION )
   PORT_DATA* pPortData = pFrame->GetPortDataByPort(nPort); 
   HRESULT hr = OnAcquireBarcode(nPort, (LPARAM)pPortData);
   if(hr==S_FALSE)
   {
	   return;
   }
#endif 

   if(g_theApp.m_bManual)
   {
	   if(!pFrame->StartOnePortWork(nPort,FALSE))
	   {
			m_ButtonArr[nIndex]->ShowWindow(SW_SHOW);
			m_ButtonArr[nIndex]->EnableWindow(TRUE);
	   }
   }


}

void CDLoaderView::OnBeginTrack(NMHDR* pNMHDR, LRESULT* pResult)
{	
	UNREFERENCED_PARAMETER(pNMHDR);

    for(int i=0; i<m_ButtonArr.GetSize();i++)
    {
        m_ButtonArr[i]->ShowWindow(SW_HIDE);   
    }	
	TRACE(_T("On Begin Track!\n"));
	*pResult = 0;	
}
#endif


void CDLoaderView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if(DL_TIMER == nIDEvent)
	{
		CListCtrl &lc = GetListCtrl();
		for(int i = 0; i< lc.GetItemCount(); i++)
		{
			CString strText = lc.GetItemText(i,TIME_INDEX);
			if(!strText.IsEmpty() && strText.Find(_T("s"))==-1)
			{
				strText.Format(_T("%d"),_ttoi(strText)+1);
				lc.SetItemText(i,TIME_INDEX,strText);
			}
		}		
		return;
	}
	CListView::OnTimer(nIDEvent);
}

void CDLoaderView::StartDLTimer()
{
	::SetTimer(this->m_hWnd,DL_TIMER,1000,NULL);
}
void CDLoaderView::StopDLTimer()
{
	::KillTimer(this->m_hWnd,DL_TIMER);
}