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

#include "euterpe/artwork_wnd.h"
#include "euterpe/app_info.h"
#include "euterpe/main_wnd.h"
#include "euterpe/plugin.h"

#define RSE_UPDATE_ARTWORK 400
#define RSE_UPDATE_ARTWORK_MS 50

RSE_ArtworkWnd::RSE_ArtworkWnd()
  : m_hwnd(NULL)
  , m_x(0)
  , m_y(0)
  , m_w(0)
  , m_h(0)
  , m_bm(NULL)
  , m_bmp(NULL)
{}

RSE_ArtworkWnd::~RSE_ArtworkWnd()
{}

HWND RSE_ArtworkWnd::Handle() const
{
  return m_hwnd;
}

void RSE_ArtworkWnd::Update()
{
  RECT r;
  GetWindowRect(GetDlgItem(m_hwnd, IDC_STATIC1), &r);
  ScreenToClient(m_hwnd, (LPPOINT)&r);
  ScreenToClient(m_hwnd, ((LPPOINT)&r)+1);

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

  if (m_bmp)
  {
    LICE_ScaledBlit(m_bm, m_bmp, m_x, m_y, m_w,
      m_h, 0.0f, 0.0f, (float)m_bmp->getWidth(),
      (float)m_bmp->getHeight(), 1.0f,
      LICE_BLIT_MODE_COPY | LICE_BLIT_FILTER_BILINEAR);
  }
  else
  {
    LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
  }
}

void RSE_ArtworkWnd::LoadArtwork(const char *filename)
{
  if (m_bmp) { delete m_bmp; m_bmp = NULL; }

  WDL_FastString img(filename);

  while (1)
  {
    img.remove_filepart(true);
    img.Append("front.jpg");
    m_bmp = LICE_LoadJPG(img.Get());
    if (m_bmp) break;

    img.remove_filepart(true);
    img.Append("cover.jpg");
    m_bmp = LICE_LoadJPG(img.Get());
    if (m_bmp) break;

    img.Set(filename);
    img.remove_fileext();
    img.Append(".jpg");
    m_bmp = LICE_LoadJPG(img.Get());
    if (m_bmp) break;

    img.remove_filepart(true);
    img.Append("folder.jpg");
    m_bmp = LICE_LoadJPG(img.Get());
    if (m_bmp) break;

    RSE_IFilePic *apic = CreateFilePic(filename);

    if (apic)
    {
      if (apic->GetPicSize() > 0)
      {
        m_bmp = LICE_LoadJPGFromMemory(apic->GetPic(), apic->GetPicSize());
      }

      delete apic;
    }
    break;
  }

  RECT r;
  GetWindowRect(GetDlgItem(m_hwnd, IDC_STATIC1), &r);
  ScreenToClient(m_hwnd, (LPPOINT)&r);
  ScreenToClient(m_hwnd, ((LPPOINT)&r)+1);

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

  if (m_bmp)
  {
    LICE_ScaledBlit(m_bm, m_bmp, m_x, m_y, m_w,
      m_h, 0.0f, 0.0f, (float)m_bmp->getWidth(),
      (float)m_bmp->getHeight(), 1.0f,
      LICE_BLIT_MODE_COPY | LICE_BLIT_FILTER_BILINEAR);
  }
  else
  {
    LICE_Clear(m_bm, LICE_RGBA(0, 0, 0, 255));
  }
}

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

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

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

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

WDL_DLGRET RSE_ArtworkWnd::ArtworkWndProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
  switch (msg)
  {
  case WM_INITDIALOG:
    {
      m_resize.init(m_hwnd);
      m_resize.init_item(IDC_STATIC1, 0.0f, 0.0f, 1.0f, 1.0f);

      int x, y, w, h;
      x = g_ini_file->read_int("artwork_wnd_x", 200, EUTERPE_NAME);
      y = g_ini_file->read_int("artwork_wnd_y", 200, EUTERPE_NAME);
      w = g_ini_file->read_int("artwork_wnd_w", 300, EUTERPE_NAME);
      h = g_ini_file->read_int("artwork_wnd_h", 300, EUTERPE_NAME);
      SetWindowPos(m_hwnd, NULL, x, y, w, h, SWP_NOZORDER|SWP_NOACTIVATE);

      m_context_menu = (HMENU)GetSubMenu(LoadMenu(g_inst, MAKEINTRESOURCE(IDR_MAIN_CONTEXT)), 1);

      switch (w)
      {
      case 300:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_CHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);
        break;
      case 400:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_CHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);
        break;
      case 600:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_CHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);
        break;
      case 800:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_CHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);
        break;
      case 1000:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_CHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);
        break;
      case 1100:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_CHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);
        break;
      case 1200:
        CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
        CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_CHECKED);
        break;
      }

      RECT r;
      GetWindowRect(GetDlgItem(m_hwnd, IDC_STATIC1), &r);
      ScreenToClient(m_hwnd, (LPPOINT)&r);
      ScreenToClient(m_hwnd, ((LPPOINT)&r)+1);

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

      m_bm = new LICE_SysBitmap(m_w, m_h);

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

      m_last_fn.Set(g_main_loop->GetCurrentFilename());
      LoadArtwork(m_last_fn.Get());

      SetTimer(m_hwnd, RSE_UPDATE_ARTWORK, RSE_UPDATE_ARTWORK_MS, NULL);
    }
    break;
  case WM_TIMER:
    {
      if (wparam == RSE_UPDATE_ARTWORK)
      {
        if (strcmp(g_main_loop->GetCurrentFilename(), "") == 0)
        {
          if (m_bmp)
          {
            delete m_bmp;
            m_bmp = NULL;
          }

          m_last_fn.Set("");

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

        if (strcmp(m_last_fn.Get(), g_main_loop->GetCurrentFilename()))
        {
          m_last_fn.Set(g_main_loop->GetCurrentFilename());
          LoadArtwork(m_last_fn.Get());
        }

#if defined(_WIN32)
        InvalidateRect(m_hwnd, NULL, FALSE);
#else
        {
          HWND h = GetDlgItem(m_hwnd, IDC_STATIC1);
          HDC dc = GetWindowDC(h);
          DoPaint(m_hwnd,dc);
          ReleaseDC(h,dc);
          //SWELL_FlushWindow(h); // for macos
        }
#endif
      }
    }
    break;
  case WM_ERASEBKGND:
    {
      return 1;
    }
    break;
  case WM_CONTEXTMENU:
    {
      POINT pt;
      pt.x = GET_X_LPARAM(lparam);
      pt.y = GET_Y_LPARAM(lparam);
      ScreenToClient(m_hwnd, (LPPOINT)&pt);

      ClientToScreen(m_hwnd, (LPPOINT)&pt);
      TrackPopupMenu(m_context_menu, TPM_LEFTALIGN, pt.x, pt.y, 0, m_hwnd, NULL);
    }
    break;
  case WM_PAINT:
    {
      PAINTSTRUCT ps;
      HWND sta = GetDlgItem(m_hwnd, IDC_STATIC1);
      HDC dc = BeginPaint(sta, &ps);
      DoPaint(m_hwnd, dc);
      EndPaint(sta, &ps);
    }
    break;
  case WM_SIZE:
    {
      if (wparam != SIZE_MINIMIZED)
      {
        m_resize.onResize();
      }
    }
    break;
  case WM_MOVE:
    {

    }
    break;
  case WM_DESTROY:
    {
      m_last_fn.Set("");

      KillTimer(m_hwnd, RSE_UPDATE_ARTWORK);

      RECT r;
      GetWindowRect(m_hwnd, &r);
      g_ini_file->write_int("artwork_wnd_x", r.left, EUTERPE_NAME);
      g_ini_file->write_int("artwork_wnd_y", r.top, EUTERPE_NAME);
      g_ini_file->write_int("artwork_wnd_w", r.right - r.left, EUTERPE_NAME);
      g_ini_file->write_int("artwork_wnd_h", r.bottom - r.top, EUTERPE_NAME);

      if (m_bm)
      {
        delete m_bm;
        m_bm = NULL;
      }

      if (m_bmp)
      {
        delete m_bmp;
        m_bmp = NULL;
      }

      CheckMenuItem(GetMenu(g_main_wnd->Handle()),
        ID_OPTIONS_VIEWARTWORK, MF_UNCHECKED);

      m_hwnd = NULL;
    }
    break;
  case WM_COMMAND:
    {
      switch(LOWORD(wparam))
      {
      case IDCANCEL:
        {
          DestroyWindow(m_hwnd);
        }
        break;
      case ID_ARTWORK_300X300: // 0.1
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_CHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 300, 300, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(300, 300);
          Update();
        }
        break;
      case ID_ARTWORK_400X400: // 0.2
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_CHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 400, 400, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(400, 400);
          Update();
        }
        break;
      case ID_ARTWORK_600X600: // 0.4
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_CHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 600, 600, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(600, 600);
          Update();
        }
        break;
      case ID_ARTWORK_800X800: // 0.6
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_CHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 800, 800, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(800, 800);
          Update();
        }
        break;
      case ID_ARTWORK_1000X1000: // 1.0
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_CHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 1000, 1000, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(1000, 1000);
          Update();
        }
        break;
      case ID_ARTWORK_1100X1100: // 1.2
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_CHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_UNCHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 1100, 1100, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(1100, 1100);
          Update();
        }
        break;
      case ID_ARTWORK_1200X1200: // 1.4
        {
          CheckMenuItem(m_context_menu, ID_ARTWORK_300X300, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_400X400, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_600X600, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_800X800, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1000X1000, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1100X1100, MF_UNCHECKED);
          CheckMenuItem(m_context_menu, ID_ARTWORK_1200X1200, MF_CHECKED);

          RECT r;
          GetWindowRect(m_hwnd, &r);
          SetWindowPos(m_hwnd, NULL, r.left, r.top, 1200, 1200, SWP_NOZORDER|SWP_NOACTIVATE);
          m_bm->resize(1200, 1200);
          Update();
        }
        break;
      }
    }
    break;
  }

  return 0;
}
