#include "SM_GuiToolkitPCH.h"
#include "SM_Window.h"
#include "SM_Main.h"


#define CLASSNAME "SMGUIWindow"


Window* Window::g_pInitWindow=0;

bool Window::m_bRegistered=false;

Window::Window  ()
{
  m_bIsOK = false;
}

Window::~Window()
{
  Shutdown();
}


int Window::InitPrivate(const char* pcName, DWORD dwExStyle, DWORD dwStyle, Window* pParent, const char* pcClassName)
{
  if (EventSuscriber::Init() != 0)
  {
    return -1;
  }
  
  if (!m_bRegistered && !pcClassName)
  {
    if (Register())
    {
      return -1;
    }
  }

  m_pParent = pParent;
  g_pInitWindow=this;

  
  m_hwnd=CreateWindowEx(
    dwExStyle,
    pcClassName?pcClassName:CLASSNAME,
    pcName,
    dwStyle,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    pParent?pParent->m_hwnd:0,
    0,
    SM_Main::HInstance(),
    0);

  if (!m_hwnd)
  {
    return -1;
  }
  
  return 0;
}

int Window::InitDialogPrivate (const char* pcName, LPCTSTR lpTemplate, Window* pParent)
{
  if (EventSuscriber::Init() != 0)
  {
    return -1;
  }
  
  if (!m_bRegistered)
  {
    if (Register())
    {
      return -1;
    }
  }

  m_pParent = pParent;
  g_pInitWindow=this;

  
  m_hwnd = CreateDialog(
    SM_Main::HInstance(),
    lpTemplate,
    pParent?pParent->m_hwnd:0,    
    StaticProcessDialogMessage);

    
  if (!m_hwnd)
  {
    return -1;
  }
  
  return 0;
}
  

void Window::Show()
{
  ShowWindow(m_hwnd, SW_SHOW);
}

int Window::Init(Window* pParent)
{
  assert(!"Should never be called");
  return 0;
}

int  Window::Shutdown    ()
{
  m_bIsOK=false;
  return 0;
}

bool Window::IsOk()
{
  return m_bIsOK;
}

LRESULT CALLBACK Window::StaticProcessMessage(HWND hwnd, const UINT message, const WPARAM wParam, const LPARAM lParam)
{
  Window* pWindow;  

  pWindow=(Window*) GetWindowLong(hwnd, GWL_USERDATA);

  if (!pWindow)
  {
    // Make thread safe
    assert(g_pInitWindow);

    // Set this pointer in our private space
    pWindow=g_pInitWindow;
    SetWindowLong(hwnd, GWL_USERDATA, (LONG) pWindow);

    // Assign handle
    g_pInitWindow->m_hwnd = hwnd;

    // Reset
    g_pInitWindow = 0;
  }
  
  assert(pWindow);

  return pWindow->ProcessMessage(message, wParam, lParam);
}

int CALLBACK Window::StaticProcessDialogMessage  (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  Window* pWindow;  

  pWindow=(Window*) GetWindowLong(hwndDlg, DWL_USER);

  if (!pWindow)
  {
    // Make thread safe
    assert(g_pInitWindow);

    // Set this pointer in our private space
    pWindow=g_pInitWindow;
    SetWindowLong(hwndDlg, DWL_USER, (LONG) pWindow);

    // Assign handle
    g_pInitWindow->m_hwnd = hwndDlg;

    // Reset
    g_pInitWindow = 0;
  }

  
  return pWindow->ProcessDialogMessage(uMsg, wParam, lParam);
}


int Window::ProcessMessage(const UINT message, const WPARAM wParam, const LPARAM lParam)
{
  return DefWindowProc(m_hwnd, message, wParam, lParam);
}

int Window::ProcessDialogMessage(const UINT message, const WPARAM wParam, const LPARAM lParam)
{
  return FALSE;
}


bool Window::IsRegistered()
{
  return m_bRegistered;
}

int Window::Register()
{
  WNDCLASS wc;

  wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
	wc.lpfnWndProc = (WNDPROC)StaticProcessMessage;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = NULL;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = "";
	wc.lpszClassName = CLASSNAME;


  if (!RegisterClass(&wc))
  {
    return -1;
  }

  m_bRegistered = true;
  return 0;
}

ILayout*   Window::Layout()
{
  return m_pLayout;
}

Window* Window::Parent()
{
  return m_pParent;
}

void Window::SetSize(int w, int h)
{
  SetWindowPos(m_hwnd, 0, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER);  
}

void Window::GetSize(int* w, int* h)
{
  RECT r;

  GetWindowRect(m_hwnd, &r);

  if (w) *w = r.right - r.left;
  if (h) *h = r.bottom - r.top;
}

void Window::GetClientSize(int* w, int* h)
{
  RECT r;

  GetClientRect(m_hwnd, &r);

  if (w) *w = r.right;
  if (h) *h = r.bottom;
}

void Window::SetPosition(int x, int y)
{
  SetWindowPos(m_hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
}

void Window::GetPosition(int* x, int* y)
{
  RECT r;
  
  GetWindowRect(m_hwnd, &r);
  
  if (x) *x = r.left;
  if (y) *y = r.top;
}

void Window::Update()
{
  if (Layout())
  {
    Layout()->Update();
  }
}

HWND Window::Hwnd()
{
  return m_hwnd;
}


