// Copyright 2015 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 "base/bind.h"
#include "base/macros.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/common/binding_set.h"
#include "mojo/gpu/gl_texture.h"
#include "mojo/gpu/texture_cache.h"
#include "mojo/gpu/texture_uploader.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/services/nfc/interfaces/nfc.mojom.h"
#include "mojo/services/view_manager/cpp/view_manager_client_factory.h"
#include "mojo/services/view_manager/cpp/view_manager_delegate.h"
#include "mojo/services/view_manager/cpp/view_observer.h"
#include "mojo/skia/ganesh_context.h"
#include "mojo/skia/ganesh_surface.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"

namespace examples {

mojo::Size ToSize(const mojo::Rect& rect) {
  mojo::Size size;
  size.width = rect.width;
  size.height = rect.height;
  return size;
}

struct CircleData {
  gfx::Point point;
  SkColor color;
};

class ViewTextureUploader {
 public:
  ViewTextureUploader(base::WeakPtr<mojo::GLContext> gl_context,
                      mojo::SurfacePtr* surface,
                      mojo::View* view,
                      mojo::TextureCache* texture_cache,
                      base::Callback<void(SkCanvas*)> draw_callback)
      : gl_context_(gl_context),
        surface_(surface),
        texture_cache_(texture_cache),
        view_(view),
        draw_callback_(draw_callback) {
    gr_context_.reset(new mojo::GaneshContext(gl_context_));
    submit_frame_callback_ = base::Bind(&ViewTextureUploader::OnFrameComplete,
                                        base::Unretained(this));
  }

  void Draw(uint32_t surface_id) {
    mojo::GaneshContext::Scope scope(gr_context_.get());

    mojo::Size view_size = ToSize(view_->bounds());
    if (view_size.width <= 0 || view_size.height <= 0) {
      return;
    }
    scoped_ptr<mojo::TextureCache::TextureInfo> texture_info(
        texture_cache_->GetTexture(view_size).Pass());
    mojo::GaneshSurface ganesh_surface(gr_context_.get(),
                                       texture_info->TakeTexture().Pass());

    gr_context_->gr()->resetContext(kTextureBinding_GrGLBackendState);
    SkCanvas* canvas = ganesh_surface.canvas();
    draw_callback_.Run(canvas);

    scoped_ptr<mojo::GLTexture> surface_texture(
        ganesh_surface.TakeTexture().Pass());
    mojo::FramePtr frame = mojo::TextureUploader::GetUploadFrame(
        gl_context_, texture_info->resource_id(), surface_texture);
    texture_cache_->NotifyPendingResourceReturn(texture_info->resource_id(),
                                                surface_texture.Pass());
    (*surface_)->SubmitFrame(surface_id, frame.Pass(), submit_frame_callback_);
  }

  void OnFrameComplete() {}

 private:
  base::WeakPtr<mojo::GLContext> gl_context_;
  scoped_ptr<mojo::GaneshContext> gr_context_;
  mojo::SurfacePtr* surface_;
  mojo::TextureCache* texture_cache_;
  mojo::View* view_;
  base::Callback<void(SkCanvas*)> draw_callback_;
  base::Closure submit_frame_callback_;

  DISALLOW_COPY_AND_ASSIGN(ViewTextureUploader);
};

class NfcSenderDelegate : public mojo::ApplicationDelegate,
                          public mojo::ViewManagerDelegate,
                          public nfc::NfcReceiver,
                          public mojo::ViewObserver,
                          public mojo::InterfaceFactory<nfc::NfcReceiver> {
 public:
  NfcSenderDelegate()
      : app_(nullptr),
        shell_(nullptr),
        view_(nullptr),
        nfc_receiver_binding_(this),
        surface_id_(1u),
        transmission_pending_(false) {}

  ~NfcSenderDelegate() override {}

  // mojo::ApplicationDelegate implementation.
  void Initialize(mojo::ApplicationImpl* app) override {
    app_ = app;
    shell_ = app->shell();
    view_manager_client_factory_.reset(
        new mojo::ViewManagerClientFactory(app->shell(), this));

    ConnectToNfc();
    TransmitOnNextConnection();
  }

  void ConnectToNfc() {
    app_->ConnectToService("mojo:nfc", &nfc_);
    nfc_.set_connection_error_handler(base::Bind(
        &NfcSenderDelegate::OnConnectionError, base::Unretained(this)));

    nfc_->Register();
  }

  bool ConfigureIncomingConnection(
      mojo::ApplicationConnection* connection) override {
    connection->AddService(view_manager_client_factory_.get());
    connection->AddService(this);
    return true;
  }

  // mojo::InterfaceFactory<nfc::NfcReceiver> implementation.
  void Create(mojo::ApplicationConnection* connection,
              mojo::InterfaceRequest<nfc::NfcReceiver> request) override {
    nfc_receiver_bindings_.AddBinding(this, request.Pass());
  }

  // mojo::ViewManagerDelegate
  void OnEmbed(mojo::View* root,
               mojo::InterfaceRequest<mojo::ServiceProvider> services,
               mojo::ServiceProviderPtr exposed_services) override {
    view_ = root;
    view_->AddObserver(this);

    mojo::ServiceProviderPtr surfaces_service_provider;
    shell_->ConnectToApplication("mojo:surfaces_service",
                                 mojo::GetProxy(&surfaces_service_provider),
                                 nullptr);
    mojo::ConnectToService(surfaces_service_provider.get(), &surface_);
    gl_context_ = mojo::GLContext::Create(shell_);

    surface_->CreateSurface(surface_id_);
    surface_->GetIdNamespace(
        base::Bind(&NfcSenderDelegate::SetIdNamespace, base::Unretained(this)));

    mojo::ResourceReturnerPtr resource_returner;
    texture_cache_.reset(
        new mojo::TextureCache(gl_context_, &resource_returner));
    texture_uploader_.reset(new ViewTextureUploader(
        gl_context_, &surface_, view_, texture_cache_.get(),
        base::Bind(&NfcSenderDelegate::DrawCircles, base::Unretained(this))));
    surface_->SetResourceReturner(resource_returner.Pass());
    UpdateView();
  }

  void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override {}

  void OnConnectionError() {
    transmission_pending_ = false;
    ConnectToNfc();
  }

  void SetIdNamespace(uint32_t id_namespace) {
    auto view_surface_id = mojo::SurfaceId::New();
    view_surface_id->id_namespace = id_namespace;
    view_surface_id->local = surface_id_;
    view_->SetSurfaceId(view_surface_id.Pass());
  }

  void UpdateView() {
    if (texture_uploader_) {
      texture_uploader_->Draw(surface_id_);
    }
  }

  void DrawCircles(SkCanvas* canvas) {
    canvas->clear(SK_ColorGREEN);
    for (const auto& circle : circles_) {
      SkPaint paint;
      paint.setColor(circle.color);
      paint.setFlags(SkPaint::kAntiAlias_Flag);
      canvas->drawCircle(circle.point.x(), circle.point.y(), 50, paint);
    }

    canvas->flush();
  }

  // mojo::ViewObserver
  void OnViewInputEvent(mojo::View* view,
                        const mojo::EventPtr& event) override {
    if (event->action == mojo::EventType::POINTER_DOWN ||
        event->action == mojo::EventType::POINTER_MOVE) {
      if (event->pointer_data) {
        gfx::Point point(event->pointer_data->x, event->pointer_data->y);

        int r = rand() % 256;
        int g = rand() % 256;
        int b = rand() % 256;
        CircleData circle_data;
        circle_data.point = point;
        circle_data.color = SkColorSetARGB(0xFF, r, g, b);
        circles_.push_back(circle_data);
        while (circles_.size() > 100) {
          circles_.pop_front();
        }
        UpdateView();
        TransmitOnNextConnection();
      }
    }
  }

  void OnViewBoundsChanged(mojo::View* view,
                           const mojo::Rect& old_bounds,
                           const mojo::Rect& new_bounds) override {
    UpdateView();
  }

  // nfc::NfcReceiver implementation.
  void OnReceivedNfcData(nfc::NfcDataPtr nfc_data) override {
    if (nfc_data->data.is_null()) {
      return;
    }
    circles_.clear();

    for (size_t offset = 0; (offset + 12) <= nfc_data->data.size();
         offset += 12) {
      int32_t x;
      memcpy(&x, &nfc_data->data.front() + offset, 4);

      int32_t y;
      memcpy(&y, &nfc_data->data.front() + offset + 4, 4);

      CircleData circle_data;
      circle_data.point = gfx::Point(x, y);
      circle_data.color = SkColorSetARGB(
          nfc_data->data.at(offset + 8), nfc_data->data.at(offset + 9),
          nfc_data->data.at(offset + 10), nfc_data->data.at(offset + 11));

      circles_.push_back(circle_data);
    }
    UpdateView();
    TransmitOnNextConnection();
  }

  void TransmitOnNextConnection() {
    if (transmission_pending_) {
      nfc_transmission_->Cancel();
    }
    transmission_pending_ = true;
    nfc_->TransmitOnNextConnection(
        CreateNfcData().Pass(), GetProxy(&nfc_transmission_),
        base::Bind(&NfcSenderDelegate::TransmitResult, base::Unretained(this)));
  }

  void TransmitResult(bool success) {
    transmission_pending_ = false;
    if (success) {
      TransmitOnNextConnection();
    }
  }

  nfc::NfcDataPtr CreateNfcData() {
    nfc::NfcDataPtr nfc_data = nfc::NfcData::New();
    nfc_data->data = mojo::Array<uint8>::New(12 * circles_.size());
    size_t offset = 0;
    for (const auto& circle : circles_) {
      int32_t x = circle.point.x();
      memcpy(&nfc_data->data.front() + offset, &x, 4);

      int32_t y = circle.point.y();
      memcpy(&nfc_data->data.front() + offset + 4, &y, 4);

      nfc_data->data.at(offset + 8) = SkColorGetA(circle.color);
      nfc_data->data.at(offset + 9) = SkColorGetR(circle.color);
      nfc_data->data.at(offset + 10) = SkColorGetG(circle.color);
      nfc_data->data.at(offset + 11) = SkColorGetB(circle.color);
      offset += 12;
    }
    return nfc_data;
  }

 private:
  mojo::ApplicationImpl* app_;
  mojo::Shell* shell_;
  scoped_ptr<mojo::ViewManagerClientFactory> view_manager_client_factory_;
  mojo::View* view_;
  nfc::NfcPtr nfc_;
  nfc::NfcTransmissionPtr nfc_transmission_;
  mojo::Binding<nfc::NfcReceiver> nfc_receiver_binding_;
  std::deque<CircleData> circles_;
  uint32_t surface_id_;
  base::WeakPtr<mojo::GLContext> gl_context_;
  mojo::SurfacePtr surface_;
  scoped_ptr<mojo::TextureCache> texture_cache_;
  scoped_ptr<ViewTextureUploader> texture_uploader_;
  bool transmission_pending_;
  mojo::BindingSet<nfc::NfcReceiver> nfc_receiver_bindings_;

  DISALLOW_COPY_AND_ASSIGN(NfcSenderDelegate);
};

}  // namespace examples

MojoResult MojoMain(MojoHandle application_request) {
  mojo::ApplicationRunnerChromium runner(new examples::NfcSenderDelegate);
  return runner.Run(application_request);
}
