// Copyright 2015 The Fuchsia 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 "garnet/examples/ui/tile/tile_view.h"

#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/split_string.h>
#include <lib/svc/cpp/services.h>
#include <lib/ui/base_view/cpp/embedded_view_utils.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>

namespace examples {

TileView::TileView(scenic::ViewContext context, TileParams params)
    : BaseView(std::move(context), "Tile"),
      vfs_(async_get_default_dispatcher()),
      services_dir_(fbl::AdoptRef(new fs::PseudoDir())),
      params_(std::move(params)),
      container_node_(session()) {
  root_node().AddChild(container_node_);
  CreateNestedEnvironment();
  ConnectViews();
}

void TileView::PresentView(
    fuchsia::ui::views::ViewHolderToken view_holder_token,
    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation) {
  AddChildView("tile_view child(Presented view)", std::move(view_holder_token),
               nullptr);
}

void TileView::ConnectViews() {
  for (const auto& url : params_.view_urls) {
    component::Services services;
    fuchsia::sys::ComponentControllerPtr controller;

    fuchsia::sys::LaunchInfo launch_info;

    // Pass arguments to children, if there are any.
    std::vector<std::string> split_url = fxl::SplitStringCopy(
        url, " ", fxl::kTrimWhitespace, fxl::kSplitWantNonEmpty);
    FXL_CHECK(split_url.size() >= 1);
    launch_info.url = split_url[0];
    launch_info.directory_request = services.NewRequest();

    if (split_url.size() > 1) {
      launch_info.arguments = fidl::VectorPtr<std::string>::New(0);
      for (auto it = split_url.begin() + 1; it != split_url.end(); it++) {
        launch_info.arguments.push_back(*it);
      }
    }

    // |env_launcher_| launches the component with our nested environment.
    env_launcher_->CreateComponent(std::move(launch_info),
                                   controller.NewRequest());

    // Create a View from the launched component.
    auto [view_token, view_holder_token] = scenic::NewViewTokenPair();

    auto view_provider =
        services.ConnectToService<fuchsia::ui::app::ViewProvider>();
    view_provider->CreateView(std::move(view_token.value), nullptr, nullptr);

    // Add the view.
    AddChildView("tile_view child(" + split_url[0] + ")",
                 std::move(view_holder_token), std::move(controller));
  }
}

zx::channel TileView::OpenAsDirectory() {
  zx::channel h1, h2;
  if (zx::channel::create(0, &h1, &h2) != ZX_OK)
    return zx::channel();
  if (vfs_.ServeDirectory(services_dir_, std::move(h1)) != ZX_OK)
    return zx::channel();
  return h2;
}

void TileView::CreateNestedEnvironment() {
  // Add a binding for the presenter service
  auto service = fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
    presenter_bindings_.AddBinding(
        this, fidl::InterfaceRequest<fuchsia::ui::policy::Presenter>(
                  std::move(channel)));
    return ZX_OK;
  }));
  services_dir_->AddEntry(fuchsia::ui::policy::Presenter::Name_, service);

  fuchsia::sys::ServiceListPtr service_list(new fuchsia::sys::ServiceList);
  service_list->names.push_back(fuchsia::ui::policy::Presenter::Name_);
  service_list->host_directory = OpenAsDirectory();
  startup_context()->environment()->CreateNestedEnvironment(
      env_.NewRequest(), env_controller_.NewRequest(), "tile",
      std::move(service_list), {.inherit_parent_services = true});
  env_->GetLauncher(env_launcher_.NewRequest());
}

void TileView::OnChildAttached(uint32_t view_holder_id) {
  auto it = views_.find(view_holder_id);
  FXL_DCHECK(it != views_.end());
}

void TileView::OnChildUnavailable(uint32_t view_holder_id) {
  FXL_LOG(ERROR) << "View died unexpectedly: view_holder_id=" << view_holder_id;
  RemoveChildView(view_holder_id);
}

void TileView::OnScenicEvent(fuchsia::ui::scenic::Event event) {
  switch (event.Which()) {
    case ::fuchsia::ui::scenic::Event::Tag::kGfx:
      switch (event.gfx().Which()) {
        case ::fuchsia::ui::gfx::Event::Tag::kViewConnected: {
          auto& evt = event.gfx().view_connected();
          OnChildAttached(evt.view_holder_id);
          break;
        }
        case ::fuchsia::ui::gfx::Event::Tag::kViewDisconnected: {
          auto& evt = event.gfx().view_disconnected();
          OnChildUnavailable(evt.view_holder_id);
          break;
        }
        default:
          break;
      }
    default:
      break;
  }
}

void TileView::AddChildView(
    std::string label, fuchsia::ui::views::ViewHolderToken view_holder_token,
    fuchsia::sys::ComponentControllerPtr controller) {
  auto view_data = std::make_unique<ViewData>(
      label, std::move(view_holder_token), std::move(controller), session());

  container_node_.AddChild(view_data->host_node);

  view_data->host_node.AddPart(view_data->clip_shape_node);
  view_data->host_node.SetClip(0, true);
  view_data->host_node.Attach(view_data->view_holder);

  views_.emplace(view_data->view_holder.id(), std::move(view_data));

  InvalidateScene();
}

void TileView::RemoveChildView(uint32_t view_holder_id) {
  auto it = views_.find(view_holder_id);
  FXL_DCHECK(it != views_.end());

  it->second->host_node.Detach();
  views_.erase(it);

  InvalidateScene();
}

void TileView::OnSceneInvalidated(
    fuchsia::images::PresentationInfo presentation_info) {
  if (!has_logical_size() || views_.empty())
    return;

  // Layout all children in a row.
  const bool vertical =
      (params_.orientation_mode == TileParams::OrientationMode::kVertical);

  uint32_t index = 0;
  uint32_t space = vertical ? logical_size().y : logical_size().x;
  uint32_t base = space / views_.size();
  uint32_t excess = space % views_.size();
  uint32_t offset = 0;
  for (auto it = views_.begin(); it != views_.end(); ++it, ++index) {
    ViewData* view_data = it->second.get();

    // Distribute any excess width among the leading children.
    uint32_t extent = base;
    if (excess) {
      extent++;
      excess--;
    }

    fuchsia::math::RectF layout_bounds;
    if (vertical) {
      layout_bounds.x = 0;
      layout_bounds.y = offset;
      layout_bounds.width = logical_size().x;
      layout_bounds.height = extent;
    } else {
      layout_bounds.x = offset;
      layout_bounds.y = 0;
      layout_bounds.width = extent;
      layout_bounds.height = logical_size().y;
    }
    offset += extent;

    if (view_data->width != layout_bounds.width ||
        view_data->height != layout_bounds.height) {
      view_data->width = layout_bounds.width;
      view_data->height = layout_bounds.height;
      view_data->view_holder.SetViewProperties(0, 0, 0, view_data->width,
                                               view_data->height, 1000.f, 0, 0,
                                               0, 0, 0, 0);
    }

    view_data->host_node.SetTranslation(layout_bounds.x, layout_bounds.y, 0u);

    // Clip
    scenic::Rectangle shape(session(),            // session
                            layout_bounds.width,  // width
                            layout_bounds.height  // height
    );
    view_data->clip_shape_node.SetShape(shape);
    view_data->clip_shape_node.SetTranslation(layout_bounds.width * 0.5f,
                                              layout_bounds.height * 0.5f, 0.f);
  }
}

TileView::ViewData::ViewData(
    std::string label, fuchsia::ui::views::ViewHolderToken view_holder_token,
    fuchsia::sys::ComponentControllerPtr controller, scenic::Session* session)
    : controller(std::move(controller)),
      host_node(session),
      clip_shape_node(session),
      view_holder(session, std::move(view_holder_token), label) {}

}  // namespace examples
