#include "stdafx.h"
#define BOOST_ASSIGN_MAX_PARAMS 7
#include <boost/assign.hpp>
#include <boost/assign/ptr_list_of.hpp>
#include <boost/assign/ptr_list_inserter.hpp>
#include <boost/foreach.hpp>

#if _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

#include "sf_windows.h"
#include "exception.h"



#define THROW_IFERR(hres) \
  if (FAILED(hres)) { throw sf::win32_error_exception(hres); }

#ifndef HINST_THISCOMPONENT
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
#endif

namespace sf 
{
  LRESULT base_win32_window::window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
  {

    LRESULT 結果 = 0;
    switch (message)
    {
    case WM_CREATE:
      {
        // TODO:
        //create_device();
        break;
      }
    case WM_SIZE:
      {
        //if (render_target_)
        //{
        //	D2D1_SIZE_U size;
        //	size.width = lParam & 0xFFFF;
        //	size.height = (lParam >> 16) & 0xFFFF; ;

        //	// Note: This method can fail, but it's okay to ignore the
        //	// error here -- it will be repeated on the next call to
        //	// EndDraw.
        //	//render_target_->Resize(size);
        //}
      }
    case WM_PAINT:
      {
        //create_device();

        paint_struct begin_paint(hwnd);

        //if (!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED))
        //{
        //	// Retrieve the size of the render target.
        //	D2D1_SIZE_F renderTargetSize = render_target_->GetSize();
        //	try {
        //		//render_target_->BeginDraw();
        //		base_->on_render();
        //		//THROW_IFERR(render_target_->EndDraw());
        //	} catch (sf::win32_error_exception& e )
        //	{
        //		if(e.hresult() == D2DERR_RECREATE_TARGET)
        //		{
        //			discard_device();
        //		} else {
        //			throw;
        //		}
        //	}
        //}
        return FALSE;
      }
    case WM_DISPLAYCHANGE:
      {
        ::InvalidateRect(hwnd, NULL, FALSE);
      }
    case WM_ERASEBKGND:
      {
        return FALSE;
      }
    case WM_MOUSEMOVE:
      {
        //					on_mouse_move(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),wParam); 
      }
    case WM_LBUTTONDOWN:
      {
      }
    }
    return ::DefWindowProcW(hwnd,message,wParam,lParam);
  };
  
  void base_win32_window::register_class (
    const wchar_t * menu_name,
    uint32_t        style ,
    boost::int32_t     cbClsExtra,
    HICON       hIcon ,
    HCURSOR     hCursor,
    HBRUSH      hbrBackground ,
    HICON       hIconSm
    )		
  {
    wnd_class_.reset(new sf::window_class_ex(menu_name,name_,HINST_THISCOMPONENT,thunk_proc_,style,cbClsExtra,hIcon,hCursor,hbrBackground,hIconSm));
  }

  /** デフォルト設定 */
  void base_win32_window::register_class()
  {
    wnd_class_.reset(new sf::window_class_ex(0,name_,HINST_THISCOMPONENT,thunk_proc_));
  }

  void base_win32_window::create_window()
  {
    // Create the application window.
    //
    // Because the CreateWindow function takes its size in pixels, we
    // obtain the system DPI and use it to scale the window size.
    //FLOAT dpiX, dpiY;
    //factory_->GetDesktopDpi(&dpiX, &dpiY);


    // Windowを作成する
    CreateWindow(
      name_.c_str(),
      title_.c_str(),
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      static_cast<uint32_t>(dpi_.scale_x(width_)),
      static_cast<uint32_t>(dpi_.scale_y(height_)),
      NULL,
      NULL,
      HINST_THISCOMPONENT,
      this
      );
    ::GetWindowPlacement(hwnd_,&wp_);
  }

  //void base_win32_window::show() 
  //{
  //  //HRESULT hr = S_OK;
  //  //BOOL enable;
  //  //DwmIsCompositionEnabled (&enable);
  //  //if(enable){
  //  //   //Create and populate the BlurBehind structre
  //  //   DWM_BLURBEHIND bb = {0};
  //  //   //Enable Blur Behind and Blur Region;
  //  //   bb.dwFlags = DWM_BB_ENABLE;
  //  //   bb.fEnable = true;
  //  //   bb.hRgnBlur = NULL;

  //  //   //Enable Blur Behind
  //  //   hr = DwmEnableBlurBehindWindow(hwnd_, &bb);
  //  //}
  //  ::ShowWindow(hwnd_,SW_SHOW);
  //  ::GetWindowPlacement(&wp_);
  //}


  void base_win32_window::update() {::UpdateWindow(hwnd_);}

  base_win32_window::~base_win32_window()
  {

  }

  base_win32_window::base_win32_window(const std::wstring& title,const std::wstring& name,bool fit_to_display,float width,float height)
    : title_(title),name_(name),fit_to_display_(fit_to_display),width_(width),height_(height),thunk_(this,base_win32_window::WndProc),hwnd_(0)
  {
    memset(&wp_,0,sizeof(wp_));
    wp_.length = sizeof(WINDOWPLACEMENT);
    thunk_proc_ = (WNDPROC)thunk_.getCode();
    //create_device_independent_resources();
  }

  //ID2D1FactoryPtr base_win32_window::factory() { return impl_->factory();};
  //ID2D1HwndRenderTargetPtr base_win32_window::render_target() { return impl_->render_target();};
  //IDWriteFactoryPtr base_win32_window::write_factory() {return impl_->write_factory();};
}

