// Copyright 2018 The Chromium OS 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 "media_perception/output_manager.h"

#include <functional>
#include <base/logging.h>
#include <dbus/object_proxy.h>

#include "media_perception/frame_perception.pb.h"
#include "media_perception/hotword_detection.pb.h"
#include "media_perception/huddly.pb.h"
#include "media_perception/occupancy_trigger.pb.h"
#include "media_perception/presence_perception.pb.h"
#include "media_perception/proto_mojom_conversion.h"
#include "media_perception/serialized_proto.h"

namespace mri {

namespace {

// To avoid passing a lambda as a base::Closure.
void OnConnectionClosedOrError(const std::string& interface_type) {
  LOG(INFO) << "Got closed connection: " << interface_type;
}

}  // namespace

OutputManager::~OutputManager() {
  if (thread_.IsRunning()) {
    base::WaitableEvent destruction_complete(
        base::WaitableEvent::ResetPolicy::MANUAL,
        base::WaitableEvent::InitialState::NOT_SIGNALED);
    thread_.task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&OutputManager::DestructDbus, base::Unretained(this),
                       &destruction_complete));
    destruction_complete.Wait();
  }
}

void OutputManager::DestructDbus(base::WaitableEvent* destruction_complete) {
  dbus_connection_.reset();
  destruction_complete->Signal();
}

OutputManager::OutputManager(
    const std::string& configuration_name,
    std::shared_ptr<Rtanalytics> rtanalytics,
    const PerceptionInterfaces& interfaces,
    chromeos::media_perception::mojom::PerceptionInterfacesPtr* interfaces_ptr)
    : thread_("OutputManager Dbus Thread") {
  // Save the configuration name in case we need to reference it later.
  configuration_name_ = configuration_name;
  rtanalytics_ = rtanalytics;

  for (const PerceptionInterface& interface : interfaces.interface()) {
    // Frame perception interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_FRAME_PERCEPTION) {
      (*interfaces_ptr)->frame_perception_handler_request =
          frame_perception_handler_.BindNewPipeAndPassReceiver();
      frame_perception_handler_.set_disconnect_handler(
          base::Bind(&OnConnectionClosedOrError, "INTERFACE_FRAME_PERCEPTION"));

      // Frame perception outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() ==
            PipelineOutputType::OUTPUT_FRAME_PERCEPTION) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleFramePerception, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // Hotword detection interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_HOTWORD_DETECTION) {
      (*interfaces_ptr)->hotword_detection_handler_request =
          hotword_detection_handler_.BindNewPipeAndPassReceiver();
      hotword_detection_handler_.set_disconnect_handler(base::Bind(
          &OnConnectionClosedOrError, "INTERFACE_HOTWORD_DETECTION"));

      // Hotword detection outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() ==
            PipelineOutputType::OUTPUT_HOTWORD_DETECTION) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleHotwordDetection, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // Presence perception interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_PRESENCE_PERCEPTION) {
      (*interfaces_ptr)->presence_perception_handler_request =
          presence_perception_handler_.BindNewPipeAndPassReceiver();
      presence_perception_handler_.set_disconnect_handler(base::Bind(
          &OnConnectionClosedOrError, "INTERFACE_PRESENCE_PERCEPTION"));

      // Presence perception outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() ==
            PipelineOutputType::OUTPUT_PRESENCE_PERCEPTION) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandlePresencePerception, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // Occupancy trigger interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_OCCUPANCY_TRIGGER) {
      (*interfaces_ptr)->occupancy_trigger_handler_request =
          occupancy_trigger_handler_.BindNewPipeAndPassReceiver();
      occupancy_trigger_handler_.set_disconnect_handler(base::Bind(
          &OnConnectionClosedOrError, "INTERFACE_OCCUPANCY_TRIGGER"));

      // Occpancy trigger outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() ==
            PipelineOutputType::OUTPUT_OCCUPANCY_TRIGGER) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleOccupancyTrigger, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // Appearances interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_APPEARANCES) {
      (*interfaces_ptr)->appearances_handler_request =
          appearances_handler_.BindNewPipeAndPassReceiver();
      appearances_handler_.set_disconnect_handler(
          base::Bind(&OnConnectionClosedOrError, "APPEARANCES"));

      // Appearances outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() == PipelineOutputType::OUTPUT_APPEARANCES) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleAppearances, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // One touch Autozoom interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_ONE_TOUCH_AUTOZOOM) {
      (*interfaces_ptr)->one_touch_autozoom_handler_request =
          one_touch_autozoom_handler_.BindNewPipeAndPassReceiver();
      one_touch_autozoom_handler_.set_disconnect_handler(
          base::Bind(&OnConnectionClosedOrError, "ONE_TOUCH_AUTOZOOM"));

      // One touch Autozoom outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() == PipelineOutputType::OUTPUT_SMART_FRAMING) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleSmartFraming, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // Software Autozoom interface setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_SOFTWARE_AUTOZOOM) {
      (*interfaces_ptr)->software_autozoom_handler_request =
          software_autozoom_handler_.BindNewPipeAndPassReceiver();
      software_autozoom_handler_.set_disconnect_handler(
          base::Bind(&OnConnectionClosedOrError, "SOFTWARE_AUTOZOOM"));

      // Software Autozoom outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() == PipelineOutputType::OUTPUT_SMART_FRAMING) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleSmartFraming, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
          }
        }
      }
      continue;
    }

    // Falcon Autozoom outputs setup.
    if (interface.interface_type() ==
        PerceptionInterfaceType::INTERFACE_FALCON_AUTOZOOM) {
      // Falcon Autozoom outputs setup.
      for (const PipelineOutput& output : interface.output()) {
        if (output.output_type() ==
            PipelineOutputType::OUTPUT_INDEXED_TRANSITIONS) {
          SerializedSuccessStatus serialized_status =
              rtanalytics->SetPipelineOutputHandler(
                  configuration_name, output.stream_name(),
                  std::bind(&OutputManager::HandleIndexedTransitions, this,
                            std::placeholders::_1));
          SuccessStatus status =
              Serialized<SuccessStatus>(serialized_status).Deserialize();
          if (!status.success()) {
            LOG(ERROR) << "Failed to set output handler for "
                       << configuration_name << " with output "
                       << output.stream_name();
            continue;
          }

          if (!thread_.StartWithOptions(
                  base::Thread::Options(base::MessagePumpType::IO, 0))) {
            LOG(ERROR) << "Failed to create dbus thread.";
            continue;
          }
          dbus_connection_ = std::make_unique<brillo::DBusConnection>();
          thread_.task_runner()->PostTask(
              FROM_HERE, base::Bind(&OutputManager::InitializeDbus,
                                    base::Unretained(this)));
        }
      }
      continue;
    }
  }
}

void OutputManager::InitializeDbus() {
  bus_ = dbus_connection_->Connect();
  if (bus_ == nullptr) {
    LOG(FATAL) << "Unable to connect to Dbus from OutputManager.";
  }
  dbus_proxy_ = bus_->GetObjectProxy(
      "org.chromium.IpPeripheralService",
      dbus::ObjectPath("/org/chromium/IpPeripheralService"));
}

void OutputManager::HandleFramePerception(const std::vector<uint8_t>& bytes) {
  if (!frame_perception_handler_.is_bound()) {
    LOG(WARNING) << "Got frame perception output but handler ptr is not bound.";
    return;
  }

  if (frame_perception_handler_.get() == nullptr) {
    LOG(ERROR) << "Handler ptr is null.";
    return;
  }

  FramePerception frame_perception =
      Serialized<FramePerception>(bytes).Deserialize();
  frame_perception_handler_->OnFramePerception(
      chromeos::media_perception::mojom::ToMojom(frame_perception));
}

void OutputManager::HandleHotwordDetection(const std::vector<uint8_t>& bytes) {
  if (!hotword_detection_handler_.is_bound()) {
    LOG(WARNING)
        << "Got hotword detection output but handler ptr is not bound.";
    return;
  }

  if (hotword_detection_handler_.get() == nullptr) {
    LOG(ERROR) << "Handler ptr is null.";
    return;
  }

  HotwordDetection hotword_detection =
      Serialized<HotwordDetection>(bytes).Deserialize();
  hotword_detection_handler_->OnHotwordDetection(
      chromeos::media_perception::mojom::ToMojom(hotword_detection));
}

void OutputManager::HandlePresencePerception(
    const std::vector<uint8_t>& bytes) {
  if (!presence_perception_handler_.is_bound()) {
    LOG(WARNING)
        << "Got presence perception output but handler ptr is not bound.";
    return;
  }

  if (presence_perception_handler_.get() == nullptr) {
    LOG(ERROR) << "Handler ptr is null.";
    return;
  }

  PresencePerception presence_perception =
      Serialized<PresencePerception>(bytes).Deserialize();
  presence_perception_handler_->OnPresencePerception(
      chromeos::media_perception::mojom::ToMojom(presence_perception));
}

void OutputManager::HandleOccupancyTrigger(const std::vector<uint8_t>& bytes) {
  if (!occupancy_trigger_handler_.is_bound()) {
    LOG(WARNING)
        << "Got occupancy trigger output but handler ptr is not bound.";
    return;
  }

  if (occupancy_trigger_handler_.get() == nullptr) {
    LOG(ERROR) << "Handler ptr is null.";
    return;
  }

  OccupancyTrigger occupancy_trigger =
      Serialized<OccupancyTrigger>(bytes).Deserialize();
  occupancy_trigger_handler_->OnOccupancyTrigger(
      chromeos::media_perception::mojom::ToMojom(occupancy_trigger));
}

void OutputManager::HandleAppearances(const std::vector<uint8_t>& bytes) {
  if (!appearances_handler_.is_bound()) {
    LOG(WARNING) << "Got appearances but handler ptr is not bound.";
    return;
  }

  if (appearances_handler_.get() == nullptr) {
    LOG(ERROR) << "Handler ptr is null.";
    return;
  }

  appearances_handler_->OnAppearances(bytes);
}

void OutputManager::HandleSmartFraming(const std::vector<uint8_t>& bytes) {
  if (one_touch_autozoom_handler_.is_bound() &&
      one_touch_autozoom_handler_.get() != nullptr) {
    one_touch_autozoom_handler_->OnSmartFraming(bytes);
  } else if (software_autozoom_handler_.is_bound() &&
             software_autozoom_handler_.get() != nullptr) {
    software_autozoom_handler_->OnSmartFraming(bytes);
  } else {
    LOG(WARNING) << "Got smart framing but handler ptr is not bound.";
  }
}

void OutputManager::HandleIndexedTransitions(
    const std::vector<uint8_t>& bytes) {
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&OutputManager::HandleIndexedTransitionsOnDbusThread,
                     base::Unretained(this), bytes));
}

void OutputManager::HandleIndexedTransitionsOnDbusThread(
    const std::vector<uint8_t>& bytes) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
  std::string falcon_ip = rtanalytics_->GetFalconIp(configuration_name_);
  std::size_t found = falcon_ip.find_last_of(".");
  if (found == -1) {
    LOG(ERROR) << "Device id is not an IP address.";
    return;
  }

  falcon_ip = falcon_ip.substr(0, found);
  // Send indexed transitions bytes over D-bus to the IP peripheral service.
  if (bytes.size() == 0) {
    dbus::MethodCall method_call("org.chromium.IpPeripheralService.FalconGrpc",
                                 "ResetPTZTransition");
    dbus::MessageWriter writer(&method_call);
    writer.AppendString(falcon_ip);
    dbus_proxy_->CallMethod(&method_call,
                            dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
                            base::BindOnce([](dbus::Response* response) {}));
  } else {
    dbus::MethodCall method_call("org.chromium.IpPeripheralService.FalconGrpc",
                                 "DoPTZTransition");
    dbus::MessageWriter writer(&method_call);
    writer.AppendString(falcon_ip);
    writer.AppendArrayOfBytes(bytes.data(), bytes.size());
    dbus_proxy_->CallMethod(
        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
        base::BindOnce(&OutputManager::HandleFalconPtzTransitionResponse,
                       weak_ptr_factory_.GetWeakPtr()));
  }
}

void OutputManager::HandleFalconPtzTransitionResponse(
    dbus::Response* response) {
  std::vector<uint8_t> serialized_response;
  if (response == nullptr) {
    LOG(ERROR) << "HandleFalconPtzTransitionResponse ignoring dbus nullptr.";
    huddly::IndexedTransitionsResponse itr;
    itr.set_chosen_starting_index(-1);
    serialized_response =
        Serialized<huddly::IndexedTransitionsResponse>(itr).GetBytes();
  } else {
    dbus::MessageReader reader(response);
    // Return the response to rtanalytics.
    const uint8_t* bytes = nullptr;
    size_t size;
    reader.PopArrayOfBytes(&bytes, &size);
    serialized_response.assign(bytes, bytes + size);
  }
  rtanalytics_->RespondToFalconPtzTransition(configuration_name_,
                                             serialized_response);
}

}  // namespace mri
