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

#include "mnemosyne/about_wnd.h"

// 3:1 (ultra wide)
#define RSM_ABOUT_WIDTH 630
#define RSM_ABOUT_HEIGHT 210

#define RSM_ABOUT_UPDATE_ID 330
#define RSM_ABOUT_UPDATE_MS 41

static const char *master_project =
  "\xce\x9c\xce\xbd\xce\xb7\xce\xbc\xce\xbf\xcf\x83\xcf\x8d\xce\xbd\xce\xb7";

static const char *different =
  "\xce\x93\xce\xb9\xcf\x8e\xcf\x81\xce\xb3\xce\xbf"
  "\xcf\x82\x20\xce\x92\xce\xbf\xcf\x85\xce\xb3\xce"
  "\xb9\xce\xbf\xcf\x8d\xce\xba\xce\xb1\xcf\x82";

static const char *rsm_credits[] =
{
  MNEMOSYNE_NAME_MARKETING,
  "Version: " MNEMOSYNE_NAKED_VERSION " (" MNEMOSYNE_ARCH ")",
  "Build timestamp: " MNEMOSYNE_TIMESTAMP,
  "Git commit: " MNEMOSYNE_GIT_SHA,
  "",
  "Developed by:",
  "Giorgos Vougioukas",
  "",
  "WDL:",
  "Cockos Incorporated",
  //"(when you care enough to use the very best)",
  //"",
  //"Cool Scrollbar:",
  //"J Brown",
  "",
  "libpng:",
  "Glenn Randers-Pehrson",
  "Simon-Pierre Cadieux",
  "Eric S. Raymond",
  "Mans Rullgard",
  "Cosmin Truta",
  "Gilles Vollant",
  "James Yu",
  "Tom Lane",
  "Willem van Schaik",
  "John Bowler",
  "Kevin Bracey",
  "Sam Bushell",
  "Magnus Holmgren",
  "Greg Roelofs",
  "Tom Tanner",
  "Andreas Dilger",
  "Dave Martindale",
  "Guy Eric Schalnat",
  "Paul Schmidt",
  "Tim Wegner",
  "",
  "jpeglib:",
  "Tom Lane",
  "Philip Gladstone",
  "Jim Boucher",
  "Lee Crocker",
  "Julian Minguillon",
  "Luis Ortiz",
  "George Phillips",
  "Davide Rossi",
  "Guido Vollbeding",
  "Ge' Weijers",
  "Independent JPEG Group",
  "",
  "giflib:",
  "Gershon Elber",
  "Toshio Kuratomi",
  "Lennie Araki",
  "Michael Brown",
  "Daniel Eisenbud",
  "Marc Ewing",
  "marek",
  "Peter Mehlitz",
  "Dick Porter",
  "Eric S. Raymond",
  "Georg Schwarz",
  "",
  "zlib:",
  "Jean-loup Gailly",
  "Mark Adler",
  "",
  "Windows installer:",
  "Nullsoft Scriptable Install System (NSIS)",
  "Compressor | ZLIB",
  "",
  "Windows portable:",
  "Archive format | ZIP",
  //"",
  //"Linux tarball:",
  //"gzip",
  "",
  "Giorgos wishes to thank the following",
  "for their assistance:",
  "Asimina",
  "Manolis",
  "Justin Frankel",
  "and",
  "Snoopy",
  "",
  "Contact | email:",
  "support@grafmin.gr",
  "",
  MNEMOSYNE_NAME_MARKETING,
  MNEMOSYNE_COPYRIGHT
};

static LOGFONT lf =
{
  16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
  OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
  "Arial"
};

int RSM_AboutWnd::Run()
{
  RECT r, fr;
  int half_screen, half_text;

  HWND sta = GetDlgItem(m_hwnd, IDC_STATIC_ABOUT);

  GetWindowRect(sta, &r);
  ScreenToClient(m_hwnd, (LPPOINT)&r);
  ScreenToClient(m_hwnd, ((LPPOINT)&r)+1);

  GetWindowRect(sta, &fr);
  ScreenToClient(m_hwnd, (LPPOINT)&fr);
  ScreenToClient(m_hwnd, ((LPPOINT)&fr)+1);

  LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));

  m_font->SetBkColor(LICE_RGBA(0, 0, 0, 255));
  m_font->SetTextColor(LICE_RGBA(192, 192, 192, m_font_alpha));
  m_font->SetFromHFont(CreateFontIndirect(&lf),LICE_FONT_FLAG_OWNS_HFONT);

  half_screen = (r.right - r.left) / 2;

  fr.top = RSM_ABOUT_HEIGHT - 32;
  fr.bottom = fr.top + RSM_ABOUT_HEIGHT;

  fr.top -= m_scroll_offset_y;
  fr.bottom -= m_scroll_offset_y;

  for (int i = 0; i < sizeof(rsm_credits) /
    sizeof(rsm_credits[0]); i++)
  {
    if (m_disjunction.Find(i) < 0)
    {
      if (i > m_disjunction.Get()[m_disjunction.GetSize() - 1])
      {
        fr.top += 32;
        fr.bottom += 32;
      }
      else
      {
        fr.top += 16;
        fr.bottom += 16;
      }

      if (fr.top >= -16 && fr.top <= RSM_ABOUT_HEIGHT)
      {
        if (!strcmp(rsm_credits[i],
          "\x47\x69\x6f\x72\x67\x6f\x73\x20\x56\x6f\x75\x67\x69\x6f\x75\x6b\x61\x73")
          && (GetAsyncKeyState(VK_CONTROL) & 0x8000))
        {
          m_font->DrawText(m_bm, different,
            (int)strlen(different),
            &fr, DT_CALCRECT| DT_NOPREFIX | DT_SINGLELINE);
          half_text = (fr.right - fr.left) / 2;
          fr.left = 0;
          fr.left += half_screen - half_text;
          fr.right += half_screen - half_text;
          m_font->DrawText(m_bm, different,
            (int)strlen(different), &fr,
            LICE_DT_NEEDALPHA | LICE_DT_USEFGALPHA |
            DT_NOPREFIX | DT_SINGLELINE);
        }
        else if (!strcmp(rsm_credits[i], "\x4d\x6e\x65\x6d\x6f\x73\x79\x6e\x65")
          && (GetAsyncKeyState(VK_CONTROL) & 0x8000))
        {
          m_font->DrawText(m_bm, master_project,
            (int)strlen(master_project),
            &fr, DT_CALCRECT| DT_NOPREFIX | DT_SINGLELINE);
          half_text = (fr.right - fr.left) / 2;
          fr.left = 0;
          fr.left += half_screen - half_text;
          fr.right += half_screen - half_text;
          m_font->DrawText(m_bm, master_project,
            (int)strlen(master_project), &fr,
            LICE_DT_NEEDALPHA | LICE_DT_USEFGALPHA |
            DT_NOPREFIX | DT_SINGLELINE);
        }
        else
        {
          m_font->DrawText(m_bm, rsm_credits[i],
            (int)strlen(rsm_credits[i]),
            &fr, DT_CALCRECT| DT_NOPREFIX | DT_SINGLELINE);
          half_text = (fr.right - fr.left) / 2;
          fr.left = 0;
          fr.left += half_screen - half_text;
          fr.right += half_screen - half_text;
          m_font->DrawText(m_bm, rsm_credits[i],
            (int)strlen(rsm_credits[i]), &fr,
            LICE_DT_NEEDALPHA | LICE_DT_USEFGALPHA |
            DT_NOPREFIX | DT_SINGLELINE);
        }
      }
    }
    else
    {
      if (i == m_disjunction.Get()[m_disjunction.GetSize() - 1])
      {
        fr.top += RSM_ABOUT_HEIGHT - 60;
        fr.bottom += RSM_ABOUT_HEIGHT - 60;
      }
      else
      {
        fr.top += 32;
        fr.bottom += 32;
      }
    }
  }

  if (m_calc)
  {
    m_credits_height = fr.bottom - (RSM_ABOUT_HEIGHT / 2);
    m_calc = false;
  }

  m_x = r.left;
  m_y = r.top;
  m_w = r.right - r.left;
  m_h = r.bottom - r.top;

  LICE_Blit(m_bm, m_bm, m_x, m_y, m_w, m_h, m_bm->getWidth(),
    m_bm->getHeight(), 1.0f, LICE_BLIT_MODE_COPY);

  if (m_scroll_offset_y > m_credits_height)
  {
    if (m_font_alpha > 220) m_font_alpha -= 1;
    else m_font_alpha -= 20;

    if (m_font_alpha <= 0)
    {
      m_font_alpha = 255;
      m_scroll_offset_y = -32;
    }
  }
  else
  {
    m_scroll_offset_y++;
  }

  return 1;
}

void RSM_AboutWnd::DoPaint(HDC dc)
{
  BitBlt(dc, m_x, m_y, m_w, m_h, m_bm->getDC(), 0, 0, SRCCOPY);
}

void RSM_AboutWnd::OnInitDialog()
{
  HWND s = GetDlgItem(m_hwnd, IDC_STATIC_ABOUT);

  m_resize.init(m_hwnd);
  m_resize.init_itemhwnd(s);

  int x = GetPrivateProfileInt(MNEMOSYNE_NAME, "about_wnd_x", 0, g_inipath.Get());
  int y = GetPrivateProfileInt(MNEMOSYNE_NAME, "about_wnd_y", 50, g_inipath.Get());
  int w = RSM_ABOUT_WIDTH;
  int h = RSM_ABOUT_HEIGHT;
  SetWindowPos(m_hwnd, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE);

  for (int i = 0; i < sizeof(rsm_credits) /
    sizeof(rsm_credits[0]); i++)
  {
    if (!strcmp(rsm_credits[i], "")) m_disjunction.Add(&i, 1);
  }

  m_bm = new LICE_SysBitmap(w, h);
  m_font = new LICE_CachedFont();

  m_x = x;
  m_y = y;
  m_w = w;
  m_h = h;
  LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
  SetTimer(m_hwnd, RSM_ABOUT_UPDATE_ID, RSM_ABOUT_UPDATE_MS, NULL);
}

void RSM_AboutWnd::OnPaint()
{
#if _WIN32
  PAINTSTRUCT ps;
  HWND sta = GetDlgItem(m_hwnd, IDC_STATIC_ABOUT);
  HDC dc = BeginPaint(sta, &ps);
  DoPaint(dc);
  EndPaint(sta, &ps);
#endif
}

void RSM_AboutWnd::OnTimer()
{
  if (m_wparam == RSM_ABOUT_UPDATE_ID)
  {
    Run();
#if defined(_WIN32)
    InvalidateRect(m_hwnd, NULL, FALSE);
#else
    {
      HWND h = GetDlgItem(m_hwnd, IDC_STATIC_ABOUT);
      HDC dc = GetWindowDC(h);
      DoPaint(dc);
      ReleaseDC(h,dc);
      //SWELL_FlushWindow(h); // for macos
    }
#endif
  }
}

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

void RSM_AboutWnd::OnDestroy()
{
  KillTimer(m_hwnd, RSM_ABOUT_UPDATE_ID);

  RECT r;
  GetWindowRect(m_hwnd, &r);

  WDL_FastString rleft, rtop;
  rleft.SetFormatted(32, "%d", r.left);
  rtop.SetFormatted(32, "%d", r.top);

  WritePrivateProfileString(MNEMOSYNE_NAME,"about_wnd_x", rleft.Get(), g_inipath.Get());
  WritePrivateProfileString(MNEMOSYNE_NAME,"about_wnd_y", rtop.Get(), g_inipath.Get());
}

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

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

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

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

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

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

  return 0;
}
