// 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();
}

fpromise::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 fpromise::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 fpromise::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
