/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com

Copyright (c) 2011 I-maginer

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt
-----------------------------------------------------------------------------
*/

#include "embeddedWebNavigatorClient.h"
#include "embeddedWebNavigator.h"
#include "embeddedWebNavigatorDisplayHandler.h"
#include "embeddedWebNavigatorDragHandler.h"
#include "embeddedWebNavigatorFindHandler.h"
#include "embeddedWebNavigatorFocusHandler.h"
#include "embeddedWebNavigatorJSDialogHandler.h"
#include "embeddedWebNavigatorKeyboardHandler.h"
#include "embeddedWebNavigatorLifeSpanHandler.h"
#include "embeddedWebNavigatorLoadHandler.h"
#include "embeddedWebNavigatorMenuHandler.h"
#include "embeddedWebNavigatorPrintHandler.h"
#include "embeddedWebNavigatorRenderHandler.h"
#include "embeddedWebNavigatorRequestHandler.h"
#include "embeddedWebNavigatorV8ContextHandler.h"

namespace Scol
{
  namespace EmbeddedWebNavigator
  {

WebNavigatorClient::WebNavigatorClient(WebNavigator* parentWebNavigatorInstance, const ScolWindowHandle& scolMainWindow, bool offscreen, CefRefPtr<WebNavigatorCriticalSection>& offscreenBufferCriticalSectionInstance) : parentWebNavigator(parentWebNavigatorInstance),
                                                                                                                                                                                                                          scolMainWindowHandle(scolMainWindow),
                                                                                                                                                                                                                          offscreenBufferCriticalSection(offscreenBufferCriticalSectionInstance)
{
  displayHandler   = new WebNavigatorDisplayHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  dragHandler      = new WebNavigatorDragHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  findHandler      = new WebNavigatorFindHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  focusHandler     = new WebNavigatorFocusHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  jsDialogHandler  = new WebNavigatorJSDialogHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  keyboardHandler  = new WebNavigatorKeyboardHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  lifeSpanHandler  = new WebNavigatorLifeSpanHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  loadHandler      = new WebNavigatorLoadHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  menuHandler      = new WebNavigatorMenuHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  printHandler     = new WebNavigatorPrintHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  renderHandler    = new WebNavigatorRenderHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle, offscreen, offscreenBufferCriticalSection);
  requestHandler   = new WebNavigatorRequestHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);
  v8ContextHandler = new WebNavigatorV8ContextHandler(CefRefPtr<WebNavigatorClient>(const_cast <WebNavigatorClient*> (this)), scolMainWindowHandle);

  cefBrowser = 0;
}

WebNavigatorClient::WebNavigatorClient() : parentWebNavigator(0),
                                           scolMainWindowHandle(0)
{
  // Forbiden ctor.
}

WebNavigatorClient::~WebNavigatorClient()
{
  _Cleanup();
}

bool WebNavigatorClient::BlitOffscreenBitmap(unsigned char* dest, int destWidth, int destHeight, int destBytesPerPixel, int destBitsPerLine)
{
  bool result = false;
  offscreenBufferCriticalSection->Lock();
 
  if ((renderHandler->GetOffscreenBufferWidth() == destWidth) && (renderHandler->GetOffscreenBufferHeight() == destHeight))
  {
    // Get source buffer
    unsigned char* buffer = renderHandler->GetOffscreenBuffer();

    int sbpl = destWidth * 4;
    for (long y=0; y<destHeight; y++)
    {
      for (long x=0; x<destWidth; x++)
      {
        unsigned long srcByte = (x * 4) + (sbpl * y);
        unsigned long destByte = (x * destBytesPerPixel) + (destBitsPerLine * y);

        dest[destByte]     = buffer[srcByte];
        dest[destByte + 1] = buffer[srcByte + 1];
        dest[destByte + 2] = buffer[srcByte + 2];
      }
    }
    result = true;
  }

  offscreenBufferCriticalSection->Unlock();
  return result;
}

bool WebNavigatorClient::BlitOffscreenAlphaBitmap(unsigned char* destColor, unsigned char* destAlpha, int destWidth, int destHeight, int destColorBytesPerPixel, int destColorBitsPerLine)
{
  bool result = false;
  offscreenBufferCriticalSection->Lock();
 
  if ((renderHandler->GetOffscreenBufferWidth() == destWidth) && (renderHandler->GetOffscreenBufferHeight() == destHeight))
  {
    // Get source buffer
    unsigned char* buffer = renderHandler->GetOffscreenBuffer();

    int sbpl = destWidth * 4;
    unsigned long srcByte = 0;
    unsigned long destByte = 0;
    unsigned long alphaLineOffset = 0;
    for (long y=0; y<destHeight; y++)
    {
      alphaLineOffset = (y*destWidth);
      for (long x=0; x<destWidth; x++)
      {
        srcByte = (x * 4) + (sbpl * y);
        destByte = (x * destColorBytesPerPixel) + (destColorBitsPerLine * y);

        destColor[destByte]            = buffer[srcByte];
        destColor[destByte + 1]        = buffer[srcByte + 1];
        destColor[destByte + 2]        = buffer[srcByte + 2];
        destAlpha[x + alphaLineOffset] = buffer[srcByte + 3];
      }
    }
    result = true;
  }

  offscreenBufferCriticalSection->Unlock();
  return result;
}

void WebNavigatorClient::_Cleanup()
{
  if(cefBrowser)
  {
    if(!parentWebNavigator->IsOffscreen())
      cefBrowser->ParentWindowWillClose();

    cefBrowser->CloseBrowser();
    cefBrowser = 0;
  }
}

CefRefPtr<CefLifeSpanHandler> WebNavigatorClient::GetLifeSpanHandler()
{
  return static_cast <CefRefPtr<CefLifeSpanHandler> > (lifeSpanHandler);
}

CefRefPtr<CefLoadHandler> WebNavigatorClient::GetLoadHandler()
{
  return static_cast <CefRefPtr<CefLoadHandler> > (loadHandler);
}

CefRefPtr<CefRequestHandler> WebNavigatorClient::GetRequestHandler()
{
  return static_cast <CefRefPtr<CefRequestHandler> > (requestHandler);
}

CefRefPtr<CefDisplayHandler> WebNavigatorClient::GetDisplayHandler()
{
  return static_cast <CefRefPtr<CefDisplayHandler> > (displayHandler);
}

CefRefPtr<CefFocusHandler> WebNavigatorClient::GetFocusHandler()
{
  return static_cast <CefRefPtr<CefFocusHandler> > (focusHandler);
}

CefRefPtr<CefKeyboardHandler> WebNavigatorClient::GetKeyboardHandler()
{
  return static_cast <CefRefPtr<CefKeyboardHandler> > (keyboardHandler);
}

CefRefPtr<CefMenuHandler> WebNavigatorClient::GetMenuHandler()
{
  return static_cast <CefRefPtr<CefMenuHandler> > (menuHandler);
}

CefRefPtr<CefPrintHandler> WebNavigatorClient::GetPrintHandler()
{
  return static_cast <CefRefPtr<CefPrintHandler> > (printHandler);
}

CefRefPtr<CefFindHandler> WebNavigatorClient::GetFindHandler()
{
  return static_cast <CefRefPtr<CefFindHandler> > (findHandler);
}

CefRefPtr<CefJSDialogHandler> WebNavigatorClient::GetJSDialogHandler()
{
  return static_cast <CefRefPtr<CefJSDialogHandler> > (jsDialogHandler);
}

CefRefPtr<CefV8ContextHandler> WebNavigatorClient::GetV8ContextHandler()
{
  return static_cast <CefRefPtr<CefV8ContextHandler> > (v8ContextHandler);
}

CefRefPtr<CefRenderHandler> WebNavigatorClient::GetRenderHandler()
{
  return static_cast <CefRefPtr<CefRenderHandler> > (renderHandler);
}

CefRefPtr<CefDragHandler> WebNavigatorClient::GetDragHandler()
{
  return static_cast <CefRefPtr<CefDragHandler> > (dragHandler);
}

CefRefPtr<CefBrowser> WebNavigatorClient::GetBrowser()
{
  return cefBrowser;
}

WebNavigator* WebNavigatorClient::GetParentWebNavigator()
{
  return parentWebNavigator;
}

void WebNavigatorClient::_NotifyBrowserCreated(CefRefPtr<CefBrowser> browser)
{
  assert(cefBrowser == 0);
  cefBrowser = browser;

  // Set initial position and size
  parentWebNavigator->SetPosition(parentWebNavigator->GetPosition());
  parentWebNavigator->SetSize(parentWebNavigator->GetSize());
}

void WebNavigatorClient::_NotifyBrowserDestroyed(CefRefPtr<CefBrowser> browser)
{
  displayHandler = 0;
  dragHandler = 0;
  findHandler = 0;
  focusHandler = 0;
  v8ContextHandler = 0;
  jsDialogHandler = 0;
  keyboardHandler = 0;
  lifeSpanHandler = 0;
  loadHandler = 0;
  menuHandler = 0;
  printHandler = 0;
  renderHandler = 0;
  requestHandler = 0;
}

  }
}