// 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/bind_helpers.h"
#include "base/macros.h"
#include "mojo/tools/embed/data.h"
#include "services/keyboard_native/kActionIcon.h"
#include "services/keyboard_native/kDeleteIcon.h"
#include "services/keyboard_native/kLowerCaseIcon.h"
#include "services/keyboard_native/kUpperCaseIcon.h"
#include "services/keyboard_native/key_layout.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageDecoder.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/vector2d.h"

namespace keyboard {

// An implementation of Key that draws itself as ASCII text.
class KeyLayout::TextKey : public Key {
 public:
  TextKey(const char* text,
          base::Callback<void(const TextKey&)> touch_up_callback)
      : text_(text), touch_up_callback_(touch_up_callback) {}

  ~TextKey() override {}

  void Draw(SkCanvas* canvas,
            const SkPaint& paint,
            const gfx::RectF& rect) override {
    float text_baseline_offset = rect.height() / 5.0f;
    canvas->drawText(text_, strlen(text_), rect.x() + (rect.width() / 2.0f),
                     rect.y() + rect.height() - text_baseline_offset, paint);
  }

  const char* ToText() const override { return text_; }

  void OnTouchUp() override { touch_up_callback_.Run(*this); }

 private:
  const char* text_;
  base::Callback<void(const TextKey&)> touch_up_callback_;

  DISALLOW_COPY_AND_ASSIGN(TextKey);
};

// An implementation of Key that draws itself as an image.
class ImageKey : public KeyLayout::Key {
 public:
  ImageKey(const char* text,
           base::Callback<void(const KeyLayout::TextKey&)> touch_up_callback,
           const mojo::embed::Data& data)
      : text_key_(text, touch_up_callback), bitmap_valid_(false), bitmap_() {
    bool result = gfx::PNGCodec::Decode(
        reinterpret_cast<const unsigned char*>(data.data), data.size, &bitmap_);
    bitmap_valid_ = result && bitmap_.width() > 0 && bitmap_.height() > 0;
    DCHECK(bitmap_valid_);
  }
  ~ImageKey() override {}

  // Key implementation.
  void Draw(SkCanvas* canvas,
            const SkPaint& paint,
            const gfx::RectF& rect) override {
    // If our bitmap is somehow invalid, default to drawing the text of the key.
    if (!bitmap_valid_) {
      text_key_.Draw(canvas, paint, rect);
      return;
    }

    float width_scale = rect.width() / bitmap_.width();
    float height_scale = rect.height() / bitmap_.height();
    float scale = width_scale > height_scale ? height_scale : width_scale;
    float target_width = bitmap_.width() * scale;
    float target_height = bitmap_.height() * scale;
    float delta_width = rect.width() - target_width;
    float target_x = rect.x() + (delta_width / 2.0f);
    float delta_height = rect.height() - target_height;
    float target_y = rect.y() + (delta_height / 2.0f);
    canvas->drawBitmapRect(
        bitmap_,
        SkRect::MakeXYWH(target_x, target_y, target_width, target_height),
        &paint);
  }
  const char* ToText() const override { return text_key_.ToText(); }
  void OnTouchUp() override { text_key_.OnTouchUp(); }

 private:
  KeyLayout::TextKey text_key_;
  bool bitmap_valid_;
  SkBitmap bitmap_;

  DISALLOW_COPY_AND_ASSIGN(ImageKey);
};

KeyLayout::KeyLayout()
    : on_text_callback_(),
      layout_(&letters_layout_),
      key_map_(&lower_case_key_map_),
      weak_factory_(this) {
  InitLayouts();
  InitKeyMaps();
}

KeyLayout::~KeyLayout() {
  for (auto& row : lower_case_key_map_) {
    for (auto& key : row) {
      delete key;
    }
  }
  for (auto& row : upper_case_key_map_) {
    for (auto& key : row) {
      delete key;
    }
  }
  for (auto& row : symbols_key_map_) {
    for (auto& key : row) {
      delete key;
    }
  }
}

void KeyLayout::SetTextCallback(
    base::Callback<void(const std::string&)> on_text_callback) {
  on_text_callback_ = on_text_callback;
}

void KeyLayout::SetDeleteCallback(base::Callback<void()> on_delete_callback) {
  on_delete_callback_ = on_delete_callback;
}

void KeyLayout::SetKeyArea(const gfx::RectF& key_area) {
  key_area_ = key_area;
}

void KeyLayout::Draw(SkCanvas* canvas) {
  // Add shadow beneath the key area.
  int blur = 20;
  SkColor color = SkColorSetARGB(0x80, 0, 0, 0);
  std::vector<gfx::ShadowValue> shadows;
  shadows.push_back(gfx::ShadowValue(gfx::Vector2d(0, 0), blur, color));
  skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows);

  SkPaint background_paint;
  background_paint.setColor(SK_ColorLTGRAY);
  background_paint.setStrokeJoin(SkPaint::kRound_Join);
  background_paint.setLooper(looper.get());
  canvas->drawRect(RectFToSkRect(key_area_), background_paint);

  float row_height = key_area_.height() / static_cast<float>(layout_->size());

  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(row_height / 2);
  text_paint.setAntiAlias(true);
  text_paint.setTextAlign(SkPaint::kCenter_Align);

  SkPaint paint;
  for (size_t row_index = 0; row_index < layout_->size(); row_index++) {
    float current_top = key_area_.y() + row_index * row_height;
    float current_left = key_area_.x();
    for (size_t key_index = 0; key_index < (*layout_)[row_index].size();
         key_index++) {
      float key_width = static_cast<float>(key_area_.width()) *
                        (*layout_)[row_index][key_index];

      (*key_map_)[row_index][key_index]->Draw(
          canvas, text_paint,
          gfx::RectF(current_left, current_top, key_width, row_height));
      current_left += key_width;
    }
  }
}

KeyLayout::Key* KeyLayout::GetKeyAtPoint(const gfx::PointF& point) {
  if (!key_area_.Contains(point)) {
    return nullptr;
  }

  int row_index =
      (point.y() - key_area_.y()) / (key_area_.height() / layout_->size());
  float width_percent = static_cast<float>(point.x() - key_area_.x()) /
                        static_cast<float>(key_area_.width());

  int key_index = 0;
  while (width_percent >= (*layout_)[row_index][key_index]) {
    width_percent -= (*layout_)[row_index][key_index];
    key_index++;
  }
  return (*key_map_)[row_index][key_index];
}

void KeyLayout::OnTouchUp(const gfx::PointF& touch_up) {
  Key* key = GetKeyAtPoint(touch_up);
  if (key != nullptr) {
    key->OnTouchUp();
  }
}

void KeyLayout::InitLayouts() {
  // Row layouts are specified by a vector of floats which indicate the percent
  // width a given key takes up in that row.  The floats of a given row *MUST*
  // add up to 1.
  std::vector<float> ten_key_row_layout = {
      0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f};
  std::vector<float> nine_key_row_layout = {
      0.15f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.15f};
  std::vector<float> seven_key_row_layout = {
      0.15f, 0.1f, 0.1f, 0.3f, 0.1f, 0.1f, 0.15f};
  std::vector<float> five_key_row_layout = {0.15f, 0.1f, 0.5f, 0.1f, 0.15f};

  letters_layout_.push_back(ten_key_row_layout);
  letters_layout_.push_back(nine_key_row_layout);
  letters_layout_.push_back(nine_key_row_layout);
  letters_layout_.push_back(five_key_row_layout);

  symbols_layout_.push_back(ten_key_row_layout);
  symbols_layout_.push_back(nine_key_row_layout);
  symbols_layout_.push_back(nine_key_row_layout);
  symbols_layout_.push_back(seven_key_row_layout);
}

void KeyLayout::OnKeyDoNothing(const TextKey& key) {
  // do nothing
}

void KeyLayout::OnKeyEmitText(const TextKey& key) {
  on_text_callback_.Run(std::string(key.ToText()));
}

void KeyLayout::OnKeyDelete(const TextKey& key) {
  on_delete_callback_.Run();
}

void KeyLayout::OnKeySwitchToUpperCase(const TextKey& key) {
  layout_ = &letters_layout_;
  key_map_ = &upper_case_key_map_;
}

void KeyLayout::OnKeySwitchToLowerCase(const TextKey& key) {
  layout_ = &letters_layout_;
  key_map_ = &lower_case_key_map_;
}

void KeyLayout::OnKeySwitchToSymbols(const TextKey& key) {
  layout_ = &symbols_layout_;
  key_map_ = &symbols_key_map_;
}

void KeyLayout::InitKeyMaps() {
  base::Callback<void(const TextKey&)> do_nothing_callback =
      base::Bind(&KeyLayout::OnKeyDoNothing, weak_factory_.GetWeakPtr());
  base::Callback<void(const TextKey&)> emit_text_callback =
      base::Bind(&KeyLayout::OnKeyEmitText, weak_factory_.GetWeakPtr());
  base::Callback<void(const TextKey&)> delete_callback =
      base::Bind(&KeyLayout::OnKeyDelete, weak_factory_.GetWeakPtr());
  base::Callback<void(const TextKey&)> switch_to_upper_case_callback =
      base::Bind(&KeyLayout::OnKeySwitchToUpperCase,
                 weak_factory_.GetWeakPtr());
  base::Callback<void(const TextKey&)> switch_to_lower_case_callback =
      base::Bind(&KeyLayout::OnKeySwitchToLowerCase,
                 weak_factory_.GetWeakPtr());
  base::Callback<void(const TextKey&)> switch_to_symbols_callback =
      base::Bind(&KeyLayout::OnKeySwitchToSymbols, weak_factory_.GetWeakPtr());

  ImageKey* switch_to_upper_case_image_key = new ImageKey(
      "/\\", switch_to_upper_case_callback, keyboard_native::kUpperCaseIcon);
  ImageKey* switch_to_lower_case_image_key = new ImageKey(
      "\\/", switch_to_lower_case_callback, keyboard_native::kLowerCaseIcon);
  ImageKey* delete_image_key =
      new ImageKey("<-", delete_callback, keyboard_native::kDeleteIcon);
  ImageKey* action_image_key =
      new ImageKey(":)", do_nothing_callback, keyboard_native::kActionIcon);

  std::vector<Key*> lower_case_key_map_row_one = {
      new TextKey("q", emit_text_callback),
      new TextKey("w", emit_text_callback),
      new TextKey("e", emit_text_callback),
      new TextKey("r", emit_text_callback),
      new TextKey("t", emit_text_callback),
      new TextKey("y", emit_text_callback),
      new TextKey("u", emit_text_callback),
      new TextKey("o", emit_text_callback),
      new TextKey("i", emit_text_callback),
      new TextKey("p", emit_text_callback)};

  std::vector<Key*> lower_case_key_map_row_two = {
      new TextKey("a", emit_text_callback),
      new TextKey("s", emit_text_callback),
      new TextKey("d", emit_text_callback),
      new TextKey("f", emit_text_callback),
      new TextKey("g", emit_text_callback),
      new TextKey("h", emit_text_callback),
      new TextKey("j", emit_text_callback),
      new TextKey("k", emit_text_callback),
      new TextKey("l", emit_text_callback)};

  std::vector<Key*> lower_case_key_map_row_three = {
      switch_to_upper_case_image_key,
      new TextKey("z", emit_text_callback),
      new TextKey("x", emit_text_callback),
      new TextKey("c", emit_text_callback),
      new TextKey("v", emit_text_callback),
      new TextKey("b", emit_text_callback),
      new TextKey("n", emit_text_callback),
      new TextKey("m", emit_text_callback),
      delete_image_key};

  std::vector<Key*> lower_case_key_map_row_four = {
      new TextKey("sym", switch_to_symbols_callback),
      new TextKey(",", emit_text_callback),
      new TextKey(" ", emit_text_callback),
      new TextKey(".", emit_text_callback),
      action_image_key};

  lower_case_key_map_ = {lower_case_key_map_row_one,
                         lower_case_key_map_row_two,
                         lower_case_key_map_row_three,
                         lower_case_key_map_row_four};

  std::vector<Key*> upper_case_key_map_row_one = {
      new TextKey("Q", emit_text_callback),
      new TextKey("W", emit_text_callback),
      new TextKey("E", emit_text_callback),
      new TextKey("R", emit_text_callback),
      new TextKey("T", emit_text_callback),
      new TextKey("Y", emit_text_callback),
      new TextKey("U", emit_text_callback),
      new TextKey("O", emit_text_callback),
      new TextKey("I", emit_text_callback),
      new TextKey("P", emit_text_callback)};

  std::vector<Key*> upper_case_key_map_row_two = {
      new TextKey("A", emit_text_callback),
      new TextKey("S", emit_text_callback),
      new TextKey("D", emit_text_callback),
      new TextKey("F", emit_text_callback),
      new TextKey("G", emit_text_callback),
      new TextKey("H", emit_text_callback),
      new TextKey("J", emit_text_callback),
      new TextKey("K", emit_text_callback),
      new TextKey("L", emit_text_callback)};

  std::vector<Key*> upper_case_key_map_row_three = {
      switch_to_lower_case_image_key,
      new TextKey("Z", emit_text_callback),
      new TextKey("X", emit_text_callback),
      new TextKey("C", emit_text_callback),
      new TextKey("V", emit_text_callback),
      new TextKey("B", emit_text_callback),
      new TextKey("N", emit_text_callback),
      new TextKey("M", emit_text_callback),
      delete_image_key};

  std::vector<Key*> upper_case_key_map_row_four = {
      new TextKey("SYM", switch_to_symbols_callback),
      new TextKey(",", emit_text_callback),
      new TextKey(" ", emit_text_callback),
      new TextKey(".", emit_text_callback),
      action_image_key};

  upper_case_key_map_ = {upper_case_key_map_row_one,
                         upper_case_key_map_row_two,
                         upper_case_key_map_row_three,
                         upper_case_key_map_row_four};

  std::vector<Key*> symbols_key_map_row_one = {
      new TextKey("1", emit_text_callback),
      new TextKey("2", emit_text_callback),
      new TextKey("3", emit_text_callback),
      new TextKey("4", emit_text_callback),
      new TextKey("5", emit_text_callback),
      new TextKey("6", emit_text_callback),
      new TextKey("7", emit_text_callback),
      new TextKey("8", emit_text_callback),
      new TextKey("9", emit_text_callback),
      new TextKey("0", emit_text_callback)};

  std::vector<Key*> symbols_key_map_row_two = {
      new TextKey("@", emit_text_callback),
      new TextKey("#", emit_text_callback),
      new TextKey("$", emit_text_callback),
      new TextKey("%", emit_text_callback),
      new TextKey("&", emit_text_callback),
      new TextKey("-", emit_text_callback),
      new TextKey("+", emit_text_callback),
      new TextKey("(", emit_text_callback),
      new TextKey(")", emit_text_callback)};

  std::vector<Key*> symbols_key_map_row_three = {
      new TextKey("=\\<", switch_to_symbols_callback),
      new TextKey("*", emit_text_callback),
      new TextKey("\"", emit_text_callback),
      new TextKey("'", emit_text_callback),
      new TextKey(":", emit_text_callback),
      new TextKey(";", emit_text_callback),
      new TextKey("!", emit_text_callback),
      new TextKey("?", emit_text_callback),
      delete_image_key};

  std::vector<Key*> symbols_key_map_row_four = {
      new TextKey("ABC", switch_to_lower_case_callback),
      new TextKey(",", emit_text_callback),
      new TextKey("_", emit_text_callback),
      new TextKey(" ", emit_text_callback),
      new TextKey("/", emit_text_callback),
      new TextKey(".", emit_text_callback),
      action_image_key};

  symbols_key_map_ = {symbols_key_map_row_one,
                      symbols_key_map_row_two,
                      symbols_key_map_row_three,
                      symbols_key_map_row_four};
}
}
// namespace keyboard
