// 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 <math.h>

#include "services/keyboard_native/view_observer_delegate.h"

#include "base/bind.h"
#include "base/sys_info.h"
#include "mojo/gpu/gl_texture.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/skia/ganesh_surface.h"
#include "services/keyboard_native/clip_animation.h"
#include "services/keyboard_native/keyboard_service_impl.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/vector2d.h"

namespace keyboard {

static const base::TimeDelta kAnimationDurationMs =
    base::TimeDelta::FromMilliseconds(1000);

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

ViewObserverDelegate::ViewObserverDelegate()
    : keyboard_service_impl_(nullptr),
      view_(nullptr),
      id_namespace_(0u),
      surface_id_(1u),
      key_layout_(),
      needs_draw_(false),
      frame_pending_(false),
      floating_key_height_(0.0f),
      floating_key_width_(0.0f),
      weak_factory_(this) {
  key_layout_.SetTextCallback(
      base::Bind(&ViewObserverDelegate::OnText, weak_factory_.GetWeakPtr()));
  key_layout_.SetDeleteCallback(
      base::Bind(&ViewObserverDelegate::OnDelete, weak_factory_.GetWeakPtr()));
  submit_frame_callback_ = base::Bind(&ViewObserverDelegate::OnFrameComplete,
                                      weak_factory_.GetWeakPtr());
}

ViewObserverDelegate::~ViewObserverDelegate() {
}

void ViewObserverDelegate::SetKeyboardServiceImpl(
    KeyboardServiceImpl* keyboard_service_impl) {
  keyboard_service_impl_ = keyboard_service_impl;
}

void ViewObserverDelegate::SetIdNamespace(uint32_t id_namespace) {
  id_namespace_ = id_namespace;
  UpdateSurfaceIds();
}

void ViewObserverDelegate::UpdateSurfaceIds() {
  auto surface_id = mojo::SurfaceId::New();
  surface_id->id_namespace = id_namespace_;
  surface_id->local = surface_id_;
  view_->SetSurfaceId(surface_id.Pass());
}

void ViewObserverDelegate::OnViewCreated(mojo::View* view, mojo::Shell* shell) {
  if (view_ != nullptr) {
    view_->RemoveObserver(this);
  }
  view_ = view;
  view_->AddObserver(this);
  gl_context_ = mojo::GLContext::Create(shell);
  mojo::ResourceReturnerPtr resource_returner;
  texture_cache_.reset(new mojo::TextureCache(gl_context_, &resource_returner));
  gr_context_.reset(new mojo::GaneshContext(gl_context_));
  mojo::ServiceProviderPtr surfaces_service_provider;
  shell->ConnectToApplication("mojo:surfaces_service",
                              mojo::GetProxy(&surfaces_service_provider),
                              nullptr);
  mojo::ConnectToService(surfaces_service_provider.get(), &surface_);
  surface_->SetResourceReturner(resource_returner.Pass());
  surface_->CreateSurface(surface_id_);
  surface_->GetIdNamespace(base::Bind(&ViewObserverDelegate::SetIdNamespace,
                                      base::Unretained(this)));
  IssueDraw();
}

void ViewObserverDelegate::OnText(const std::string& text) {
  keyboard_service_impl_->OnKey(text.c_str());
}

void ViewObserverDelegate::OnDelete() {
  keyboard_service_impl_->OnDelete();
}

void ViewObserverDelegate::UpdateState(int32 pointer_id,
                                       int action,
                                       const gfx::PointF& touch_point) {
  // Ignore touches outside of key area.
  if (!key_area_.Contains(touch_point)) {
    return;
  }

  base::TimeTicks current_ticks = base::TimeTicks::Now();

  auto it2 = active_pointer_state_.find(pointer_id);
  if (it2 != active_pointer_state_.end()) {
    if (it2->second->last_point_valid) {
      animations_.push_back(make_scoped_ptr(
          new MotionDecayAnimation(current_ticks, kAnimationDurationMs,
                                   it2->second->last_point, touch_point)));
      it2->second->last_point = touch_point;
    } else {
      it2->second->last_point = touch_point;
    }
    it2->second->last_point_valid = action != mojo::EVENT_TYPE_POINTER_UP;
  }

  if (action == mojo::EVENT_TYPE_POINTER_UP ||
      action == mojo::EVENT_TYPE_POINTER_DOWN) {
    animations_.push_back(make_scoped_ptr(new MaterialSplashAnimation(
        current_ticks, kAnimationDurationMs, touch_point)));
  }
}

void ViewObserverDelegate::DrawKeysToCanvas(const gfx::RectF& key_area,
                                            SkCanvas* canvas) {
  key_layout_.SetKeyArea(key_area);
  key_layout_.Draw(canvas);
}

void ViewObserverDelegate::DrawState() {
  base::TimeTicks current_ticks = base::TimeTicks::Now();
  mojo::Size size = ToSize(view_->bounds());
  mojo::GaneshContext::Scope scope(gr_context_.get());
  scoped_ptr<mojo::TextureCache::TextureInfo> texture_info(
      texture_cache_->GetTexture(size).Pass());
  mojo::GaneshSurface surface(gr_context_.get(),
                              texture_info->Texture().Pass());

  gr_context_.get()->gr()->resetContext(kTextureBinding_GrGLBackendState);

  SkCanvas* canvas = surface.canvas();

  canvas->clear(SK_ColorTRANSPARENT);

  // If we have a clip animation it must go first as only things drawn after the
  // clip is set will be clipped.
  if (clip_animation_) {
    if (!clip_animation_->IsDone(current_ticks)) {
      clip_animation_->Draw(canvas, current_ticks);
    } else {
      clip_animation_.reset();
    }
  }

  DrawKeysToCanvas(key_area_, canvas);
  // clip animations to the key area.
  canvas->clipRect(SkRect::MakeXYWH(key_area_.x(), key_area_.y(),
                                    key_area_.width(), key_area_.height()));
  DrawAnimations(canvas, current_ticks);

  // reset clip to whatever the clip animation sets.
  canvas->clipRect(SkRect::MakeXYWH(0, 0, size.width, size.height),
                   SkRegion::kReplace_Op);
  if (clip_animation_) {
    if (!clip_animation_->IsDone(current_ticks)) {
      clip_animation_->Draw(canvas, current_ticks);
    } else {
      clip_animation_.reset();
    }
  }

  DrawFloatingKey(canvas, floating_key_height_, floating_key_width_);

  canvas->flush();
  scoped_ptr<mojo::GLTexture> surface_texture(surface.TakeTexture().Pass());
  mojo::FramePtr frame = mojo::TextureUploader::GetUploadFrame(
      gl_context_, texture_info->ResourceId(), surface_texture);
  texture_cache_->NotifyPendingResourceReturn(texture_info->ResourceId(),
                                              surface_texture.Pass());
  surface_->SubmitFrame(surface_id_, frame.Pass(), submit_frame_callback_);
}

void ViewObserverDelegate::DrawAnimations(
    SkCanvas* canvas,
    const base::TimeTicks& current_ticks) {
  auto first_valid_animation = animations_.end();
  for (auto it = animations_.begin(); it != animations_.end(); ++it) {
    bool done = (*it)->IsDone(current_ticks);
    if (!done) {
      (*it)->Draw(canvas, current_ticks);
      if (first_valid_animation == animations_.end()) {
        first_valid_animation = it;
      }
    }
  }

  // Clean up 'done' animations.
  animations_.erase(animations_.begin(), first_valid_animation);
}

void ViewObserverDelegate::DrawFloatingKey(SkCanvas* canvas,
                                           float floating_key_height,
                                           float floating_key_width) {
  if (active_pointer_ids_.empty()) {
    return;
  }

  for (auto& pointer_state : active_pointer_state_) {
    if (pointer_state.second->last_key != nullptr &&
        pointer_state.second->last_point_valid) {
      SkPaint paint;
      paint.setColor(SK_ColorYELLOW);
      float left =
          pointer_state.second->last_point.x() - (floating_key_width / 2);
      float top =
          pointer_state.second->last_point.y() - (0.45f * key_area_.height());
      SkRect rect = SkRect::MakeLTRB(left, top, left + floating_key_width,
                                     top + floating_key_height);

      // Add shadow beneath the floating key.
      paint.setStrokeJoin(SkPaint::kRound_Join);
      int blur = 20;
      float ratio_x_from_center =
          (left + (floating_key_width / 2) - (key_area_.width() / 2)) /
          (key_area_.width() / 2);
      float ratio_y_from_center =
          (top + (floating_key_height / 2) - (key_area_.height() / 2)) /
          (key_area_.height() / 2);
      SkColor color = SkColorSetARGB(0x80, 0, 0, 0);
      std::vector<gfx::ShadowValue> shadows;
      shadows.push_back(gfx::ShadowValue(
          gfx::Vector2d(ratio_x_from_center * 10, ratio_y_from_center * 10),
          blur, color));
      skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows);
      paint.setLooper(looper.get());

      canvas->drawRect(rect, paint);

      skia::RefPtr<SkTypeface> typeface = skia::AdoptRef(
          SkTypeface::CreateFromName("Arial", SkTypeface::kNormal));
      SkPaint text_paint;
      text_paint.setTypeface(typeface.get());
      text_paint.setColor(SK_ColorBLACK);
      text_paint.setTextSize(floating_key_height / 1.7f);
      text_paint.setAntiAlias(true);
      text_paint.setTextAlign(SkPaint::kCenter_Align);
      pointer_state.second->last_key->Draw(
          canvas, text_paint,
          gfx::RectF(left, top, floating_key_width, floating_key_height));
    }
  }
}

void ViewObserverDelegate::IssueDraw() {
  if (!frame_pending_) {
    DrawState();
    frame_pending_ = true;
    needs_draw_ = !animations_.empty() || clip_animation_;
  } else {
    needs_draw_ = true;
  }
}

void ViewObserverDelegate::OnFrameComplete() {
  frame_pending_ = false;
  if (needs_draw_) {
    IssueDraw();
  }
}

// mojo::ViewObserver implementation.
void ViewObserverDelegate::OnViewBoundsChanged(mojo::View* view,
                                               const mojo::Rect& old_bounds,
                                               const mojo::Rect& new_bounds) {
  surface_->DestroySurface(surface_id_);
  surface_id_++;
  surface_->CreateSurface(surface_id_);
  UpdateSurfaceIds();

  floating_key_height_ = static_cast<float>(new_bounds.height) / 5.0f;
  floating_key_width_ = static_cast<float>(new_bounds.width) / 8.0f;

  // One third of our height will be used for overlapping views behind us.  Only
  // the floating key will be drawn into that area.  The remaining two thirds
  // will be the key area.
  float overlap = new_bounds.height / 3.0f;
  key_area_ =
      gfx::RectF(0, overlap, new_bounds.width, new_bounds.height - overlap);

  // Upon resize, kick off a clip animation centered on our key area with a
  // radius equal to the length from a corner of the new bounds to the center of
  // the key area.
  base::TimeTicks current_ticks = base::TimeTicks::Now();
  gfx::PointF center(key_area_.width() / 2.0f,
                     overlap + (key_area_.height() / 2.0f));
  float radius = sqrt(new_bounds.width / 2.0f * new_bounds.width / 2.0f +
                      new_bounds.height / 2.0f * new_bounds.height / 2.0f);
  clip_animation_.reset(
      new ClipAnimation(current_ticks, kAnimationDurationMs, center, radius));

  IssueDraw();
}

void ViewObserverDelegate::OnViewInputEvent(mojo::View* view,
                                            const mojo::EventPtr& event) {
  if (event->pointer_data) {
    gfx::PointF point(event->pointer_data->x, event->pointer_data->y);

    if (event->action == mojo::EVENT_TYPE_POINTER_UP) {
      key_layout_.OnTouchUp(point);
    }

    if (event->action == mojo::EVENT_TYPE_POINTER_DOWN ||
        event->action == mojo::EVENT_TYPE_POINTER_UP) {
      auto it =
          std::find(active_pointer_ids_.begin(), active_pointer_ids_.end(),
                    event->pointer_data->pointer_id);
      if (it != active_pointer_ids_.end()) {
        active_pointer_ids_.erase(it);
      }

      auto it2 = active_pointer_state_.find(event->pointer_data->pointer_id);
      if (it2 != active_pointer_state_.end()) {
        active_pointer_state_.erase(it2);
      }
      if (event->action == mojo::EVENT_TYPE_POINTER_DOWN) {
        active_pointer_ids_.push_back(event->pointer_data->pointer_id);
        PointerState* pointer_state = new PointerState();
        pointer_state->last_key = nullptr;
        pointer_state->last_point = gfx::PointF();
        pointer_state->last_point_valid = false;
        active_pointer_state_[event->pointer_data->pointer_id].reset(
            pointer_state);
      }
    }

    auto it2 = active_pointer_state_.find(event->pointer_data->pointer_id);
    if (it2 != active_pointer_state_.end()) {
      active_pointer_state_[event->pointer_data->pointer_id]->last_key =
          key_layout_.GetKeyAtPoint(point);
    }

    UpdateState(event->pointer_data->pointer_id, event->action, point);
    IssueDraw();
  }
}

void ViewObserverDelegate::OnViewDestroyed(mojo::View* view) {
  if (view_ == view) {
    view_->RemoveObserver(this);
    view_ = nullptr;
    gl_context_->Destroy();
  }
}

}  // namespace keyboard
