// Copyright 2019 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 "src/camera/bin/factory/factory_server.h"

#include <lib/async/cpp/task.h>
#include <lib/syslog/cpp/macros.h>

#include <iostream>

#include "src/lib/files/directory.h"
#include "src/lib/files/file.h"
#include "src/lib/files/path.h"

namespace camera {

FactoryServer::FactoryServer()
    : loop_(&kAsyncLoopConfigNoAttachToCurrentThread), controller_binding_(this) {}

FactoryServer::~FactoryServer() {
  loop_.RunUntilIdle();
  controller_binding_.Unbind();
  streamer_ = nullptr;
  loop_.Quit();
  loop_.JoinThreads();
}

fit::result<std::unique_ptr<FactoryServer>, zx_status_t> FactoryServer::Create(
    fuchsia::sysmem::AllocatorHandle allocator, fuchsia::camera3::DeviceWatcherHandle watcher,
    fit::closure stop_callback) {
  auto server = std::make_unique<FactoryServer>();

  server->stop_callback_ = std::move(stop_callback);

  // Start a thread and begin processing messages.
  zx_status_t status = server->loop_.StartThread("camera-factory Loop");
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status);
    return fit::error(status);
  }

  auto streamer_result =
      Streamer::Create(std::move(allocator), std::move(watcher), std::move(stop_callback));
  if (streamer_result.is_error()) {
    FX_PLOGS(ERROR, streamer_result.error()) << "Failed to create Streamer.";
    return streamer_result.take_error_result();
  }
  server->streamer_ = streamer_result.take_value();

  // Create the WebUI
  auto webui_result = WebUI::Create(server.get());
  if (webui_result.is_error()) {
    FX_PLOGS(ERROR, webui_result.error()) << "Failed to create WebUI.";
    return webui_result.take_error_result();
  }
  server->webui_ = webui_result.take_value();
  constexpr uint32_t kPortNumber = 52224;
  server->webui_->PostListen(kPortNumber);

  return fit::ok(std::move(server));
}

fidl::InterfaceRequestHandler<fuchsia::factory::camera::Controller> FactoryServer::GetHandler() {
  return fit::bind_member(this, &FactoryServer::OnNewRequest);
}

void FactoryServer::OnNewRequest(
    fidl::InterfaceRequest<fuchsia::factory::camera::Controller> request) {
  if (controller_binding_.is_bound()) {
    request.Close(ZX_ERR_ALREADY_BOUND);
    return;
  }

  controller_binding_.Bind(std::move(request), loop_.dispatcher());
}

void FactoryServer::Capture() {
  streamer_->RequestCapture(
      0, "", true, [&](zx_status_t status, std::unique_ptr<camera::Capture> frame) {
        if (status != ZX_OK) {
          FX_PLOGS(ERROR, status) << "capture failed";
          return;
        }
        char file[] = "/data/capture.png";
        FILE* filefp = fopen(file, "w");
        if (filefp == NULL) {
          FX_LOGS(ERROR) << "failed to open " << file << ": " << strerror(errno);
          return;
        }
        frame->WritePNGAsNV12(filefp);
        fclose(filefp);
      });
}

void FactoryServer::RequestCaptureData(uint32_t stream, CaptureResponse callback) {
  streamer_->RequestCapture(
      stream, "", true,
      [callback = callback.share()](zx_status_t status, std::unique_ptr<camera::Capture> frame) {
        callback(status, std::move(frame));
      });
}

void FactoryServer::IsIspBypassModeEnabled(bool enabled) {}

void FactoryServer::CaptureFrames(std::string dir_path, CaptureFramesCallback callback) {
  streamer_->RequestCapture(
      0, "", true,
      [this, dir_path = std::move(dir_path), cb = std::move(callback)](
          zx_status_t status, std::unique_ptr<camera::Capture> frame) mutable {
        async::PostTask(loop_.dispatcher(),
                        [this, dir_path = std::move(dir_path), cb = std::move(cb), status,
                         frame = std::move(frame)]() {
                          if (status != ZX_OK) {
                            FX_PLOGS(ERROR, status) << "capture failed";
                            cb(ZX_OK, fuchsia::images::ImageInfo{});
                            return;
                          }
                          if (dir_path != "") {
                            if (!files::CreateDirectory("/data/" + dir_path)) {
                              FX_LOGS(ERROR) << "Failed to create on-disk directory to write to.";
                              return;
                            }
                          }
                          auto file = "/data/" + dir_path + "/capture.png";
                          FILE* filefp = fopen(file.data(), "w");
                          if (filefp == NULL) {
                            FX_LOGS(ERROR) << "failed to open " << file << ": " << strerror(errno);
                            return;
                          }

                          // TODO(fxbug.dev/58498): Check if frame->properties_.image_format ==
                          // fuchsia::sysmem::PixelFormatType::NV12
                          if (bypass_) {
                            frame->WritePNGUnprocessed(filefp, true);
                          } else {
                            frame->WritePNGAsNV12(filefp);
                          }

                          fclose(filefp);
                          cb(ZX_OK, fuchsia::images::ImageInfo{});
                        });
      });
}

}  // namespace camera
