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

#include <shlobj.h>

#if defined(_WIN32) && defined(_DEBUG)
#include <vld.h>
#endif

#include "RSI/definitions.h"

#include "RSI/app_info.h"
#include "RSI/plugin.h"
#include "RSI/preferences.h"
#include "RSI/main_wnd.h"
#include "RSI/skin.h"

#include "WDL/win32_curses/curses.h"
#include "WDL/dirscan.h"
#include "WDL/wdlstring.h"

int WINAPI WinMain(_In_ HINSTANCE instance,
  _In_opt_ HINSTANCE previous_instance,
  _In_ LPSTR cmd_param, _In_ int show_cmd)
{
  g_inst = instance;

  CoInitialize(NULL);
  //CoInitializeEx(NULL, ); // COINIT_APARTMENTTHREADED, COINIT_MULTITHREADED

  InitCommonControls();
  //LoadLibrary("riched20.dll");

  g_scrollmessage = RegisterWindowMessage("MSWHEEL_ROLLMSG");

  HICON icon = LoadIcon(g_inst, MAKEINTRESOURCE(IDI_ICON1));

  {
    WNDCLASS wc = { 0 };
    GetClassInfo(NULL, "#32770", &wc);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = icon;
    wc.hInstance = g_inst;
    RegisterClass(&wc);

    //wc.style = CS_HREDRAW | CS_VREDRAW;
    //wc.style = CS_GLOBALCLASS;
    wc.style = CS_DBLCLKS;
    wc.lpszClassName = "rsi_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "license_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "changelog_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "preferences_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "about_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "load_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "stats_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "library_superhost";
    RegisterClass(&wc);

    wc.lpszClassName = "track_superhost";
    RegisterClass(&wc);

    //wc.lpfnWndProc = (WNDPROC)RSI_WaveformAWnd::WaveformAWndProc;
    //wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    //wc.lpszClassName = "waveforma_superhost";
    //RegisterClass(&wc);

    //wc.lpfnWndProc = (WNDPROC)RSI_WaveformBWndProc;
    //wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    //wc.lpszClassName = "waveformb_superhost";
    //RegisterClass(&wc);

    curses_registerChildClass(g_inst);

    //wc.style = CS_GLOBALCLASS;
    //wc.lpfnWndProc = (WNDPROC)main_draw_proc;
    //wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    //wc.lpszClassName = "maindraw_superhost";
    //RegisterClass(&wc);

    //wc.lpfnWndProc = (WNDPROC)custom_playlist_control_proc;
    //wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    //wc.lpszClassName = "playlist_control_superhost";
    //RegisterClass(&wc);
  }

  char modfn[2048];
  GetModuleFileName(g_inst, modfn, sizeof(modfn));

  g_modpath.Set(modfn);
  g_modpath.remove_filepart(true);

  bool portable_settings = false;

  // In order to have portable settings
  // create an empty directory with the
  // name |portable| in the root directory
  // of Terpsichore.

  if (!portable_settings)
  {
    WDL_DirScan dir;
    WDL_FastString fn;

    if (!dir.First(g_modpath.Get()))
    {
      do
      {
        if (dir.GetCurrentIsDirectory())
        {
          dir.GetCurrentFullFN(&fn);

          if (strcmp(fn.get_filepart(), "portable") == 0)
          {
            portable_settings = true;
            break;
          }
        }
      }
      while (!dir.Next());
    }
  }

  if (portable_settings)
  {
    g_setpath.Set(g_modpath.Get());
    g_setpath.Append("portable");
    g_setpath.Append(WDL_DIRCHAR_STR);
  }
  else
  {
    char user_path[2048];

    // CSIDL_APPDATA to get the equivalent of %APPDATA%
    // CSIDL_PROFILE to get the equivalent of %USERPROFILE%
    if (SHGetSpecialFolderPathUTF8(NULL, user_path, sizeof(user_path), CSIDL_APPDATA, 0))
    {
      g_setpath.Set(user_path);
      g_setpath.Append("\\" RSI_NAME_MARKETING "\\");
      CreateDirectory(g_setpath.Get(), NULL);
    }
    else
    {
      MessageBox(NULL, "RSI cannot retrieve user's roaming directory. Press OK to exit RSI.", "RSI error", MB_OK);
      exit(1);
    }
  }

  g_inipath.Set(g_setpath.Get());
  g_inipath.Append(RSI_NAME);
  g_inipath.Append(".ini");

  g_preferences = new RSI_Preferences;
  g_preferences->Create();
  if (WDL_unlikely(!g_preferences->Parse()))
  {
    WDL_FastString def(g_setpath), usr(g_setpath), err;
    def.Append("preferences-default.txt");
    usr.Append("preferences.txt");

    err.SetFormatted(512, "%s\nin %s\n\nPress OK to try load the default file:\n\n%s",
      g_preferences->GetParseError(), usr.Get(), def.Get());

    MessageBox(GetDesktopWindow(), err.Get(), "RSI: preferences parse error found", MB_OK);

    if (!g_preferences->Parse(true))
    {
      goto terminate;
    }
  }

  LoadPlugins();

  g_skin.LoadSkin();

  g_mainwnd = new RSI_MainWnd;
  CreateDialogParam(g_inst, MAKEINTRESOURCE(IDD_MAIN), GetDesktopWindow(),
    RSI_MainWnd::MainWndProc, (LPARAM)g_mainwnd);

  RSI_RunMessageLoop();

  delete g_mainwnd;
  ReleasePlugins();

terminate:
  bool relaunch = g_preferences->WantRelaunch();

  delete g_preferences;

  CoUninitialize();

  if (relaunch)
  {
    WDL_FastString mod(g_modpath);
    mod.Append(RSI_NAME ".exe");
    ShellExecute(NULL, "", mod.Get(), "", "", SW_SHOWNORMAL);
  }

  return 0;
}
