#include "wxinc.h"
#include "wx/print.h"
#include "wx/printdlg.h"

#include "xvt.h"
#include "oslinux.h"

#include "xvt_menu.h"
#include "xvt_help.h"
#include "xvintern.h"
#include <wx/fontenum.h>
#include <wx/string.h>
#include <wx/snglinst.h>
#include <wx/utils.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <mntent.h>
#include <sys/vfs.h>
#include <unistd.h>

wxString OsLinux_File2App(const char* filename)
{
  wxString app;

  SORRY_BOX();
  return app;
}

int OsLinux_EnumerateFamilies(char** families, int max_count)
{
  wxFontEnumerator ef;

  ef.EnumerateFacenames();
  wxArrayString * fonts = ef.GetFacenames();

  size_t items = fonts->GetCount();
  size_t i;

  for (i = 0; i < items; i++)
    families[i] = xvt_str_duplicate((*fonts)[i].c_str());
	
	return items;
}

int OsLinux_EnumerateSizes(const char* name, long* sizes, short* scalable, int max_count)
{
  int i = 0;
	*scalable = 1;

  for (int size = 4; size < 80; size++)
     sizes[i++] = size;
  return i;
}

void OsLinux_PlaceProcessInWindow(unsigned int instance, const char* name, unsigned int parent)
{
  SORRY_BOX();
}

void OsLinux_UpdateWindow(unsigned int handle)
{
 // non deve fare nulla in Linux, sembra di si verificare SORRY_BOX();
}

///////////////////////////////////////////////////////////
// Hardlock Support
///////////////////////////////////////////////////////////

#include "hlapi_c.h"

bool OsLinux_HL_Login(unsigned short address, const unsigned char* label, const unsigned char* password)
{
  int err = HL_LOGIN(address, LOCAL_DEVICE, (unsigned char*)label, (unsigned char*)password);
  return err == STATUS_OK;
}

bool OsLinux_HL_Logout()
{
  HL_LOGOUT();
  return TRUE;
}

bool OsLinux_HL_Read(unsigned short reg, unsigned short* data)
{
  int err = HL_READ(reg, data);
  return err == STATUS_OK;
}

bool OsLinux_HL_ReadBlock(unsigned char* data)
{
  int err = HL_READBL(data);
  return err == STATUS_OK;
}

bool OsLinux_HL_Write(unsigned short reg, unsigned short data)
{
  int err = HL_WRITE(reg, data);
  return err == STATUS_OK;
}

bool OsLinux_HL_Crypt(unsigned short* data) // Array di 4 words (8 bytes)
{
  int err = HL_CODE(data, 1);
  return err == STATUS_OK;
}

///////////////////////////////////////////////////////////
// Eutron Smartlink Support
///////////////////////////////////////////////////////////

#include "skeylinux.h"

static SKEY_DATA skey;

bool OsLinux_SL_Crypt(unsigned short* data)
{
  skey.command = SCRAMBLING_MODE;
  memset(skey.data, 0, sizeof(skey.data));
  memcpy(skey.data, data, 8);
  clink(&skey);
  const bool ok = (skey.status == ST_OK);
  if (ok)
    memcpy(data, skey.data, 8);
  return ok;
}

bool OsLinux_SL_Login(const unsigned char* label, const unsigned char* password)
{
  memset(&skey, 0, sizeof(SKEY_DATA));
  skey.command = LOCATING_MODE;
  skey.status = ST_HW_FAILURE; // Don't leave ST_OK = 0 here!
  memcpy(skey.label, label, strlen((const char*)label));
  memcpy(skey.password, password, strlen((const char*)password));

  clink(&skey);
  return skey.status == ST_OK;
}

bool OsLinux_SL_Logout()
{
  skey.command = 0;
  clink(&skey);
  return true;
}

bool OsLinux_SL_ReadBlock(unsigned short reg, unsigned short size, unsigned short* data)
{
  skey.command = BLOCK_READING_MODE;
  unsigned short* pointer = (unsigned short*)(&skey.data[0]);
  unsigned short* number  = (unsigned short*)(&skey.data[2]);
  *pointer = reg;
  *number = size;
  clink(&skey);
  const bool ok = skey.status == ST_OK;
  if (ok)
    memcpy(data, &skey.data[4], size*sizeof(unsigned short));
  return ok;
}

bool OsLinux_SL_WriteBlock(unsigned short reg, unsigned short size, const unsigned short* data)
{
  skey.command = BLOCK_WRITING_MODE;
  unsigned short* pointer = (unsigned short*)(&skey.data[0]);
  unsigned short* number  = (unsigned short*)(&skey.data[2]);
  *pointer = reg;
  *number = size;
  memcpy(&skey.data[4], data, size*sizeof(unsigned short));
  clink(&skey);
  return skey.status == ST_OK;
}

void  OsLinux_GetFileSys(const char* path, char * dev, char * dir, char * type)
{
  struct mntent *m;
  FILE *f = setmntent("/etc/mnttab", "r");

  while ((m = getmntent(f)) && strncmp(path, m->mnt_dir, strlen(m->mnt_dir)) != 0);
  if (m)
  {
    if (dev) strcpy(dev, m->mnt_fsname);
    if (dir) strcpy(dir, m->mnt_dir);
    if (type) strcpy(type, m->mnt_type);
  }
  else
  {
    if (dev) *dev = '\0';
    if (dir) *dir = '\0';
    if (type) *type = '\0';
  }
  endmntent(f);
}


bool OsLinux_IsNetworkDrive(const char * path)
{
  struct statfs buf;

  if (statfs(path, &buf) == -1)
    return FALSE;
  return (buf.f_type == 0x6969 /*NFS_SUPER_MAGIC */) ||
         (buf.f_type == 0x517B /*SMB_SUPER_MAGIC)*/);
}

int64_t OsLinux_GetDiskFreeSpace(const char * path)
{
  struct statfs buf;
  int64_t nBytes = 0L;

  if (statfs(path, &buf) != -1)
  {
    nBytes = buf.f_bsize;
    nBytes *= buf.f_bavail;
    nBytes *= 1024;
  }

  return nBytes;
}

#include "wx/settings.h"
#include "X11/Xutil.h"

#ifndef MWM_DECOR_BORDER
#define MWM_HINTS_FUNCTIONS     (1L << 0)
#define MWM_HINTS_DECORATIONS   (1L << 1)
#define MWM_HINTS_INPUT_MODE    (1L << 2)
#define MWM_HINTS_STATUS        (1L << 3)
#define MWM_DECOR_ALL           (1L << 0)
#define MWM_DECOR_BORDER        (1L << 1)
#define MWM_DECOR_RESIZEH       (1L << 2)
#define MWM_DECOR_TITLE         (1L << 3)
#define MWM_DECOR_MENU          (1L << 4)
#define MWM_DECOR_MINIMIZE      (1L << 5)
#define MWM_DECOR_MAXIMIZE      (1L << 6)
#define MWM_FUNC_ALL            (1L << 0)
#define MWM_FUNC_RESIZE         (1L << 1)
#define MWM_FUNC_MOVE           (1L << 2)
#define MWM_FUNC_MINIMIZE       (1L << 3)
#define MWM_FUNC_MAXIMIZE       (1L << 4)
#define MWM_FUNC_CLOSE          (1L << 5)
#define MWM_INPUT_MODELESS 0
#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
#define MWM_INPUT_SYSTEM_MODAL 2
#define MWM_INPUT_FULL_APPLICATION_MODAL 3
#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
#define MWM_TEAROFF_WINDOW (1L<<0)
#endif

struct MwmHints {
    long flags;
    long functions;
    long decorations;
    long input_mode;
};
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
// Set the window manager decorations according to the
// given wxWindows style
bool wxSetWMDecorations(Window w, long style)
{
    Atom mwm_wm_hints = XInternAtom((Display * )wxGetDisplay(),"_MOTIF_WM_HINTS", False);
    if (mwm_wm_hints == 0)
       return FALSE;

    MwmHints hints;
    hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
    hints.decorations = 0;
    hints.functions = 0;

//    if ((style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
    if (style & wxNO_BORDER)
    {
        // leave zeros
    }
    else
    {
        hints.decorations = MWM_DECOR_BORDER;
        hints.functions = MWM_FUNC_MOVE | MWM_FUNC_CLOSE;
        if ((style & wxCAPTION) != 0)
            hints.decorations |= MWM_DECOR_TITLE;

        if ((style & wxSYSTEM_MENU) != 0)
        {
            hints.decorations |= MWM_DECOR_MENU;
        }

        if ((style & wxMINIMIZE_BOX) != 0)
        {
            hints.functions |= MWM_FUNC_MINIMIZE;
            hints.decorations |= MWM_DECOR_MINIMIZE;
        }

        if ((style & wxMAXIMIZE_BOX) != 0)
        {
            hints.functions |= MWM_FUNC_MAXIMIZE;
            hints.decorations |= MWM_DECOR_MAXIMIZE;
        }

        if ((style & wxRESIZE_BORDER) != 0)
        {
            hints.functions |= MWM_FUNC_RESIZE;
            hints.decorations |= MWM_DECOR_RESIZEH;
        }
    }
    XChangeProperty((Display *) wxGetDisplay(), w, mwm_wm_hints, mwm_wm_hints, 32, PropModeReplace,
    								(unsigned char *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
    return TRUE;
}

#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>

void OsLinux_SetCaptionStyle(wxWindow * w, long style)
{
  wxSetWMDecorations(GDK_WINDOW_XID(w->m_widget->window), style);
}


int OsLinux_GetSessionId()
{
	char s[80];

	strcpy(s, getenv("DISPLAY"));

	char * p = strchr(s, ':');

	if (p == NULL)
		p = s;
	else
		p++;

	char * e = strchr(p, '.');

	if (e != NULL)
		*e = '\0';

	return atoi(p);
}