// goview.cpp : implementation file
//

#include "stdafx.h"
#include "winaping.h"
#include "constdef.h"
#include "goview.h"

#include "winapdoc.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGoView

IMPLEMENT_DYNCREATE(CGoView, CFormView)

CGoView::CGoView()
        : CFormView(CGoView::IDD)
{
        //{{AFX_DATA_INIT(CGoView)
        m_partner = _T("");
        m_rate2 = _T("");
        m_rate1 = _T("");
        m_curriter = _T("");
        m_alloctime = 0;
        m_avgtime = 0;
        m_confirmtime = 0;
        m_maxtime = 0;
        m_mintime = 0;
        m_totbyte = _T("");
        m_tottime = _T("");
        //}}AFX_DATA_INIT
}

CGoView::~CGoView()
{
}

void CGoView::DoDataExchange(CDataExchange* pDX)
{
        CFormView::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CGoView)
        DDX_Control(pDX, IDC_MSGAREA, m_msgArea);
        DDX_Text(pDX, IDC_PARTNER, m_partner);
        DDX_Text(pDX, IDC_RATE2, m_rate2);
        DDX_Text(pDX, IDC_RATE1, m_rate1);
        DDX_Text(pDX, IDC_CURRITER, m_curriter);
        DDX_Text(pDX, IDC_ALLOCTIME, m_alloctime);
        DDX_Text(pDX, IDC_AVGTIME, m_avgtime);
        DDX_Text(pDX, IDC_CONFIRMTIME, m_confirmtime);
        DDX_Text(pDX, IDC_MAXTIME, m_maxtime);
        DDX_Text(pDX, IDC_MINTIME, m_mintime);
        DDX_Text(pDX, IDC_TOTBYTE, m_totbyte);
        DDX_Text(pDX, IDC_TOTTIME, m_tottime);
        //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CGoView, CFormView)
        //{{AFX_MSG_MAP(CGoView)
                // NOTE - the ClassWizard will add and remove mapping macros here.
        ON_MESSAGE(WM_CPICCALL_ERR, OnCpiccallErr)    // user msg
        ON_MESSAGE(WM_REFRESH,      OnRefresh)        // user msg
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()



/////////////////////////////////////////////////////////////////////////////
// CGoView diagnostics

#ifdef _DEBUG
void CGoView::AssertValid() const
{
//      CFormView::AssertValid();          // ?????? FAILED HERE ???????????
}

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

/////////////////////////////////////////////////////////////////////////////
// CGoView message handlers

void CGoView::OnInitialUpdate()
{
        // measure the font in the dialog
        CClientDC       dc(this);
        dc.GetTextMetrics(&tm);

        CFormView::OnInitialUpdate();
}

//-----------------------------------------
// This is to add a string to messages area
void CGoView::RefreshMsg(CString str)
{
//  ((CListBox*) GetDlgItem(IDC_MSGAREA))->AddString(str);    ypc
  CSize strExtent = m_msgArea.GetDC()->GetTextExtent(str);  //ypc
  if (strExtent.cx > m_msgArea.GetHorizontalExtent())       //ypc
          m_msgArea.SetHorizontalExtent(strExtent.cx);      //ypc
  m_msgArea.AddString(str);                                 //ypc
}

//-----------------------------------------------
// This is to reset the screen and local counters
void CGoView::Refresh0()
{
  CWinapingDoc* pDoc  = (CWinapingDoc*) GetDocument();
  CListCtrl*    pList = (CListCtrl*) GetDlgItem(IDC_LISTVIEW);
  verify_failed_msg_issued = FALSE;
  total_byte_per_iter = (pDoc->pingInfo.packetSize) *
                        (pDoc->pingInfo.consecutivePackets);
  if (pDoc->pingInfo.echo) total_byte_per_iter *= 2;
  grand_total_byte = 0;
  grand_total_time = 0;

  //---------------------------------------------
  // Clear local m_... variables for upper screen
        m_alloctime   = 0;
        m_avgtime     = 0;
        m_confirmtime = 0;
        m_curriter    = _T("");
        m_maxtime     = 0;
        m_mintime     = 0;
        m_partner     = _T("");
        m_rate2       = _T("");
        m_rate1       = _T("");
        m_totbyte     = _T("");
        m_tottime     = _T("");

  //-------------------------------------------------------------
  // Delete all items & cloumns in list view then rebuild columns
  pList->DeleteAllItems();
  BOOL rc;
  do { rc = pList->DeleteColumn(0); }
  while (rc != 0);

  int colnum = 0;
  LV_COLUMN  lvc;
  lvc.mask = LVCF_FMT|LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH;
  lvc.iSubItem = 0;

  lvc.pszText    = "Iteration";
  lvc.fmt        = LVCFMT_CENTER;     // seems not working
  lvc.cx         = (lstrlen(lvc.pszText)-3)*tm.tmAveCharWidth;
  lvc.cchTextMax = lstrlen(lvc.pszText);
  rc= pList->InsertColumn(colnum++, &lvc);

  lvc.pszText    = "Duration";
  lvc.fmt        = LVCFMT_RIGHT;
  lvc.cx         = (lstrlen(lvc.pszText)-1)*tm.tmAveCharWidth;
  lvc.cchTextMax = lstrlen(lvc.pszText);
  rc= pList->InsertColumn(colnum++, &lvc);

  if (pDoc->pingInfo.echo) lvc.pszText = "Data S/R";
  else              lvc.pszText = "Data Sent";
  lvc.fmt        = LVCFMT_CENTER;
  lvc.cx         = (lstrlen(lvc.pszText)+1)*tm.tmAveCharWidth;
  lvc.cchTextMax = lstrlen(lvc.pszText);
  rc= pList->InsertColumn(colnum++, &lvc);

  lvc.pszText = "Rate (KB/s)";
  lvc.fmt  = LVCFMT_RIGHT;
  lvc.cx = lstrlen(lvc.pszText)*tm.tmAveCharWidth;
  lvc.cchTextMax = lstrlen(lvc.pszText);
  rc= pList->InsertColumn(colnum++, &lvc);

  lvc.pszText = "Rate (Mb/s)";
  lvc.fmt  = LVCFMT_RIGHT;
  lvc.cx = lstrlen(lvc.pszText)*tm.tmAveCharWidth;
  lvc.cchTextMax = lstrlen(lvc.pszText);
  rc= pList->InsertColumn(colnum++, &lvc);

  if (pDoc->pingInfo.verify) {
    lvc.pszText    = "Verify OK";
    lvc.cx         = (lstrlen(lvc.pszText)-2)*tm.tmAveCharWidth;
    lvc.fmt        = LVCFMT_LEFT;
    lvc.cchTextMax = lstrlen(lvc.pszText);
    rc= pList->InsertColumn(colnum++, &lvc);
    }

  //-----------------------
  // Clear the message area
  // ((CListBox*) GetDlgItem(IDC_MSGAREA))->ResetContent();   ypc
  m_msgArea.ResetContent();                                 //ypc
  m_msgArea.SetHorizontalExtent(0);                         //ypc

  UpdateData(FALSE);     // local m_ variables to dlg window
}

LONG CGoView::OnRefresh(UINT currnum, LONG currtime) {
  CWinapingDoc* pDoc = (CWinapingDoc*) GetDocument();
  BOOL verifyok = TRUE;

  if (currtime < 0) {
    verifyok = FALSE;
    currtime = -currtime;
    }
  if (currnum == 0) {               // no iteration started yet
    m_alloctime   = pDoc->alloctime;
    m_confirmtime = pDoc->confirmtime;
    m_partner     = pDoc->partner;
    }
  else {                                  // for each iteration done
    CListCtrl*    pList = (CListCtrl*) GetDlgItem(IDC_LISTVIEW);
    double rate;

    //-------------------------
    // Recalculate summary info
    m_curriter.Format(_T("%d/%d"), currnum, pDoc->pingInfo.iterations);
    grand_total_byte += total_byte_per_iter;
    m_totbyte.Format(_T("%.0f"), grand_total_byte);
    grand_total_time += currtime;
    m_tottime.Format(_T("%.0f"), grand_total_time);
    if (m_maxtime < (DWORD) currtime)
      m_maxtime = (DWORD) currtime;
    if ((currnum == 1) | (m_mintime > (DWORD) currtime))
      m_mintime = (DWORD) currtime;
    m_avgtime = (DWORD) (grand_total_time/currnum);
    if (grand_total_time == 0) rate = 0;
    else rate = (grand_total_byte*1000)/(grand_total_time*1024);
    m_rate1.Format(_T("%8.4f"), rate);
    m_rate2.Format(_T("%8.4f"), (rate*8)/1000);

    //------------------------------
    // Display the iteration details
    // A small flaw here, but OK
    // Since currnum always > 0, item 0 never get inserted
    int     i;
    CString str;
    LV_ITEM lvi;

    lvi.mask     = LVIF_TEXT | LVIF_PARAM;
    lvi.iItem    = 0;
    lvi.iSubItem = 0;
    str.Format(_T("%6d"), currnum);
    lvi.pszText      = (LPSTR) (LPCSTR) str;
    pList->InsertItem(&lvi);

    i = 1;
    str.Format(_T("%d"), currtime);
    pList->SetItemText(0, i++, (LPSTR) (LPCSTR) str);

    str.Format(_T("%d"), total_byte_per_iter);
    pList->SetItemText(0, i++, (LPSTR) (LPCSTR) str);

    if (currtime == 0) rate = 0;
    else rate = ((double)total_byte_per_iter*1000)/
                ((double)currtime*1024);
    str.Format(_T("%8.4f"), rate);
    pList->SetItemText(0, i++, (LPSTR) (LPCSTR) str);

    rate = (rate*8)/1000;
    str.Format(_T("%8.4f"), rate);
    pList->SetItemText(0, i++, (LPSTR) (LPCSTR) str);

    if (pDoc->pingInfo.verify) {
      if (!verifyok) str=_T("Failed");
      else                     str=_T("");
      pList->SetItemText(0, i++, (LPSTR) (LPCSTR) str);
      if (!verifyok && !verify_failed_msg_issued) {
        verify_failed_msg_issued = TRUE;
        str.Format(_T("First verification failed at iteration %d"), currnum);
        RefreshMsg(str);
        }
      }
    }

  UpdateData(FALSE);     // local m_ variables to dlg window

  return 0;
}

LONG CGoView::OnCpiccallErr(UINT, LONG) {
  CWinapingDoc* pDoc  = (CWinapingDoc*) GetDocument();
  CString str = pDoc->cmcall + _T(" failed with rc: ") + pDoc->cmrcmsg;
  RefreshMsg(str);
  return 0;
}
