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

#include "euterpe_wasapi/wasapi_wnd.h"
#include "euterpe_wasapi/res/resource.h"
//#include "euterpe/plugin.h"

#include "WDL/win32_utf8.h"
#include "WDL/wdlstring.h"
#include "WDL/heapbuf.h"

RSE_WasapiWnd::RSE_WasapiWnd()
  : m_hwnd(NULL)
  , m_ini_file(NULL)
  , m_devlist(NULL)
{}

RSE_WasapiWnd::~RSE_WasapiWnd()
{}

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

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

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

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

WDL_DLGRET RSE_WasapiWnd::WasapiWndProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
  switch (msg)
  {
  case WM_INITDIALOG:
    {
      WDL_FastString inipath(GetSettingsPath());
      inipath.Append("euterpe_wasapi.ini");

      m_ini_file = new RSE_IniFile(inipath.Get());
      m_devlist = new RSE_WasapiDevice();

      m_devlist->Scan();

      HWND output_combo = GetDlgItem(m_hwnd, IDC_COMBO1);
      WDL_UTF8_HookComboBox(output_combo); // Needs to be called every time you use GetDlgItem

      for (int i = 0; i < m_devlist->output_dev.GetSize(); i++)
      {
        SendMessage(output_combo, CB_ADDSTRING, 0,
          (LPARAM)m_devlist->output_dev.Enumerate(i));
        SendMessage(output_combo, CB_SETITEMDATA,
          i, (LPARAM)m_devlist->output_dev.ReverseLookup(
          m_devlist->output_dev.Enumerate(i)));
      }

      int output_dev = m_ini_file->read_int("output_dev",
        m_devlist->GetDefaultOutputDevice(), "euterpe_wasapi");
      SendMessage(output_combo, CB_SETCURSEL,
        m_devlist->output_dev.GetIdx(output_dev), 0);

      HWND hw = GetDlgItem(m_hwnd, IDC_COMBO2);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"16 bit, 44100 Hz");
      SendMessage(hw, CB_SETITEMDATA, 0, (LPARAM)0);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"16 bit, 48000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 1, (LPARAM)1);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"16 bit, 88200 Hz");
      SendMessage(hw, CB_SETITEMDATA, 2, (LPARAM)2);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"16 bit, 96000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 3, (LPARAM)3);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"16 bit, 176400 Hz");
      SendMessage(hw, CB_SETITEMDATA, 4, (LPARAM)4);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"16 bit, 192000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 5, (LPARAM)5);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"24 bit, 44100 Hz");
      SendMessage(hw, CB_SETITEMDATA, 6, (LPARAM)6);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"24 bit, 48000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 7, (LPARAM)7);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"24 bit, 88200 Hz");
      SendMessage(hw, CB_SETITEMDATA, 8, (LPARAM)8);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"24 bit, 96000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 9, (LPARAM)9);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"24 bit, 176400 Hz");
      SendMessage(hw, CB_SETITEMDATA, 10, (LPARAM)10);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"24 bit, 192000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 11, (LPARAM)11);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"32 bit, 44100 Hz");
      SendMessage(hw, CB_SETITEMDATA, 12, (LPARAM)12);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"32 bit, 48000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 13, (LPARAM)13);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"32 bit, 88200 Hz");
      SendMessage(hw, CB_SETITEMDATA, 14, (LPARAM)14);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"32 bit, 96000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 15, (LPARAM)15);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"32 bit, 176400 Hz");
      SendMessage(hw, CB_SETITEMDATA, 16, (LPARAM)16);
      SendMessage(hw, CB_ADDSTRING, 0, (LPARAM)"32 bit, 192000 Hz");
      SendMessage(hw, CB_SETITEMDATA, 17, (LPARAM)17);

      int sample_fmt = m_ini_file->read_int("sample_fmt", 16, "euterpe_wasapi");

      // Make sure that the old values are valid
      // with the new approach.
      if (sample_fmt == 1616) sample_fmt = 16;
      if (sample_fmt == 2424) sample_fmt = 24;
      if (sample_fmt == 3224) sample_fmt = 24;
      if (sample_fmt == 3232) sample_fmt = 32;

      int samplerate = m_ini_file->read_int("samplerate", 44100, "euterpe_wasapi");

      if (sample_fmt == 16 && samplerate == 44100)
      {
        SendMessage(hw, CB_SETCURSEL, 0, 0);
      }
      else if (sample_fmt == 16 && samplerate == 48000)
      {
        SendMessage(hw, CB_SETCURSEL, 1, 0);
      }
      else if (sample_fmt == 16 && samplerate == 88200)
      {
        SendMessage(hw, CB_SETCURSEL, 2, 0);
      }
      else if (sample_fmt == 16 && samplerate == 96000)
      {
        SendMessage(hw, CB_SETCURSEL, 3, 0);
      }
      else if (sample_fmt == 16 && samplerate == 176400)
      {
        SendMessage(hw, CB_SETCURSEL, 4, 0);
      }
      else if (sample_fmt == 16 && samplerate == 192000)
      {
        SendMessage(hw, CB_SETCURSEL, 5, 0);
      }
      else if (sample_fmt == 24 && samplerate == 44100)
      {
        SendMessage(hw, CB_SETCURSEL, 6, 0);
      }
      else if (sample_fmt == 24 && samplerate == 48000)
      {
        SendMessage(hw, CB_SETCURSEL, 7, 0);
      }
      else if (sample_fmt == 24 && samplerate == 88200)
      {
        SendMessage(hw, CB_SETCURSEL, 8, 0);
      }
      else if (sample_fmt == 24 && samplerate == 96000)
      {
        SendMessage(hw, CB_SETCURSEL, 9, 0);
      }
      else if (sample_fmt == 24 && samplerate == 176400)
      {
        SendMessage(hw, CB_SETCURSEL, 10, 0);
      }
      else if (sample_fmt == 24 && samplerate == 192000)
      {
        SendMessage(hw, CB_SETCURSEL, 11, 0);
      }
      else if (sample_fmt == 32 && samplerate == 44100)
      {
        SendMessage(hw, CB_SETCURSEL, 12, 0);
      }
      else if (sample_fmt == 32 && samplerate == 48000)
      {
        SendMessage(hw, CB_SETCURSEL, 13, 0);
      }
      else if (sample_fmt == 32 && samplerate == 88200)
      {
        SendMessage(hw, CB_SETCURSEL, 14, 0);
      }
      else if (sample_fmt == 32 && samplerate == 96000)
      {
        SendMessage(hw, CB_SETCURSEL, 15, 0);
      }
      else if (sample_fmt == 32 && samplerate == 176400)
      {
        SendMessage(hw, CB_SETCURSEL, 16, 0);
      }
      else if (sample_fmt == 32 && samplerate == 192000)
      {
        SendMessage(hw, CB_SETCURSEL, 17, 0);
      }

      int exclusive = m_ini_file->read_int("exclusive", 0, "euterpe_wasapi");
      if (exclusive)
      {
        CheckDlgButton(m_hwnd, IDC_CHECK1, TRUE);
        EnableWindow(GetDlgItem(m_hwnd, IDC_COMBO2), TRUE);
      }
      else
      {
        CheckDlgButton(m_hwnd, IDC_CHECK1, FALSE);
        EnableWindow(GetDlgItem(m_hwnd, IDC_COMBO2), FALSE);
      }
    }
    break;

  case WM_DESTROY:
    {
      m_devlist->input_dev.DeleteAll();
      m_devlist->output_dev.DeleteAll();

      delete m_devlist;
      m_devlist = NULL;

      delete m_ini_file;
      m_ini_file = NULL;
    }
    break;

  case WM_COMMAND:
    {
      switch (LOWORD(wparam))
      {
      case IDC_COMBO1:
        if (HIWORD(wparam) == CBN_SELCHANGE)
        {
          int index = (int)SendMessage(
            GetDlgItem(m_hwnd, IDC_COMBO1),
            CB_GETCURSEL, 0, 0);
          int output_dev = (int)SendMessage(
            GetDlgItem(m_hwnd, IDC_COMBO1),
            CB_GETITEMDATA, index, 0);
          //g_device_settings->Set("wo_output_dev", output_dev);
          m_ini_file->write_int("output_dev", output_dev, "euterpe_wasapi");
        }
        break;
      case IDC_COMBO2:
        if (HIWORD(wparam) == CBN_SELCHANGE)
        {
          int sample_fmt = 16;
          int samplerate = 44100;

          int index = (int)SendMessage(
            GetDlgItem(m_hwnd, IDC_COMBO2),
            CB_GETCURSEL, 0, 0);

          switch (index)
          {
          case 0:
            sample_fmt = 16;
            samplerate = 44100;
            break;
          case 1:
            sample_fmt = 16;
            samplerate = 48000;
            break;
          case 2:
            sample_fmt = 16;
            samplerate = 88200;
            break;
          case 3:
            sample_fmt = 16;
            samplerate = 96000;
            break;
          case 4:
            sample_fmt = 16;
            samplerate = 176400;
            break;
          case 5:
            sample_fmt = 16;
            samplerate = 192000;
            break;
          case 6:
            sample_fmt = 24;
            samplerate = 44100;
            break;
          case 7:
            sample_fmt = 24;
            samplerate = 48000;
            break;
          case 8:
            sample_fmt = 24;
            samplerate = 88200;
            break;
          case 9:
            sample_fmt = 24;
            samplerate = 96000;
            break;
          case 10:
            sample_fmt = 24;
            samplerate = 176400;
            break;
          case 11:
            sample_fmt = 24;
            samplerate = 192000;
            break;
          case 12:
            sample_fmt = 32;
            samplerate = 44100;
            break;
          case 13:
            sample_fmt = 32;
            samplerate = 48000;
            break;
          case 14:
            sample_fmt = 32;
            samplerate = 88200;
            break;
          case 15:
            sample_fmt = 32;
            samplerate = 96000;
            break;
          case 16:
            sample_fmt = 32;
            samplerate = 176400;
            break;
          case 17:
            sample_fmt = 32;
            samplerate = 192000;
            break;
          }

          m_ini_file->write_int("sample_fmt", sample_fmt, "euterpe_wasapi");
          m_ini_file->write_int("samplerate", samplerate, "euterpe_wasapi");
        }
        break;
      case IDC_CHECK1:
        {
          LRESULT y = SendMessage(GetDlgItem(m_hwnd, IDC_CHECK1), BM_GETCHECK, 0, 0);

          if (y)
          {
            EnableWindow(GetDlgItem(m_hwnd, IDC_COMBO2), TRUE);
            m_ini_file->write_int("exclusive", 1, "euterpe_wasapi");
          }
          else
          {
            EnableWindow(GetDlgItem(m_hwnd, IDC_COMBO2), FALSE);
            m_ini_file->write_int("exclusive", 0, "euterpe_wasapi");
          }
        }
        break;
      }
    }
    break;
  }

  return 0;
}
