// Copyright 2016 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/bin/netconnector/netconnector_params.h"

#include <fuchsia/sys/cpp/fidl.h>
#include <rapidjson/document.h>

#include "garnet/lib/inet/ip_address.h"
#include "lib/fxl/files/file.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/split_string.h"

namespace netconnector {
namespace {

constexpr char kConfigServices[] = "services";
constexpr char kConfigDevices[] = "devices";
constexpr char kDefaultConfigFileName[] = "/pkg/data/netconnector.config";
}  // namespace

NetConnectorParams::NetConnectorParams(const fxl::CommandLine& command_line) {
  is_valid_ = false;

  listen_ = command_line.HasOption("listen");
  show_devices_ = command_line.HasOption("show-devices");
  mdns_verbose_ = command_line.HasOption("mdns-verbose");

  if (listen_ && show_devices_) {
    FXL_LOG(ERROR) << "--listen and --show-devices are mutually exclusive";
    Usage();
    return;
  }

  std::string config_file_name;
  if (!command_line.GetOptionValue("config", &config_file_name)) {
    config_file_name = kDefaultConfigFileName;
  }

  if (config_file_name.empty()) {
    Usage();
    return;
  }

  if (listen_ && !ReadConfigFrom(config_file_name)) {
    FXL_LOG(ERROR) << "Failed to parse config file " << config_file_name;
    return;
  }

  is_valid_ = true;
}

void NetConnectorParams::Usage() {
  FXL_LOG(INFO) << "netconnector usage:";
  FXL_LOG(INFO) << "    netconnector [ options ]";
  FXL_LOG(INFO) << "options:";
  FXL_LOG(INFO)
      << "    --config=<file>                  read config file (default "
      << kDefaultConfigFileName << ")";
  FXL_LOG(INFO) << "    --show-devices                   show known devices";
  FXL_LOG(INFO) << "    --mdns-verbose                   log mDNS traffic";
  FXL_LOG(INFO) << "    --listen                         run as listener";
}

void NetConnectorParams::RegisterService(
    const std::string& name, fuchsia::sys::LaunchInfoPtr launch_info) {
  auto result =
      launch_infos_by_service_name_.emplace(name, std::move(launch_info));

  if (!result.second) {
    FXL_DCHECK(result.first != launch_infos_by_service_name_.end());
    result.first->second = std::move(launch_info);
  }
}

void NetConnectorParams::RegisterDevice(const std::string& name,
                                        const inet::IpAddress& address) {
  auto result = device_addresses_by_name_.emplace(name, address);

  if (!result.second) {
    FXL_DCHECK(result.first != device_addresses_by_name_.end());
    result.first->second = address;
  }
}

void NetConnectorParams::UnregisterDevice(const std::string& name) {
  device_addresses_by_name_.erase(name);
}

bool NetConnectorParams::ReadConfigFrom(const std::string& config_file_name) {
  std::string config_file_contents;
  return files::ReadFileToString(config_file_name, &config_file_contents) &&
         ParseConfig(config_file_contents);
}

bool NetConnectorParams::ParseConfig(const std::string& string) {
  rapidjson::Document document;
  document.Parse(string.data(), string.size());
  if (!document.IsObject())
    return false;

  auto iter = document.FindMember(kConfigServices);
  if (iter != document.MemberEnd()) {
    const auto& value = iter->value;
    if (!value.IsObject()) {
      return false;
    }

    for (const auto& pair : value.GetObject()) {
      if (!pair.name.IsString()) {
        return false;
      }

      auto launch_info = fuchsia::sys::LaunchInfo::New();
      if (pair.value.IsString()) {
        launch_info->url = pair.value.GetString();
      } else if (pair.value.IsArray()) {
        const auto& array = pair.value.GetArray();

        if (array.Empty() || !array[0].IsString()) {
          return false;
        }

        launch_info->url = array[0].GetString();
        for (size_t i = 1; i < array.Size(); ++i) {
          if (!array[i].IsString()) {
            return false;
          }

          launch_info->arguments.push_back(array[i].GetString());
        }
      } else {
        return false;
      }

      RegisterService(pair.name.GetString(), std::move(launch_info));
    }
  }

  iter = document.FindMember(kConfigDevices);
  if (iter != document.MemberEnd()) {
    const auto& value = iter->value;
    if (!value.IsObject()) {
      return false;
    }

    for (const auto& pair : value.GetObject()) {
      if (!pair.name.IsString() || !pair.value.IsString()) {
        return false;
      }

      inet::IpAddress address =
          inet::IpAddress::FromString(pair.value.GetString());
      if (!address.is_valid()) {
        FXL_LOG(ERROR) << "Config file contains invalid IP address "
                       << pair.value.GetString();
        return false;
      }

      RegisterDevice(pair.name.GetString(), address);
    }
  }

  return true;
}

}  // namespace netconnector
