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

#include "RSI/about_wnd.h"

// 3:1 (ultra wide)
#define RSI_ABOUT_WIDTH 630
#define RSI_ABOUT_HEIGHT 210

#define RSI_ABOUT_UPDATE_ID 330
#define RSI_ABOUT_UPDATE_MS 41

static const char *master_project =
  "\x52\x65\x64\x75\x63\x65\x64\x20\x53\x79\x73\x74\x65\x6d\x20\x49\x6b\x61\x72\x6f\x73";

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 *rsi_credits[] =
{
  RSI_NAME_MARKETING,
  "Version: " RSI_NAKED_VERSION " (" RSI_ARCH ")",
  "Build timestamp: " RSI_TIMESTAMP,
  "Git commit: " RSI_GIT_SHA,
  "",
  "Developed by:",
  "Giorgos Vougioukas",
  "",
  "WDL:",
  "Cockos Incorporated",
  //"(when you care enough to use the very best)",
  //"",
  //"Cool Scrollbar:",
  //"J Brown",
  "",
  "cJSON:",
  "Dave Gamble",
  "cJSON contributors",
  "",
  "libogg:",
  "Xiph.org Foundation",
  "Monty",
  "Greg Maxwell",
  "Ralph Giles",
  "Cristian Adam",
  "Tim Terriberry",
  "",
  "libFLAC:",
  "Xiph.org Foundation",
  "Josh Coalson",
  "Erik de Castro Lopo ",
  "Janne Hyv\xc3\xa4rinen",
  "Andrey Astafiev",
  "Miroslav Lichvar",
  "Brady Patterson",
  "Daisuke Shimamura",
  "Matt Zimmerman",
  "",
  "MP3 based on reaper_mp3dec:",
  "MP3 Library 0.2a",
  "Cockos Incorporated",
  "",
  "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",
  "",
  "PortAudio:",
  "Ross Bencina",
  "Phil Burk",
  "",
  "SQLite:",
  "D. Richard Hipp",
  "",
  "SoundTouch:",
  "Olli Parviainen",
  "",
  "Mersenne Twister:",
  "Makoto Matsumoto (MT inventor)",
  "Takuji Nishimura (MT inventor)",
  "Shawn Cokus",
  "Richard J. Wagner",
  "",
  "EBU R128 Gain processor:",
  "Chris Moeller",
  "Jan Kokem\xc3\xbcller",
  "",
  "<sys/queue.h>:",
  "The Regents of the University of California",
  "",
  "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",
  "",
  RSI_NAME_MARKETING,
  RSI_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 RSI_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 = RSI_ABOUT_HEIGHT - 32;
  fr.bottom = fr.top + RSI_ABOUT_HEIGHT;

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

  for (int i = 0; i < sizeof(rsi_credits) /
    sizeof(rsi_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 <= RSI_ABOUT_HEIGHT)
      {
        if (!strcmp(rsi_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(rsi_credits[i], "\x52\x53\x49")
          && (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, rsi_credits[i],
            (int)strlen(rsi_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, rsi_credits[i],
            (int)strlen(rsi_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 += RSI_ABOUT_HEIGHT - 60;
        fr.bottom += RSI_ABOUT_HEIGHT - 60;
      }
      else
      {
        fr.top += 32;
        fr.bottom += 32;
      }
    }
  }

  if (m_calc)
  {
    m_credits_height = fr.bottom - (RSI_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 RSI_AboutWnd::DoPaint(HDC dc)
{
  BitBlt(dc, m_x, m_y, m_w, m_h, m_bm->getDC(), 0, 0, SRCCOPY);
}

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

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

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

  for (int i = 0; i < sizeof(rsi_credits) /
    sizeof(rsi_credits[0]); i++)
  {
    if (!strcmp(rsi_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, RSI_ABOUT_UPDATE_ID, RSI_ABOUT_UPDATE_MS, NULL);
}

void RSI_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 RSI_AboutWnd::OnTimer()
{
  if (m_wparam == RSI_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 RSI_AboutWnd::OnSize()
{
  if (m_wparam != SIZE_MINIMIZED)
  {
    m_resize.onResize();
  }
}

void RSI_AboutWnd::OnDestroy()
{
  KillTimer(m_hwnd, RSI_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(RSI_NAME,"about_wnd_x", rleft.Get(), g_inipath.Get());
  WritePrivateProfileString(RSI_NAME,"about_wnd_y", rtop.Get(), g_inipath.Get());
}

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

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

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

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

WDL_DLGRET RSI_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;
}
