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

#include <main.h>
#include <core.h>

#include <core/version.h>
#include <res/resource.h>

#if __linux__
HMENU SWELL_app_stocksysmenu;
#else
extern HMENU SWELL_app_stocksysmenu;
#endif

double wall_0, wall_1, cpu_0, cpu_1;

extern "C" {

    INT_PTR SWELLAppMain(int msg, INT_PTR parm1, INT_PTR parm2)
    {
        switch (msg)
        {
        case SWELLAPP_ONLOAD:
            {
                wall_0 = get_wall_time();
                cpu_0 = get_cpu_time();
            }
            break;

        case SWELLAPP_LOADED:
            {

                if (SWELL_app_stocksysmenu)
                {
                    HMENU menu = CreatePopupMenu();
                    HMENU nm = SWELL_DuplicateMenu(SWELL_app_stocksysmenu);

                    if (nm)
                    {
                        MENUITEMINFO mi = { sizeof(mi), MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE, MFT_STRING, 0, 0, nm, NULL, NULL, 0, "Euterpe" };
                        InsertMenuItem(menu, 0, TRUE, &mi);
                    }

                    SWELL_SetDefaultWindowMenu(menu);
                }


                {
                    HMENU menu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
                    {
                        HMENU sm = GetSubMenu(menu, 0);
                        DeleteMenu(sm, ID_FILE_QUIT, MF_BYCOMMAND);

                        int a = GetMenuItemCount(sm);

                        while (a > 0 && GetMenuItemID(sm, a - 1) == 0)
                        {
                            DeleteMenu(sm, a - 1, MF_BYPOSITION);
                        }

                        a--;
                    }
                    DeleteMenu(menu, GetMenuItemCount(menu) - 1, MF_BYPOSITION);


                    if (SWELL_app_stocksysmenu)
                    {
                        HMENU nm = SWELL_DuplicateMenu(SWELL_app_stocksysmenu);

                        if (nm)
                        {
                            MENUITEMINFO mi = { sizeof(mi), MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE, MFT_STRING, 0, 0, nm, NULL, NULL, 0, "Euterpe"};

                            InsertMenuItem(menu, 0, TRUE, &mi);
                        }

                    }

                    main_dlg.Create(NULL, true);

                    SetMenu(main_dlg.GetDialog(), menu);

                    if (version.IsPrototypon())
                    {
                        const char msg[] =
                        {
                            "Welcome to " APP_NAME " (the ``Software'').\n\n"
                            "THIS IS A PROTOTYPON STILL IN DEVELOPEMENT PHASE "
                            "AND IS PROVIDED ON AN ``AS IS'' BASIS AND IS BELIEVED "
                            "TO CONTAIN DEFECTS AND A PRIMARY PURPOSE OF THIS "
                            "PROTOTYPON IS TO OBTAIN FEEDBACK ON SOFTWARE PERFORMANCE "
                            "AND THE IDENTIFICATION OF DEFECTS.\n\n"
                            "IT IS ADVISED TO SAFEGUARD IMPORTANT DATA, TO USE CAUTION AND NOT "
                            "TO RELY IN ANY WAY ON THE CORRECT FUNCTIONING OF THIS VERSION.\n\n"
                            APP_COPYRIGHT
                        };


                        double wall_1 = get_wall_time();
                        double cpu_1 = get_cpu_time();
                        double wall_elapsed_sec = wall_1 - wall_0;
                        double cpu_elapsed_sec = cpu_1 - cpu_0;

                        WDL_FastString prototype;
                        prototype.Set(msg);
                        prototype.AppendFormatted(128, "\n\nStartup time.\nWall time: "
                                                  "%f sec.\nCPU time: "
                                                  "%f sec.",
                                                  wall_elapsed_sec,
                                                  cpu_elapsed_sec);

                        MessageBox(main_dlg.GetDialog(), prototype.Get(), "ALPHA PROTOTYPON", MB_OK);
                    }
                }

            }
            break;

        case SWELLAPP_ONCOMMAND:
            {
                if (main_dlg.GetDialog() && (parm1 & 0xFFFF))
                {
                    SendMessage(main_dlg.GetDialog(), WM_COMMAND, parm1 & 0xFFFF, 0);
                }
            }
            break;

        case SWELLAPP_DESTROY:
            {
                //if (g_main_wnd) DestroyWindow(g_main_wnd);
            } break;

        case SWELLAPP_PROCESSMESSAGE:
            {
                if (MainProcessMessage((MSG *) parm1) > 0)
                {
                    return 1;
                }

                return 0;
            }
            break;
        }

        return 0;
    }

};

#include <whittle/swell/swell-dlggen.h>
#include <winclient/res/euterpe.rc_mac_dlg>

#undef BEGIN
#undef END
#include <whittle/swell/swell-menugen.h>
#include <winclient/res/euterpe.rc_mac_menu>


*/

//#define SWELL_PROVIDED_BY_APP

#include "WDL/swell/swell.h"
#include "WDL/swell/swell-functions.h"
#include "WDL/lineparse.h"
#include "WDL/filewrite.h"
#include "WDL/ptrlist.h"
#include "WDL/heapbuf.h"
#include "euterpe/definitions.h"
#include "euterpe/main_wnd.h"
#include "euterpe/app_info.h"
#include "euterpe/plugin.h"

// Get home directory
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

//extern char *strndup(const char *__string, size_t __n);

//HINSTANCE instance;

extern "C"
{
  INT_PTR SWELLAppMain(int msg, INT_PTR parm1, INT_PTR parm2)
  {
    switch (msg)
    {
    case SWELLAPP_ONLOAD:

      break;

    case SWELLAPP_LOADED:

      break;

    case SWELLAPP_DESTROY:
      {
        //if (g_main_wnd->Handle()) DestroyWindow(g_main_wnd->Handle());
      } break;

    case SWELLAPP_ACTIVATE:
      {
        //if (parm1) SendMessage(g_main_wnd->Handle(), WM_ACTIVATEAPP, TRUE, 0);

        //return 0;
      }
      break;

    case SWELLAPP_PROCESSMESSAGE:
      {
        if (g_main_wnd->ProcessMessage((MSG *)parm1) > 0) return 1;

        return 0;
      }
    }

    return 0;
  }
}

//#include "euterpe/playlist_control.h"

//static HWND ccontrol_creator(HWND parent, const char *cname,
//                             int idx, const char *classname,
//                             int style, int x, int y, int w,
//                             int h)
//{
//  if (!stricmp(classname, "playlist_control_superhost"))
//  {
//    HWND hw = CreateDialog(NULL, 0, parent, (DLGPROC) custom_playlist_control_proc);
//    SetWindowLong(hw, GWL_ID, idx);
//    SetWindowPos(hw, HWND_TOP, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE);
//    ShowWindow(hw, SW_SHOWNA);
//    return hw;
//  }
//
//  return 0;
//}

HWND curses_ControlCreator(HWND parent, const char *cname, int idx, const char *classname, int style, int x, int y, int w, int h);

int main(int argc, char *argv[])
{
  char cmd_param[32767]; int len = 0;

  for (int i = 0; i < argc; i++)
  {
    bool wq = false;
    if (strncmp(argv[i], "--", 2)) { wq = true; }
    if (wq)
    {
      strcpy(cmd_param + len, " ");
      len = (int)strlen(cmd_param);
      strcpy(cmd_param + len, "'");
      len = (int)strlen(cmd_param);
    }
    strcpy(cmd_param + len, argv[i]);
    len = (int)strlen(cmd_param);
    if (wq) { strcpy(cmd_param + len, "'"); }
    len = (int)strlen(cmd_param);
    strcpy(cmd_param + len, " ");
    len = (int)strlen(cmd_param);
  }

  SWELL_ExtendedAPI("APPNAME", (void *)"Euterpe");

  WDL_TypedBuf<int> datatype;
  WDL_PtrList_DeleteOnDestroy<WDL_FastString> fadd, faddnew;
  {
    LineParser lp;
    lp.parse(cmd_param);

    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--sleep"))
      {
        Sleep(888);
      }
    }

    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--add"))
      {
        datatype.Add(1);
        while (++i < lp.getnumtokens() &&
          strncmp(lp.gettoken_str(i), "--", 2))
        {
          fadd.Add(new WDL_FastString(lp.gettoken_str(i)));
        }
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--addnew"))
      {
        datatype.Add(2);
        while (++i < lp.getnumtokens() &&
          strncmp(lp.gettoken_str(i), "--", 2))
        {
          faddnew.Add(new WDL_FastString(lp.gettoken_str(i)));
        }
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--pause"))
      {
        datatype.Add(3);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--previous"))
      {
        datatype.Add(4);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--next"))
      {
        datatype.Add(5);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--play"))
      {
        datatype.Add(6);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--stop"))
      {
        datatype.Add(7);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--exit"))
      {
        datatype.Add(8);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--show"))
      {
        datatype.Add(9);
      }
    }
    for (int i = 0; i < lp.getnumtokens(); i++)
    {
      if (!strcmp(lp.gettoken_str(i), "--hide"))
      {
        datatype.Add(10);
      }
    }
  }

  HWND other_alive = FindWindowEx(NULL, NULL, "euterpe_superhost", NULL);

  typedef struct tagCOPYDATASTRUCT
  {
    ULONG_PTR dwData;
    DWORD cbData;
    PVOID lpData;
  } COPYDATASTRUCT;

  if (other_alive)
  {
    SetForegroundWindow(other_alive);

    COPYDATASTRUCT cds;
    for (int i = 0; i < datatype.GetSize(); i++)
    {
      if (datatype.Get()[i] >= 3 && datatype.Get()[i] <= 10)
      {
        cds.dwData = datatype.Get()[i];
        cds.cbData = 0;
        cds.lpData = 0;
        SendMessage(other_alive, WM_COPYDATA, (WPARAM)other_alive, (LPARAM)(LPVOID)&cds);
      }
      else if (datatype.Get()[i] == 2)
      {
        for (int j = 0; j < faddnew.GetSize(); j++)
        {
          if (datatype.Get()[i] == 2)
          {
            cds.dwData = datatype.Get()[i];
            cds.cbData = 0;
            cds.lpData = 0;
            SendMessage(other_alive, WM_COPYDATA, (WPARAM)other_alive, (LPARAM)(LPVOID)&cds);
            datatype.Get()[i] = 1;
          }
          cds.dwData = datatype.Get()[i];
          cds.cbData = faddnew.Get(j)->GetLength() + 1;
          cds.lpData = (char *)faddnew.Get(j)->Get();
          SendMessage(other_alive, WM_COPYDATA, (WPARAM)other_alive, (LPARAM)(LPVOID)&cds);
        }
        faddnew.Empty(true);
      }
      else if (datatype.Get()[i] == 1)
      {
        for (int j = 0; j < fadd.GetSize(); j++)
        {
          cds.dwData = datatype.Get()[i];
          cds.cbData = fadd.Get(j)->GetLength() + 1;
          cds.lpData = (char *)fadd.Get(j)->Get();
          SendMessage(other_alive, WM_COPYDATA, (WPARAM)other_alive, (LPARAM)(LPVOID)&cds);
        }
        fadd.Empty(true);
      }
    }
    datatype.Resize(0);

    return 0;
  }

  //SWELL_RegisterCustomControlCreator(ccontrol_creator);
  SWELL_RegisterCustomControlCreator(curses_ControlCreator);

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

  g_module_path.Set(module_filename);
  g_module_path.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 Euterpe.

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

    if (!dir.First(g_module_path.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_settings_path.Set(g_module_path.Get());
    g_settings_path.Append("portable");
    g_settings_path.Append(WDL_DIRCHAR_STR);
  }
  else
  {
    struct passwd *pw = getpwuid(getuid());
    const char *homedir = pw->pw_dir;

    WDL_FastString home_dir(homedir);
    home_dir.Append(WDL_DIRCHAR_STR);
    home_dir.Append(".config");
    home_dir.Append(WDL_DIRCHAR_STR);

    CreateDirectory(home_dir.Get(), NULL);

    home_dir.Append("Euterpe");
    home_dir.Append(WDL_DIRCHAR_STR);

    CreateDirectory(home_dir.Get(), NULL);
    g_settings_path.Set(home_dir.Get());
  }

  g_ini_path.Set(g_settings_path.Get());
  g_ini_path.Append(EUTERPE_NAME);
  g_ini_path.Append(".ini");

  LoadPlugins();

  // Start sub-systems
  g_ini_file = new RSE_IniFile(g_ini_path.Get());

  g_main_wnd = new RSE_MainWnd;

  SWELL_Internal_PostMessage_Init();

  CreateDialogParam(g_inst, MAKEINTRESOURCE(IDD_MAIN), NULL,
    RSE_MainWnd::ST_MainWndProc, (LPARAM)g_main_wnd);

  {
    SetForegroundWindow(g_main_wnd->Handle());

    COPYDATASTRUCT cds;
    for (int i = 0; i < datatype.GetSize(); i++)
    {
      if (datatype.Get()[i] >= 3 && datatype.Get()[i] <= 10)
      {
        cds.dwData = datatype.Get()[i];
        cds.cbData = 0;
        cds.lpData = 0;
        SendMessage(g_main_wnd->Handle(), WM_COPYDATA,
          (WPARAM)g_main_wnd->Handle(), (LPARAM)(LPVOID)&cds);
      }
      else if (datatype.Get()[i] == 2)
      {
        for (int j = 0; j < faddnew.GetSize(); j++)
        {
          if (datatype.Get()[i] == 2)
          {
            cds.dwData = datatype.Get()[i];
            cds.cbData = 0;
            cds.lpData = 0;
            SendMessage(g_main_wnd->Handle(), WM_COPYDATA,
              (WPARAM)g_main_wnd->Handle(), (LPARAM)(LPVOID)&cds);
            datatype.Get()[i] = 1;
          }
          cds.dwData = datatype.Get()[i];
          cds.cbData = faddnew.Get(j)->GetLength() + 1;
          cds.lpData = (char *)faddnew.Get(j)->Get();
          SendMessage(g_main_wnd->Handle(), WM_COPYDATA,
            (WPARAM)g_main_wnd->Handle(), (LPARAM)(LPVOID)&cds);
        }
        faddnew.Empty(true);
      }
      else if (datatype.Get()[i] == 1)
      {
        for (int j = 0; j < fadd.GetSize(); j++)
        {
          cds.dwData = datatype.Get()[i];
          cds.cbData = fadd.Get(j)->GetLength() + 1;
          cds.lpData = (char *)fadd.Get(j)->Get();
          SendMessage(g_main_wnd->Handle(), WM_COPYDATA,
            (WPARAM)g_main_wnd->Handle(), (LPARAM)(LPVOID)&cds);
        }
        fadd.Empty(true);
      }
    }
    datatype.Resize(0);
  }

  while (!has_requested_quit)
  {
    SWELL_RunMessageLoop();

    Sleep(10);
  }

  if (g_main_wnd->Handle()) DestroyWindow(g_main_wnd->Handle());

  delete g_main_wnd;

  delete g_ini_file;

  ReleasePlugins();

  return 0;
}

#include "WDL/swell/swell-dlggen.h"
#include "euterpe/res/euterpe.rc_mac_dlg"

#undef BEGIN
#undef END
#include "WDL/swell/swell-menugen.h"
#include "euterpe/res/euterpe.rc_mac_menu"
