/***************************************************************************
 begin       : Mon Apr 12 2010
 copyright   : (C) 2025 by Martin Preuss
 email       : martin@aqbanking.de

 ***************************************************************************
 * This file is part of the project "AqBanking".                           *
 * Please see toplevel file COPYING of that project for license details.   *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif



#include "dlg_pintan_special_p.h"

#include "aqbanking/i18n_l.h"
#include <aqbanking/backendsupport/user.h>
#include <aqbanking/banking_be.h>

#include "aqhbci/banking/user.h"
#include "aqhbci/banking/provider.h"

#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/misc.h>
#include <gwenhywfar/pathmanager.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/gui.h>



/* ------------------------------------------------------------------------------------------------
 * defines
 * ------------------------------------------------------------------------------------------------
 */

#define DIALOG_MINWIDTH  200
#define DIALOG_MINHEIGHT 100

#define DLG_NAME                "ah_setup_pintan_special"
#define DLG_DIALOGFILE          "aqbanking/backends/aqhbci/dialogs/dlg_pintan_special.dlg"


/* IDs for dialog widgets */
#define ID_SELF                 ""
#define ID_OK_BUTTON            "okButton"
#define ID_ABORT_BUTTON         "abortButton"
#define ID_HBCIVERSION_COMBO    "hbciVersionCombo"
#define ID_HTTPVERSION_COMBO    "httpVersionCombo"
#define ID_TANMEDIUM_EDIT       "tanMediumIdEdit"
#define ID_NOBASE64_CHECK       "noBase64Check"
#define ID_OMITSMSACCOUNT_CHECK "omitSmsAccountCheck"



/* ------------------------------------------------------------------------------------------------
 * types
 * ------------------------------------------------------------------------------------------------
 */

typedef int (*_DIALOG_SIGNAL_HANDLER_FN)(GWEN_DIALOG *dlg);
typedef struct _DIALOG_SIGNAL_ENTRY _DIALOG_SIGNAL_ENTRY;
struct _DIALOG_SIGNAL_ENTRY {
  const char *sender;
  GWEN_DIALOG_EVENTTYPE eventType;
  _DIALOG_SIGNAL_HANDLER_FN handlerFn;
};



/* ------------------------------------------------------------------------------------------------
 * forward declarations
 * ------------------------------------------------------------------------------------------------
 */

static int _handleInit(GWEN_DIALOG *dlg);
static int _handleFini(GWEN_DIALOG *dlg);

static int _handleActivatedOk(GWEN_DIALOG *dlg);
static int _handleActivatedAbort(GWEN_DIALOG *dlg);

static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static int GWENHYWFAR_CB _signalHandler(GWEN_DIALOG *dlg, GWEN_DIALOG_EVENTTYPE t, const char *sender);



/* ------------------------------------------------------------------------------------------------
 * static vars
 * ------------------------------------------------------------------------------------------------
 */

GWEN_INHERIT(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG)


static _DIALOG_SIGNAL_ENTRY _signalMap[]={
  {NULL,                   GWEN_DialogEvent_TypeInit,         _handleInit},
  {NULL,                   GWEN_DialogEvent_TypeFini,         _handleFini},

  {ID_OK_BUTTON,           GWEN_DialogEvent_TypeActivated,    _handleActivatedOk},
  {ID_ABORT_BUTTON,        GWEN_DialogEvent_TypeActivated,    _handleActivatedAbort},

  {NULL, 0, NULL}
};



/* ------------------------------------------------------------------------------------------------
 * implementations
 * ------------------------------------------------------------------------------------------------
 */

GWEN_DIALOG *AH_PinTanSpecialDialog_new(AB_PROVIDER *pro)
{
  GWEN_DIALOG *dlg;
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  dlg=GWEN_Dialog_CreateAndLoadWithPath(DLG_NAME, AB_PM_LIBNAME, AB_PM_DATADIR, DLG_DIALOGFILE);
  if (dlg==NULL) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "here");
    return NULL;
  }

  GWEN_NEW_OBJECT(AH_PINTAN_SPECIAL_DIALOG, xdlg);
  GWEN_INHERIT_SETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg, xdlg, _freeData);
  GWEN_Dialog_SetSignalHandler(dlg, _signalHandler);

  xdlg->banking=AB_Provider_GetBanking(pro);
  xdlg->provider=pro;

  /* preset */
  xdlg->hbciVersion=300;
  xdlg->httpVMajor=1;
  xdlg->httpVMinor=1;

  /* done */
  return dlg;
}



void GWENHYWFAR_CB _freeData(void *bp, void *p)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  xdlg=(AH_PINTAN_SPECIAL_DIALOG *) p;
  free(xdlg->tanMediumId);

  GWEN_FREE_OBJECT(xdlg);
}



int AH_PinTanSpecialDialog_GetHttpVMajor(const GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  return xdlg->httpVMajor;
}



int AH_PinTanSpecialDialog_GetHttpVMinor(const GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  return xdlg->httpVMinor;
}



void AH_PinTanSpecialDialog_SetHttpVersion(GWEN_DIALOG *dlg, int vmajor, int vminor)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  xdlg->httpVMajor=vmajor;
  xdlg->httpVMinor=vminor;
}



int AH_PinTanSpecialDialog_GetHbciVersion(const GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  return xdlg->hbciVersion;
}



void AH_PinTanSpecialDialog_SetHbciVersion(GWEN_DIALOG *dlg, int i)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  xdlg->hbciVersion=i;
}



uint32_t AH_PinTanSpecialDialog_GetFlags(const GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  return xdlg->flags;
}



void AH_PinTanSpecialDialog_SetFlags(GWEN_DIALOG *dlg, uint32_t fl)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  xdlg->flags=fl;
}



void AH_PinTanSpecialDialog_AddFlags(GWEN_DIALOG *dlg, uint32_t fl)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  xdlg->flags&=~fl;
}



void AH_PinTanSpecialDialog_SubFlags(GWEN_DIALOG *dlg, uint32_t fl)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  xdlg->flags&=~fl;
}



const char *AH_PinTanSpecialDialog_GetTanMediumId(const GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  return xdlg->tanMediumId;
}



void AH_PinTanSpecialDialog_SetTanMediumId(GWEN_DIALOG *dlg, const char *s)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  free(xdlg->tanMediumId);
  xdlg->tanMediumId=(s && *s)?strdup(s):NULL;
}



int _handleInit(GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;
  GWEN_DB_NODE *dbPrefs;
  int i;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  dbPrefs=GWEN_Dialog_GetPreferences(dlg);

  GWEN_Dialog_SetCharProperty(dlg, ID_SELF, GWEN_DialogProperty_Title, 0, I18N("HBCI PIN/TAN Special Settings"), 0);

  GWEN_Dialog_SetCharProperty(dlg, ID_HBCIVERSION_COMBO, GWEN_DialogProperty_AddValue, 0, "2.20", 0);
  GWEN_Dialog_SetCharProperty(dlg, ID_HBCIVERSION_COMBO, GWEN_DialogProperty_AddValue, 0, "3.0", 0);

  GWEN_Dialog_SetCharProperty(dlg, ID_HTTPVERSION_COMBO, GWEN_DialogProperty_AddValue, 0, "1.0", 0);
  GWEN_Dialog_SetCharProperty(dlg, ID_HTTPVERSION_COMBO, GWEN_DialogProperty_AddValue, 0, "1.1", 0);

  /* toGui */
  switch (((xdlg->httpVMajor)<<8)+xdlg->httpVMinor) {
    case 0x0100: GWEN_Dialog_SetIntProperty(dlg, ID_HTTPVERSION_COMBO, GWEN_DialogProperty_Value, 0, 0, 0); break;
    case 0x0101: GWEN_Dialog_SetIntProperty(dlg, ID_HTTPVERSION_COMBO, GWEN_DialogProperty_Value, 0, 1, 0); break;
    default: break;
  }

  switch (xdlg->hbciVersion) {
    case 220: GWEN_Dialog_SetIntProperty(dlg, ID_HBCIVERSION_COMBO, GWEN_DialogProperty_Value, 0, 0, 0); break;
    case 300: GWEN_Dialog_SetIntProperty(dlg, ID_HBCIVERSION_COMBO, GWEN_DialogProperty_Value, 0, 1, 0); break;
    default: break;
  }

  GWEN_Dialog_SetIntProperty(dlg, ID_NOBASE64_CHECK, GWEN_DialogProperty_Value, 0, (xdlg->flags & AH_USER_FLAGS_NO_BASE64)?1:0, 0);

  GWEN_Dialog_SetIntProperty(dlg, ID_OMITSMSACCOUNT_CHECK, GWEN_DialogProperty_Value, 0,
                             (xdlg->flags & AH_USER_FLAGS_TAN_OMIT_SMS_ACCOUNT)?1:0, 0);

  if (xdlg->tanMediumId)
    GWEN_Dialog_SetCharProperty(dlg, ID_TANMEDIUM_EDIT, GWEN_DialogProperty_Value, 0, xdlg->tanMediumId, 0);
  /* set tooltip */
  GWEN_Dialog_SetCharProperty(dlg, ID_TANMEDIUM_EDIT, GWEN_DialogProperty_ToolTip, 0,
                              I18N("For smsTAN or mTAN this is your mobile phone number. "
                                   "Please ask your bank for the necessary format of this number."), 0);


  /* read width */
  i=GWEN_DB_GetIntValue(dbPrefs, "dialog_width", 0, -1);
  if (i>=DIALOG_MINWIDTH)
    GWEN_Dialog_SetIntProperty(dlg, ID_SELF, GWEN_DialogProperty_Width, 0, i, 0);

  /* read height */
  i=GWEN_DB_GetIntValue(dbPrefs, "dialog_height", 0, -1);
  if (i>=DIALOG_MINHEIGHT)
    GWEN_Dialog_SetIntProperty(dlg, ID_SELF, GWEN_DialogProperty_Height, 0, i, 0);

  return GWEN_DialogEvent_ResultHandled;
}



int _handleFini(GWEN_DIALOG *dlg)
{
  AH_PINTAN_SPECIAL_DIALOG *xdlg;
  int i;
  GWEN_DB_NODE *dbPrefs;
  uint32_t flags;
  const char *s;

  assert(dlg);
  xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, AH_PINTAN_SPECIAL_DIALOG, dlg);
  assert(xdlg);

  dbPrefs=GWEN_Dialog_GetPreferences(dlg);

  /* fromGui */
  i=GWEN_Dialog_GetIntProperty(dlg, ID_HBCIVERSION_COMBO, GWEN_DialogProperty_Value, 0, -1);
  switch (i) {
    case 0: xdlg->hbciVersion=220; break;
    default:
    case 1: xdlg->hbciVersion=300; break;
  }

  i=GWEN_Dialog_GetIntProperty(dlg, ID_HTTPVERSION_COMBO, GWEN_DialogProperty_Value, 0, -1);
  switch (i) {
  case 0:
    xdlg->httpVMajor=1;
    xdlg->httpVMinor=0;
    break;
  default:
  case 1:
    xdlg->httpVMajor=1;
    xdlg->httpVMinor=1;
    break;
  }

  flags=0;
  if (GWEN_Dialog_GetIntProperty(dlg, ID_NOBASE64_CHECK, GWEN_DialogProperty_Value, 0, 0))
    flags|=AH_USER_FLAGS_NO_BASE64;
  if (GWEN_Dialog_GetIntProperty(dlg, ID_OMITSMSACCOUNT_CHECK, GWEN_DialogProperty_Value, 0, 0))
    flags|=AH_USER_FLAGS_TAN_OMIT_SMS_ACCOUNT;
  xdlg->flags=flags;

  s=GWEN_Dialog_GetCharProperty(dlg, ID_TANMEDIUM_EDIT, GWEN_DialogProperty_Value, 0, NULL);
  AH_PinTanSpecialDialog_SetTanMediumId(dlg, s);

  /* store dialog width */
  i=GWEN_Dialog_GetIntProperty(dlg, ID_SELF, GWEN_DialogProperty_Width, 0, -1);
  GWEN_DB_SetIntValue(dbPrefs, GWEN_DB_FLAGS_OVERWRITE_VARS, "dialog_width", i);

  /* store dialog height */
  i=GWEN_Dialog_GetIntProperty(dlg, ID_SELF, GWEN_DialogProperty_Height, 0, -1);
  GWEN_DB_SetIntValue(dbPrefs, GWEN_DB_FLAGS_OVERWRITE_VARS, "dialog_height", i);
  return GWEN_DialogEvent_ResultHandled;
}



int _handleActivatedOk(GWEN_DIALOG *dlg)
{
  return GWEN_DialogEvent_ResultAccept;
}



int _handleActivatedAbort(GWEN_DIALOG *dlg)
{
  return GWEN_DialogEvent_ResultReject;
}



int GWENHYWFAR_CB _signalHandler(GWEN_DIALOG *dlg, GWEN_DIALOG_EVENTTYPE t, const char *sender)
{
  const _DIALOG_SIGNAL_ENTRY *entry;

  entry=_signalMap;
  while(entry->handlerFn) {
    if (entry->eventType==t && (entry->sender==NULL || (sender && strcasecmp(sender, entry->sender)==0))) {
      return entry->handlerFn(dlg);
    }
    entry++;
  }

  return GWEN_DialogEvent_ResultNotHandled;
}



