/*
-----------------------------------------------------------------------------
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
-----------------------------------------------------------------------------
*/

#ifndef _SCOL_EMBEDDED_WEB_NAVIGATOR_
#define _SCOL_EMBEDDED_WEB_NAVIGATOR_

#include "embeddedWebNavigatorClient.h"
#include "embeddedWebNavigatorCriticalSection.h"

namespace Scol
{
  namespace EmbeddedWebNavigator
  {

class WebNavigator
{
public:
protected:
private:
  bool inputEnable;
  const unsigned long uniqueId;
  const ScolWindowHandle scolMainWindowHandle;
  const ScolWindowHandle parentWindowHandle;
  const bool offscreen;
  CefRefPtr<WebNavigatorClient> webNavigatorClient;
  std::pair<int, int> actualSize;
  std::pair<int, int> actualPosition;
  HANDLE synchroEventCanGoBack;
  HANDLE synchroEventCanGoForward;
  HANDLE synchroEventGetZoomLevel;
  HANDLE synchroEventGetSource;
  HANDLE synchroEventGetURL;
  HANDLE synchroEventGetText;
  CefRefPtr<WebNavigatorCriticalSection> offscreenBufferCriticalSection;

public:
  /*!
  Constructor, creates a new web navigator.
  */
  WebNavigator(const unsigned long navigatorUniqueId, const ScolWindowHandle& scolMainWindow, const ScolWindowHandle& parentWindowHandleInstance, int xPosition, int yPosition, int width, int height, std::string url);

  /*!
  Constructor, creates a new web navigator that will render it's content "offscreen".
  */
  WebNavigator(const unsigned long navigatorUniqueId, const ScolWindowHandle& scolMainWindow,const ScolWindowHandle& parentWindowHandleInstance, int width, int height, std::string url, bool transparency = false);

  /*!
  Destructor.
  */
  ~WebNavigator();

  /*!
  */
  unsigned long GetUniqueId();

  /*!
  */
  ScolWindowHandle GetParentWindowHandle();

  /*!
  */
  CefRefPtr<WebNavigatorClient>& GetWebNavigatorClient();

  /*!
  Loads an URL.
  @param url The url to load
  @param frameName The target frame, main frame will be used if empty.
  */
  void LoadURL(const std::string& url, const std::string& frameName="");

  /*!
  Loads a local file.
  @param url The file to load
  @param frameName The target frame, main frame will be used if empty.
  @note	The file should reside in a scol partition.
  */
  void LoadFile(const std::string& file, const std::string& frameName="");

  /*
  Loads a string of HTML.
  @param url The html text to load
  @param frameName The target frame, main frame will be used if empty.
  @note	Relative URLs will be resolved using the base directory.
  */
  void LoadHTML(const std::string& html, const std::string& frameName="");
  
  /*!
  Returns the URL currently loaded in a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  std::string GetURL(const std::string& frameName="");

  /*!
  Execute undo on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Undo(const std::string& frameName="");
  
  /*!
  Execute redo on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Redo(const std::string& frameName="");
  
  /*!
  Execute cut on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Cut(const std::string& frameName="");
  
  /*!
  Execute copy on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Copy(const std::string& frameName="");
  
  /*!
  Execute paste on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Paste(const std::string& frameName="");
  
  /*!
  Execute delete on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Delete(const std::string& frameName="");
  
  /*!
  Execute select all on a frame.
  @param frameName The target frame, main frame will be used if empty.
  */
  void SelectAll(const std::string& frameName="");
  
  /*!
  Execute printing on a frame. The user will be prompted with the print dialog appropriate to the operating system.
  @param frameName The target frame, main frame will be used if empty.
  */
  void Print(const std::string& frameName="");
  
  /*!
  Save a frame's HTML source to a temporary file and open it in the default text viewing application.
  @param frameName The target frame, main frame will be used if empty.
  */
  void ViewSource(const std::string& frameName="");

  /*!
  Returns a frame's HTML source as a string.
  @param frameName The target frame, main frame will be used if empty.
  */
  std::string GetSource(const std::string& frameName="");

  /*!
  Returns a frame's display text as a string.
  @param frameName The target frame, main frame will be used if empty.
  */
  std::string GetText(const std::string& frameName="");

  /*!
  Execute a string of JavaScript code in this frame.
  The |script_url| parameter is the URL where the script in question can be found, if any.
  The renderer may request this URL to show the developer the source of the error.
  The |start_line| parameter is the base line number to use for error reporting.
  @param frameName The target frame, main frame will be used if empty.
  */
  void ExecuteJavaScript(const std::string& jsCode, const std::string& scriptUrl, int startLine, const std::string& frameName="");

  /*!
  Returns true if the browser can navigate backwards.
  */
  bool CanGoBack();
  
  /*!
  Navigate backwards.
  */
  void GoBack();
  
  /*!
  Returns true if the browser can navigate forwards.
  */
  bool CanGoForward();
  
  /*!
  Navigate forwards.
  */
  void GoForward();

  /*!
  Reload the current page.
  */
  void Reload();

  /*!
  Reload the current page ignoring any cached data.
  */
  void ReloadIgnoreCache();
  
  /*!
  Stop loading the page.
  */
  void StopLoad();

  /*!
  Search for text in the current page.
  @param identifier Can be used to have multiple searches running simultaniously (search index). 
  @param searchText The searched text
  @param forward Indicates whether to search forward or backward within the page.
  @param matchCase Indicates whether the search should be case-sensitive.
  @param findNext Indicates whether this is the first request or a follow-up.
  */
  void Find(int identifier, const CefString& searchText, bool forward, bool matchCase, bool findNext);

  /*!
  Cancel all searches that are currently going on.
  */
  void StopFinding(bool clearSelection);

  /*!
  Get the zoom level.
  */
  double GetZoomLevel();

  /*!
  Change the zoom level to the specified value.
  */
  void SetZoomLevel(double zoomLevel);
  
  /*!
  Clear the back/forward browsing history.
  */
  void ClearHistory();

  /*!
  Open developer tools window.
  */
  void ShowDevTools();

  /*!
  Close the developer tools window if one exists for this browser instance.
  */
  void CloseDevTools();

  /*!
  */
  std::pair<int, int> GetSize();

  /*!
  */
  void SetSize(std::pair<int, int> newSize);

  /*!
  */
  std::pair<int, int> GetPosition();

  /*!
  */
  void SetPosition(std::pair<int, int> newPosition);

  /*!
  */
  bool IsOffscreen() const;

  /*!
  Send a key event to the web navigator
  */
  void InjectKeyMsg(int msg, int lparam, int wparam);
  
  /*!
  Send a key event to the web navigator
  */
  void InjectKey(int scanCode, int keydata, bool down);

  /*!
  Send a char to the web navigatoc
  */
  void InjectChar(int scanCode, int keydata);

  /*!
  Send a mouse click event to the browser. The |x| and |y| coordinates are relative to the upper-left corner of the view.
  */
  void InjectMouseClick(int x, int y, int buttonType, bool mouseUp, int clickCount);

  /*!
  Send a mouse move event to the browser. The |x| and |y| coordinates are relative to the upper-left corner of the view.
  */
  void InjectMouseMove(int x, int y, bool mouseLeave);

  /*!
  Send a mouse wheel event to the browser. The |x| and |y| coordinates are relative to the upper-left corner of the view.
  */
  void InjectMouseWheel(int x, int y, int delta);

  /*!
  Send a focus event to the browser.
  */
  void InjectFocus(bool setFocus);

  /*!
  Send a capture lost event to the browser.
  */
  //void InjectCaptureLostEvent();

  /*!
  */
  void ResetInput();
protected:
private:
  /*!
  Forbidden constructor (private).
  */
  WebNavigator();

  /*!
  Common code for all valids constructors.
  */
  void CommonConstructorSequence(std::pair<int, int> newWebNavigatorPosition, std::pair<int, int> newWebNavigatorSize, std::string url, bool transparency = false);

  /*!
  */
  void ApplyPositionAndSize();

  /*!
  Utility function to convert scol mouse button to cef format.
  */
  CefBrowser::MouseButtonType ConvertMouseButton(int scolButton);
};

  }
}

#endif
