/*
-----------------------------------------------------------------------------
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 "embeddedWebNavigatorThread.h"
#include "embeddedWebNavigator.h"
#include "embeddedWebNavigatorManager.h"
#include "embeddedWebNavigatorClient.h"

namespace Scol
{
  namespace EmbeddedWebNavigator
  {

void WebNavigatorThread::LoadURL(unsigned long webNavigatorId, const std::string url, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);

      if(cefFrame.get())
        cefFrame->LoadURL(url);
    }
  }
}

void WebNavigatorThread::LoadFile(unsigned long webNavigatorId, const std::string file, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);

      if(cefFrame.get())
        cefFrame->LoadURL("file:///" + file);
    }
  }
}

void WebNavigatorThread::LoadHTML(unsigned long webNavigatorId, const std::string html, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);

      if(cefFrame.get())
        cefFrame->LoadStringA(html, "");
    }
  }
}

void WebNavigatorThread::CanGoBack(unsigned long webNavigatorId, bool* canGoBack, HANDLE synchro)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    (*canGoBack) = false;
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      (*canGoBack) = cefBrowser->CanGoBack();

    // Indicate to scol thread that the action is finished.
    SetEvent(synchro);
  }
}

void WebNavigatorThread::GoBack(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->GoBack();
  }
}

void WebNavigatorThread::CanGoForward(unsigned long webNavigatorId, bool* canGoForward, HANDLE synchro)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    (*canGoForward) = false;
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      (*canGoForward) = cefBrowser->CanGoForward();

    // Indicate to scol thread that the action is finished.
    SetEvent(synchro);
  }
}

void WebNavigatorThread::GoForward(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->GoForward();
  }
}

void WebNavigatorThread::Reload(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->Reload();
  }
}

void WebNavigatorThread::ReloadIgnoreCache(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->ReloadIgnoreCache();
  }
}

void WebNavigatorThread::StopLoad(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->StopLoad();
  }
}

void WebNavigatorThread::Find(unsigned long webNavigatorId, int identifier, const CefString searchText, bool forward, bool matchCase, bool findNext)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->Find(identifier, searchText, forward, matchCase, findNext);
  }
}

void WebNavigatorThread::StopFinding(unsigned long webNavigatorId, bool clearSelection)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->StopFinding(clearSelection);
  }
}

void WebNavigatorThread::GetZoomLevel(unsigned long webNavigatorId, double* zoomFactor, HANDLE synchro)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    (*zoomFactor) = 0.0;
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      (*zoomFactor) = cefBrowser->GetZoomLevel();

    // Indicate to scol thread that the zoom factor is filled.
    SetEvent(synchro);
  }
}

void WebNavigatorThread::SetZoomLevel(unsigned long webNavigatorId, double zoomLevel)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->SetZoomLevel(zoomLevel);
  }
}

void WebNavigatorThread::ClearHistory(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->ClearHistory();
  }
}

void WebNavigatorThread::ShowDevTools(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->ShowDevTools();
  }
}

void WebNavigatorThread::CloseDevTools(unsigned long webNavigatorId)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
      cefBrowser->CloseDevTools();
  }
}

void WebNavigatorThread::GetURL(unsigned long webNavigatorId, std::string* frameUrl, HANDLE synchro, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    frameUrl->clear();
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);

      if(cefFrame.get())
        frameUrl->append(cefFrame->GetURL());
    }

    // Indicate to scol thread that the url string is filled.
    SetEvent(synchro);
  }
}

void WebNavigatorThread::Undo(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Undo();
    }
  }
}

void WebNavigatorThread::Redo(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Redo();
    }
  }
}

void WebNavigatorThread::Cut(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Cut();
    }
  }
}

void WebNavigatorThread::Copy(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Copy();
    }
  }
}

void WebNavigatorThread::Paste(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Paste();
    }
  }
}

void WebNavigatorThread::Delete(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Delete();
    }
  }
}

void WebNavigatorThread::SelectAll(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->SelectAll();
    }
  }
}

void WebNavigatorThread::Print(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->Print();
    }
  }
}

void WebNavigatorThread::ViewSource(unsigned long webNavigatorId, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        cefFrame->ViewSource();
    }
  }
}

void WebNavigatorThread::GetSource(unsigned long webNavigatorId, std::string* frameSource, HANDLE synchro, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    frameSource->clear();
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);

      if(cefFrame.get())
        frameSource->append(cefFrame->GetSource());
    }

    // Indicate to scol thread that the source string is filled.
    SetEvent(synchro);
  }
}

void WebNavigatorThread::GetText(unsigned long webNavigatorId, std::string* frameText, HANDLE synchro, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    frameText->clear();
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);
      
      if(cefFrame.get())
        frameText->append(cefFrame->GetText());
    }

    // Indicate to scol thread that the source text is filled.
    SetEvent(synchro);
  }
}

void WebNavigatorThread::ExecuteJavaScript(unsigned long webNavigatorId, const std::string jsCode, const std::string scriptUrl, int startLine, const std::string frameName)
{
  WebNavigator* webNavigator = WebNavigatorManager::GetSingleton().GetNavigator(webNavigatorId);
  if(webNavigator != 0)
  {
    CefRefPtr<CefBrowser> cefBrowser = webNavigator->GetWebNavigatorClient()->GetBrowser();
    if(cefBrowser.get())
    {
      CefRefPtr<CefFrame> cefFrame;
      if(frameName == "")
        cefFrame = cefBrowser->GetMainFrame();
      else
        cefFrame = cefBrowser->GetFrame(frameName);

      if(cefFrame.get())
      {
        // Default url
        std::string javascriptUrl = scriptUrl;
        if(javascriptUrl == "")
          javascriptUrl = cefFrame->GetURL();

        // Execute JS
        cefFrame->ExecuteJavaScript(jsCode, scriptUrl, startLine);
      }
    }
  }
}

  }
}