/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "mvLobbyClient.h"

#include "mvLobby.h"
#include "mvView.h"
#include "vtkCallbackCommand.h"
#include "vtkEventData.h"
#include "vtkOpenVRModel.h"
#include "vtkOpenVRRenderer.h"
#include "vtkOpenVRRenderWindow.h"
#include "vtkOpenVRRenderWindowInteractor.h"
#include "vtkProperty.h"
#include "vtkTimerLog.h"
#include "zhelpers.hpp"


mvLobbyClient::mvLobbyClient()
{
  this->ScaleCallback = [this](void *) {
    return this->Lobby->GetPhysicalScale();
  };
}

void mvLobbyClient::HandleBroadcastMessage(
  std::string const &otherID,
  std::string const &type)
{
  if (type == "V")
  {
    // change view.
    std::string viewName = s_recv(this->Subscriber);
    std::cout << "Collab " << otherID << ", View: " <<
        viewName << " " << std::endl;
    // only want to change if it's from someone else.
    if (otherID != this->CollabID)
    {
      this->Lobby->ServerViewChanged(viewName);
    }
  }
  else if (type == "P")
  {
    // change pose.
    zmq::message_t update;
    int viewIndex = 0;
    double updateTranslation[3] = { 0 };
    double updateDirection[3] = { 0.0 };

    this->Subscriber.recv(&update);
    memcpy (&viewIndex, update.data(), sizeof(viewIndex));
    this->Subscriber.recv(&update);
    memcpy (&updateTranslation[0], update.data(), sizeof(updateTranslation));
    this->Subscriber.recv(&update);
    memcpy (&updateDirection[0], update.data(), sizeof(updateDirection));
    std::cout << "Collab " << otherID << ", Pose: " <<
        viewIndex << " " <<
        updateTranslation[0] << " " <<
        updateTranslation[1] << " " <<
        updateTranslation[2] << " " <<
        std::endl;

    // only want to change if it's from someone else.
    if (otherID != this->CollabID)
    {
      this->Lobby->ServerTourStopChanged(
        viewIndex, updateTranslation, updateDirection);
    }
  }
  else if (type == "J")
  {
    // Join message, send our list of views.
    std::string extraID = s_recv(this->Subscriber);

    // if we are idle, don't respond to join messages - send a join when
    // we are not idle anymore.
    if (this->AvatarIdle(this->CollabID))
    {
      return;
    }
    std::cout << "Collab " << otherID << ", Join" << std::endl;
    // send our list of views, even if we just joined.
    std::vector<std::string> viewNames;
    for (auto view: this->Lobby->Views)
    {
      viewNames.push_back(view->GetName());
      // re-activate all views, until view-lists come in.
      view->SetActive(true);
    }
    this->SendMessage("VL", viewNames);
    if (!this->CollabName.empty())
    {
      this->SendMessage("N", this->CollabName);
    }
  }
  else if (type == "VL")
  {
    std::string name = s_recv(this->Subscriber);
    std::vector<std::string> viewNames;
    while(!name.empty())
    {
      // std::cout << "View Name: " << name << std::endl;
      viewNames.push_back(name);
      name = s_recv(this->Subscriber);
    }
    if (otherID != this->CollabID)
    {
      // if a view is not in the list, de-activate
      for(auto view: this->Lobby->Views)
      {
        if (std::find(viewNames.begin(), viewNames.end(), view->GetName()) == viewNames.end())
        {
          std::cout << "  de-activate: " << view->GetName() << std::endl;
          view->SetActive(false);
        }
      }
    }
  }
  else
  {
    this->mvCollaborationClient::HandleBroadcastMessage(otherID, type);
  }
}
