// Copyright (c) 2021 Giorgos Vougioukas
//
// The license can be found in the LICENSE file.

#include "RSI/stats_wnd.h"

#define RSI_STATS_ID 341
#define RSI_STATS_MS 1000

static LOGFONT lf =
{
#if defined(_WIN32)
  20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
  OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
  "Arial"
#else
  17, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
  OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
  "Arial"
#endif
};

void RSI_StatsWnd::OnInitDialog()
{
  m_resize.init(m_hwnd);
  m_resize.init_item(IDC_RECT, 0.0f, 0.0f, 1.0f, 1.0f);

  int x = GetPrivateProfileInt(RSI_NAME, "stats_wnd_x", 0, g_inipath.Get());
  int y = GetPrivateProfileInt(RSI_NAME, "stats_wnd_y", 50, g_inipath.Get());
  int w = GetPrivateProfileInt(RSI_NAME, "stats_wnd_w", 282, g_inipath.Get());
  int h = GetPrivateProfileInt(RSI_NAME, "stats_wnd_h", 136, g_inipath.Get());
  SetWindowPos(m_hwnd, NULL, x, y, w, h, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

  RECT r;
  GetClientRect(m_hwnd, &r);

  m_font = new LICE_CachedFont();
  m_font->SetFromHFont(CreateFontIndirect(&lf), LICE_FONT_FLAG_OWNS_HFONT);

  m_dis.SetFont(m_font);
  m_dis.SetPosition(&r);
  m_dis.SetVisible(true);
  m_dis.SetAlign(0);
  m_font->SetBkMode(TRANSPARENT);
  m_dis.SetColors(LICE_RGBA((m_txtc >> 16) & 0xFF,
    (m_txtc >> 8) & 0xFF, m_txtc & 0xFF, 255));

  SetTimer(m_hwnd, RSI_STATS_ID, RSI_STATS_MS, NULL);
}

void RSI_StatsWnd::OnDestroy()
{
  KillTimer(m_hwnd, RSI_STATS_ID);

  RECT r;
  GetWindowRect(m_hwnd, &r);

  WDL_FastString rleft, rtop, rwidth, rheight;
  rleft.SetFormatted(32, "%d", r.left);
  rtop.SetFormatted(32, "%d", r.top);
  rwidth.SetFormatted(32, "%d", r.right - r.left);
  rheight.SetFormatted(32, "%d", r.bottom - r.top);

  WritePrivateProfileString(RSI_NAME,"stats_wnd_x", rleft.Get(), g_inipath.Get());
  WritePrivateProfileString(RSI_NAME,"stats_wnd_y", rtop.Get(), g_inipath.Get());
  WritePrivateProfileString(RSI_NAME,"stats_wnd_w", rwidth.Get(), g_inipath.Get());
  WritePrivateProfileString(RSI_NAME,"stats_wnd_h", rheight.Get(), g_inipath.Get());
}

void RSI_StatsWnd::OnPaint()
{
  int xo, yo;
  m_painter.PaintBegin(m_hwnd, RGB(0, 0, 0));
  m_bm = m_painter.GetBuffer(&xo, &yo);
  LICE_Clear(m_bm, LICE_RGBA((m_bgc >> 16) & 0xFF,
    (m_bgc >> 8) & 0xFF, m_bgc & 0xFF, 255));

  m_strbuf.SetFormatted(2048, "CPU: %02.0f%%, RAM: %" WDL_PRI_UINT64 
    " MB, System RAM: %" WDL_PRI_UINT64 " MB" " / %" WDL_PRI_UINT64 " MB",
    m_stats.GetProcessCPUUsed(),
    m_stats.GetProcessMemUsed() / WDL_UINT64_CONST(1024) / WDL_UINT64_CONST(1024),
    m_stats.GetPhysicalMemUsed() / WDL_UINT64_CONST(1024) / WDL_UINT64_CONST(1024),
    m_stats.GetTotalPhysicalMem() / WDL_UINT64_CONST(1024) / WDL_UINT64_CONST(1024));

  m_dis.SetText(m_strbuf.Get());

  m_painter.PaintVirtWnd(&m_dis);
  m_painter.PaintEnd();
}

void RSI_StatsWnd::OnLButtonUp()
{}

void RSI_StatsWnd::OnSize()
{
  if (m_wparam != SIZE_MINIMIZED)
  {
    m_resize.onResize();
  }
}

void RSI_StatsWnd::OnTimer()
{
  if (m_wparam == RSI_STATS_ID)
  {
    InvalidateRect(m_hwnd, NULL, FALSE);
  }
}

void RSI_StatsWnd::OnCommand()
{
  switch(LOWORD(m_wparam))
  {
  case IDCANCEL:
    {
      if (g_statswnd) { delete g_statswnd; g_statswnd = NULL; }
    }
    break;
  }
}

WDL_DLGRET RSI_StatsWnd::StatsWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
  RSI_StatsWnd *self = (RSI_StatsWnd *)GetWindowLongPtr(hwnd, GWLP_USERDATA);

  if (!self && msg == WM_INITDIALOG)
  {
    SetWindowLongPtr(hwnd, GWLP_USERDATA, lparam);
    self = (RSI_StatsWnd *)lparam;
    self->m_hwnd = hwnd;
  }

  if (self)
  {
    return self->StatsWndLoop(msg, wparam, lparam);
  }
  else
  {
    return 0;
  }
}

WDL_DLGRET RSI_StatsWnd::StatsWndLoop(UINT msg, WPARAM wparam, LPARAM lparam)
{
  m_msg = msg;
  m_wparam = wparam;
  m_lparam = lparam;

  switch (msg)
  {
    case WM_INITDIALOG: OnInitDialog(); break;
    case WM_DESTROY: OnDestroy(); break;
    case WM_PAINT: OnPaint(); break;
    case WM_LBUTTONUP: OnLButtonUp(); break;
    case WM_SIZE: OnSize(); break;
    case WM_TIMER: OnTimer(); break;
    case WM_COMMAND: OnCommand(); break;
  }

  return 0;
}
