// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string.h>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/private/video_destination_private.h"
#include "ppapi/cpp/private/video_frame_private.h"
#include "ppapi/cpp/private/video_source_private.h"
#include "ppapi/cpp/var.h"
#include "ppapi/utility/completion_callback_factory.h"

// When compiling natively on Windows, PostMessage can be #define-d to
// something else.
#ifdef PostMessage
#undef PostMessage
#endif

namespace {

// Helper functions
std::vector<std::string> SplitStringBySpace(const std::string& str) {
  std::istringstream buf(str);
  std::istream_iterator<std::string> begin(buf), end;
  std::vector<std::string> tokens(begin, end);
  return tokens;
}

// This object is the global object representing this plugin library as long
// as it is loaded.
class VEDemoModule : public pp::Module {
 public:
  VEDemoModule() : pp::Module() {}
  virtual ~VEDemoModule() {}

  virtual pp::Instance* CreateInstance(PP_Instance instance);
};

class VEDemoInstance : public pp::Instance {
 public:
  VEDemoInstance(PP_Instance instance, pp::Module* module);
  virtual ~VEDemoInstance();

  // pp::Instance implementation (see PPP_Instance).
  virtual void HandleMessage(const pp::Var& message_data);

 private:
  void DestinationOpenDone(int32_t result, const std::string& src_url);
  void SourceOpenDone(int32_t result);
  void GetFrameDone(int32_t result, pp::VideoFrame_Private video_frame);
  void KickoffEffect(int32_t result);
  pp::VideoSource_Private video_source_;
  pp::VideoDestination_Private video_destination_;
  bool effect_on_;
  pp::CompletionCallbackFactory<VEDemoInstance> factory_;
  pp::MessageLoop message_loop_;
};

VEDemoInstance::VEDemoInstance(PP_Instance instance, pp::Module* module)
    : pp::Instance(instance),
      video_source_(this),
      video_destination_(this),
      effect_on_(false),
      message_loop_(pp::MessageLoop::GetCurrent()) {
  factory_.Initialize(this);
}

VEDemoInstance::~VEDemoInstance() {
  video_source_.Close();
  video_destination_.Close();
}

void VEDemoInstance::HandleMessage(const pp::Var& message_data) {
  if (message_data.is_string()) {
    std::vector<std::string> messages;
    messages = SplitStringBySpace(message_data.AsString());
    if (messages.empty()) {
      PostMessage(pp::Var("Ignored empty message."));
      return;
    }
    if (messages[0] == "registerStream") {
      if (messages.size() < 3) {
        PostMessage(pp::Var("Got 'registerStream' with incorrect parameters."));
        return;
      }
      // Open destination stream for write.
      video_destination_.Open(
          messages[2],
          factory_.NewCallback(&VEDemoInstance::DestinationOpenDone,
                               messages[1]));
    } else if (messages[0] == "effectOn") {
      effect_on_ = true;
      PostMessage(pp::Var("Effect ON."));
    } else if (messages[0] == "effectOff") {
      effect_on_ = false;
      PostMessage(pp::Var("Effect OFF."));
    }
  }
}

void VEDemoInstance::DestinationOpenDone(int32_t result,
                                         const std::string& src_url) {
  if (result != PP_OK) {
    PostMessage(pp::Var("Failed to open destination stream."));
    return;
  }
  // Open source stream for read.
  video_source_.Open(src_url,
                     factory_.NewCallback(&VEDemoInstance::SourceOpenDone));
}

void VEDemoInstance::SourceOpenDone(int32_t result) {
  if (result != PP_OK) {
    PostMessage(pp::Var("Failed to open source stream."));
    return;
  }
  // Done with the stream register.
  PostMessage(pp::Var("DoneRegistering"));

  // Kick off the processing loop.
  message_loop_.PostWork(factory_.NewCallback(&VEDemoInstance::KickoffEffect));
}

void VEDemoInstance::GetFrameDone(int32_t result,
                                  pp::VideoFrame_Private video_frame) {
  if (result != PP_OK) {
    PostMessage(pp::Var("Failed to get frame."));
    return;
  }

  // Apply the effect to the received frame.
  if (effect_on_) {
    pp::ImageData image_data = video_frame.image_data();
    pp::Size size = image_data.size();
    std::vector<uint8_t> tmp_row(image_data.stride());
    uint8_t* image = static_cast<uint8_t*>(image_data.data());
    for (int i = 0; i < size.height() / 2; ++i) {
      uint8_t* top = image + i * image_data.stride();
      uint8_t* bottom = image + (size.height() - 1 - i) * image_data.stride();
      memcpy(&tmp_row[0], top, image_data.stride());
      memcpy(top, bottom, image_data.stride());
      memcpy(bottom, &tmp_row[0], image_data.stride());
    }
  }

  // Put frame back to destination stream
  video_destination_.PutFrame(video_frame);

  // Trigger for the next frame.
  message_loop_.PostWork(factory_.NewCallback(&VEDemoInstance::KickoffEffect));
}

void VEDemoInstance::KickoffEffect(int32_t /* result */) {
  // Get the frame from the source stream.
  video_source_.GetFrame(
      factory_.NewCallbackWithOutput<pp::VideoFrame_Private>(
          &VEDemoInstance::GetFrameDone));
}

pp::Instance* VEDemoModule::CreateInstance(PP_Instance instance) {
  return new VEDemoInstance(instance, this);
}

}  // anonymous namespace

namespace pp {
// Factory function for your specialization of the Module object.
Module* CreateModule() {
  return new VEDemoModule();
}
}  // namespace pp
