// 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 "apps/moterm/moterm_view.h"

#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <algorithm>
#include <string>

#include "apps/moterm/key_util.h"
#include "base/logging.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/services/files/public/interfaces/file.mojom.h"
#include "mojo/services/files/public/interfaces/types.mojom.h"
#include "mojo/services/input_events/public/interfaces/input_event_constants.mojom.h"
#include "mojo/services/input_events/public/interfaces/input_events.mojom.h"
#include "mojo/services/terminal/public/interfaces/terminal_client.mojom.h"
#include "skia/ext/refptr.h"
#include "third_party/dejavu-fonts-ttf-2.34/kDejaVuSansMonoRegular.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkXfermode.h"

namespace {

const GLint kTextureFormat =
    (kN32_SkColorType == kRGBA_8888_SkColorType) ? GL_RGBA : GL_BGRA_EXT;

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

}  // namespace

MotermView::MotermView(
    mojo::Shell* shell,
    mojo::View* view,
    mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request)
    : view_(view),
      gl_helper_(this, shell, kTextureFormat, RectToSize(view->bounds())),
      model_(MotermModel::Size(240, 160), MotermModel::Size(24, 80)),
      frame_pending_(false),
      force_next_draw_(false),
      ascent_(0),
      line_height_(0),
      advance_width_(0) {
  // TODO(vtl): |service_provider_impl_|'s ctor doesn't like an invalid request,
  // so we have to conditionally, explicitly bind.
  if (service_provider_request.is_pending()) {
    service_provider_impl_.Bind(service_provider_request.Pass());
    service_provider_impl_.AddService<mojo::terminal::Terminal>(this);
  }

  regular_typeface_ = skia::AdoptRef(SkTypeface::CreateFromStream(
      new SkMemoryStream(font_data::kDejaVuSansMonoRegular.data,
                         font_data::kDejaVuSansMonoRegular.size)));

  // TODO(vtl): This duplicates some code.
  SkPaint fg_paint;
  fg_paint.setTypeface(regular_typeface_.get());
  fg_paint.setTextSize(16);
  // Figure out appropriate metrics.
  SkPaint::FontMetrics fm = {};
  fg_paint.getFontMetrics(&fm);
  ascent_ = static_cast<int>(ceilf(-fm.fAscent));
  line_height_ = ascent_ + static_cast<int>(ceilf(fm.fDescent + fm.fLeading));
  DCHECK_GT(line_height_, 0);
  // To figure out the advance width, measure an X. Better hope the font is
  // monospace.
  advance_width_ = static_cast<int>(ceilf(fg_paint.measureText("X", 1)));
  DCHECK_GT(advance_width_, 0);

  view_->AddObserver(this);

  // Force an initial draw.
  Draw(true);
}

MotermView::~MotermView() {
  if (driver_)
    driver_->Detach();
}

void MotermView::OnViewDestroyed(mojo::View* view) {
  DCHECK_EQ(view, view_);
  view_->RemoveObserver(this);
  delete this;
}

void MotermView::OnViewBoundsChanged(mojo::View* view,
                                     const mojo::Rect& old_bounds,
                                     const mojo::Rect& new_bounds) {
  DCHECK_EQ(view, view_);
  gl_helper_.SetSurfaceSize(RectToSize(view_->bounds()));
  bitmap_device_.clear();
  Draw(true);
}

void MotermView::OnViewInputEvent(mojo::View* view,
                                  const mojo::EventPtr& event) {
  if (event->action == mojo::EVENT_TYPE_KEY_PRESSED)
    OnKeyPressed(event);
}

void MotermView::OnSurfaceIdChanged(mojo::SurfaceIdPtr surface_id) {
  view_->SetSurfaceId(surface_id.Pass());
}

void MotermView::OnContextLost() {
  // TODO(vtl): We'll need to force a draw when we regain a context.
}

void MotermView::OnFrameDisplayed(uint32_t frame_id) {
  DCHECK(frame_pending_);
  frame_pending_ = false;
  Draw(false);
}

void MotermView::OnDataReceived(const void* bytes, size_t num_bytes) {
  model_.ProcessInput(bytes, num_bytes, &model_state_changes_);
  Draw(false);
}

void MotermView::OnClosed() {
  DCHECK(driver_);
  driver_->Detach();
  driver_.reset();

  OnDestroyed();
}

void MotermView::OnDestroyed() {
  DCHECK(!driver_);
  if (!on_closed_callback_.is_null()) {
    mojo::Closure callback;
    std::swap(callback, on_closed_callback_);
    callback.Run();
  }
}

void MotermView::Create(
    mojo::ApplicationConnection* connection,
    mojo::InterfaceRequest<mojo::terminal::Terminal> request) {
  terminal_bindings_.AddBinding(this, request.Pass());
}

void MotermView::Connect(
    mojo::InterfaceRequest<mojo::files::File> terminal_file,
    bool force,
    const ConnectCallback& callback) {
  if (driver_) {
    // We already have a connection.
    if (force) {
      OnClosed();
    } else {
      // TODO(vtl): Is this error code right?
      callback.Run(mojo::files::ERROR_UNAVAILABLE);
      return;
    }
  }

  driver_ = MotermDriver::Create(this, terminal_file.Pass());
  DCHECK(on_closed_callback_.is_null());
  on_closed_callback_ = [callback] { callback.Run(mojo::files::ERROR_OK); };
}

void MotermView::ConnectToClient(
    mojo::terminal::TerminalClientPtr terminal_client,
    bool force,
    const ConnectToClientCallback& callback) {
  if (driver_) {
    // We already have a connection.
    if (force) {
      OnClosed();
    } else {
      // TODO(vtl): Is this error code right?
      callback.Run(mojo::files::ERROR_UNAVAILABLE);
      return;
    }
  }

  mojo::files::FilePtr file;
  driver_ = MotermDriver::Create(this, GetProxy(&file));
  terminal_client->ConnectToTerminal(file.Pass());
  DCHECK(on_closed_callback_.is_null());
  on_closed_callback_ = [callback] { callback.Run(mojo::files::ERROR_OK); };
}

void MotermView::GetSize(const GetSizeCallback& callback) {
  MotermModel::Size size = model_.GetSize();
  callback.Run(mojo::files::ERROR_OK, size.rows, size.columns);
}

void MotermView::SetSize(uint32_t rows,
                         uint32_t columns,
                         bool reset,
                         const SetSizeCallback& callback) {
  if (!rows) {
    rows = std::max(1u, std::min(MotermModel::kMaxRows,
                                 static_cast<uint32_t>(view_->bounds().height) /
                                     line_height_));
  }
  if (!columns) {
    columns =
        std::max(1u, std::min(MotermModel::kMaxColumns,
                              static_cast<uint32_t>(view_->bounds().width) /
                                  advance_width_));
  }

  model_.SetSize(MotermModel::Size(rows, columns), reset);
  callback.Run(mojo::files::ERROR_OK, rows, columns);

  Draw(false);
}

void MotermView::Draw(bool force) {
  // TODO(vtl): See TODO above |frame_pending_| in the class declaration.
  if (frame_pending_) {
    force_next_draw_ |= force;
    return;
  }

  force |= force_next_draw_;
  force_next_draw_ = false;

  if (!force && !model_state_changes_.IsDirty())
    return;

  // TODO(vtl): If |!force|, draw only the dirty region(s)?
  model_state_changes_.Reset();

  int32_t width = view_->bounds().width;
  int32_t height = view_->bounds().height;
  DCHECK_GT(width, 0);
  DCHECK_GT(height, 0);

  if (!bitmap_device_) {
    bitmap_device_ = skia::AdoptRef(SkBitmapDevice::Create(SkImageInfo::Make(
        width, height, kN32_SkColorType, kOpaque_SkAlphaType)));
  }

  SkCanvas canvas(bitmap_device_.get());
  canvas.clear(SK_ColorBLACK);

  SkPaint bg_paint;
  bg_paint.setStyle(SkPaint::kFill_Style);

  SkPaint fg_paint;
  fg_paint.setTypeface(regular_typeface_.get());
  fg_paint.setTextSize(16);
  fg_paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);

  MotermModel::Size size = model_.GetSize();
  int y = 0;
  for (unsigned i = 0; i < size.rows; i++, y += line_height_) {
    int x = 0;
    for (unsigned j = 0; j < size.columns; j++, x += advance_width_) {
      MotermModel::CharacterInfo ch =
          model_.GetCharacterInfoAt(MotermModel::Position(i, j));

      // Paint the background.
      bg_paint.setColor(SkColorSetRGB(ch.background_color.red,
                                      ch.background_color.green,
                                      ch.background_color.blue));
      canvas.drawRect(SkRect::MakeXYWH(x, y, advance_width_, line_height_),
                      bg_paint);

      // Paint the foreground.
      if (ch.code_point) {
        uint32_t flags = SkPaint::kAntiAlias_Flag;
        // TODO(vtl): Use real bold font?
        if ((ch.attributes & MotermModel::kAttributesBold))
          flags |= SkPaint::kFakeBoldText_Flag;
        if ((ch.attributes & MotermModel::kAttributesUnderline))
          flags |= SkPaint::kUnderlineText_Flag;
        // TODO(vtl): Handle blink, because that's awesome.
        fg_paint.setFlags(flags);
        fg_paint.setColor(SkColorSetRGB(ch.foreground_color.red,
                                        ch.foreground_color.green,
                                        ch.foreground_color.blue));

        canvas.drawText(&ch.code_point, sizeof(ch.code_point), x, y + ascent_,
                        fg_paint);
      }
    }
  }

  // Draw the cursor.
  MotermModel::Position cursor_pos = model_.GetCursorPosition();
  // Reuse the background paint, but don't just paint over.
  // TODO(vtl): Consider doing other things. Maybe make it blink, to be extra
  // annoying.
  // TODO(vtl): Maybe vary how we draw the cursor, depending on if we're focused
  // and/or active.
  bg_paint.setColor(SK_ColorWHITE);
  bg_paint.setXfermodeMode(SkXfermode::kDifference_Mode);
  canvas.drawRect(SkRect::MakeXYWH(cursor_pos.column * advance_width_,
                                   cursor_pos.row * line_height_,
                                   advance_width_, line_height_),
                  bg_paint);

  canvas.flush();

  const SkBitmap& bitmap(bitmap_device_->accessBitmap(false));
  // TODO(vtl): Do we need really need to lock/unlock pixels?
  SkAutoLockPixels pixel_locker(bitmap);

  gl_helper_.StartFrame();
  // (The texture is already bound.)
  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, kTextureFormat,
                  GL_UNSIGNED_BYTE, bitmap.getPixels());
  gl_helper_.EndFrame();
  frame_pending_ = true;
}

void MotermView::OnKeyPressed(const mojo::EventPtr& key_event) {
  std::string input_sequence = GetInputSequenceForKeyPressedEvent(*key_event);
  if (input_sequence.empty())
    return;

  if (driver_)
    driver_->SendData(input_sequence.data(), input_sequence.size());
}
