/*
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "scripted_beacon.h"

#include <fstream>
#include <cstdint>
#include <unistd.h>

#include "model/devices/scripted_beacon_ble_payload.pb.h"
#include "model/setup/device_boutique.h"
#include "os/log.h"

#ifdef _WIN32
#define F_OK 00
#define R_OK 04
#endif

using std::vector;
using std::chrono::steady_clock;
using std::chrono::system_clock;

namespace test_vendor_lib {
bool ScriptedBeacon::registered_ =
    DeviceBoutique::Register("scripted_beacon", &ScriptedBeacon::Create);
ScriptedBeacon::ScriptedBeacon() {
  advertising_interval_ms_ = std::chrono::milliseconds(1280);
  properties_.SetLeAdvertisementType(0x02 /* SCANNABLE */);
  properties_.SetLeAdvertisement({
      0x18,  // Length
      0x09 /* TYPE_NAME_CMPL */,
      'g',
      'D',
      'e',
      'v',
      'i',
      'c',
      'e',
      '-',
      's',
      'c',
      'r',
      'i',
      'p',
      't',
      'e',
      'd',
      '-',
      'b',
      'e',
      'a',
      'c',
      'o',
      'n',
      0x02,  // Length
      0x01 /* TYPE_FLAG */,
      0x4 /* BREDR_NOT_SPT */ | 0x2 /* GEN_DISC_FLAG */,
  });

  properties_.SetLeScanResponse({0x05,  // Length
                                 0x08,  // TYPE_NAME_SHORT
                                 'g', 'b', 'e', 'a'});
  LOG_INFO("Scripted_beacon registered %s", registered_ ? "true" : "false");
}

bool has_time_elapsed(steady_clock::time_point time_point) {
  return steady_clock::now() > time_point;
}

void ScriptedBeacon::Initialize(const vector<std::string>& args) {
  if (args.size() < 2) {
    LOG_ERROR(
        "Initialization failed, need mac address, playback and playback events "
        "file arguments");
    return;
  }

  Address addr{};
  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);

  if (args.size() < 4) {
    LOG_ERROR(
        "Initialization failed, need playback and playback events file "
        "arguments");
  }
  config_file_ = args[2];
  events_file_ = args[3];
  set_state(PlaybackEvent::INITIALIZED);
}

void ScriptedBeacon::populate_event(PlaybackEvent * event, PlaybackEvent::PlaybackEventType type) {
  LOG_INFO("Adding event: %d", type);
  event->set_type(type);
  event->set_secs_since_epoch(system_clock::now().time_since_epoch().count());
}

// Adds events to events file; we won't be able to post anything to the file
// until we set to permissive mode in tests. No events are posted until then.
void ScriptedBeacon::set_state(PlaybackEvent::PlaybackEventType state) {
  PlaybackEvent event;
  current_state_ = state;
  if (!events_ostream_.is_open()) {
    events_ostream_.open(events_file_, std::ios::out | std::ios::binary | std::ios::trunc);
    if (!events_ostream_.is_open()) {
      LOG_INFO("Events file not opened yet, for event: %d", state);
      return;
    }
  }
  populate_event(&event, state);
  event.SerializeToOstream(&events_ostream_);
  events_ostream_.flush();
}

void ScriptedBeacon::TimerTick() {
  switch (current_state_) {
    case PlaybackEvent::INITIALIZED:
      Beacon::TimerTick();
      break;
    case PlaybackEvent::SCANNED_ONCE:
      next_check_time_ =
          steady_clock::now() + steady_clock::duration(std::chrono::seconds(1));
      set_state(PlaybackEvent::WAITING_FOR_FILE);
      break;
    case PlaybackEvent::WAITING_FOR_FILE:
      if (!has_time_elapsed(next_check_time_)) {
        return;
      }
      next_check_time_ =
          steady_clock::now() + steady_clock::duration(std::chrono::seconds(1));
      if (access(config_file_.c_str(), F_OK) == -1) {
        return;
      }
      set_state(PlaybackEvent::WAITING_FOR_FILE_TO_BE_READABLE);
      break;
    case PlaybackEvent::WAITING_FOR_FILE_TO_BE_READABLE:
      if (access(config_file_.c_str(), R_OK) == -1) {
        return;
      }
      set_state(PlaybackEvent::PARSING_FILE);
      break;
    case PlaybackEvent::PARSING_FILE: {
      if (!has_time_elapsed(next_check_time_)) {
        return;
      }
      std::fstream input(config_file_, std::ios::in | std::ios::binary);
      if (!ble_ad_list_.ParseFromIstream(&input)) {
        LOG_ERROR("Cannot parse playback file %s", config_file_.c_str());
        set_state(PlaybackEvent::FILE_PARSING_FAILED);
        return;
      } else {
        set_state(PlaybackEvent::PLAYBACK_STARTED);
        LOG_INFO("Starting Ble advertisement playback from file: %s",
                 config_file_.c_str());
        next_ad_.ad_time = steady_clock::now();
        get_next_advertisement();
        input.close();
      }
    } break;
    case PlaybackEvent::PLAYBACK_STARTED: {
      while (has_time_elapsed(next_ad_.ad_time)) {
        auto ad = model::packets::LeAdvertisementBuilder::Create(
            next_ad_.address, Address::kEmpty /* Destination */,
            model::packets::AddressType::RANDOM,
            model::packets::AdvertisementType::ADV_NONCONN_IND, next_ad_.ad);
        SendLinkLayerPacket(std::move(ad), Phy::Type::LOW_ENERGY);
        if (packet_num_ < ble_ad_list_.advertisements().size()) {
          get_next_advertisement();
        } else {
          set_state(PlaybackEvent::PLAYBACK_ENDED);
          if (events_ostream_.is_open()) {
            events_ostream_.close();
          }
          LOG_INFO(
              "Completed Ble advertisement playback from file: %s with %d "
              "packets",
              config_file_.c_str(), packet_num_);
          break;
        }
      }
    } break;
    case PlaybackEvent::FILE_PARSING_FAILED:
    case PlaybackEvent::PLAYBACK_ENDED:
    case PlaybackEvent::UNKNOWN:
      return;
  }
}

void ScriptedBeacon::IncomingPacket(
    model::packets::LinkLayerPacketView packet) {
  if (current_state_ == PlaybackEvent::INITIALIZED) {
    if (packet.GetDestinationAddress() == properties_.GetLeAddress() &&
        packet.GetType() == model::packets::PacketType::LE_SCAN) {
      auto scan_response = model::packets::LeScanResponseBuilder::Create(
          properties_.GetLeAddress(), packet.GetSourceAddress(),
          static_cast<model::packets::AddressType>(
              properties_.GetLeAddressType()),
          model::packets::AdvertisementType::SCAN_RESPONSE,
          properties_.GetLeScanResponse());
      set_state(PlaybackEvent::SCANNED_ONCE);
      SendLinkLayerPacket(std::move(scan_response), Phy::Type::LOW_ENERGY);
    }
  }
}

void ScriptedBeacon::get_next_advertisement() {
  std::string payload = ble_ad_list_.advertisements(packet_num_).payload();
  std::string mac_address =
      ble_ad_list_.advertisements(packet_num_).mac_address();
  uint32_t delay_before_send_ms =
      ble_ad_list_.advertisements(packet_num_).delay_before_send_ms();
  next_ad_.ad.assign(payload.begin(), payload.end());
  if (Address::IsValidAddress(mac_address)) {
    // formatted string with colons like "12:34:56:78:9a:bc"
    Address::FromString(mac_address, next_ad_.address);
  } else if (mac_address.size() == Address::kLength) {
    // six-byte binary address
    std::vector<uint8_t> mac_vector(mac_address.cbegin(), mac_address.cend());
    next_ad_.address.Address::FromOctets(mac_vector.data());
  } else {
    Address::FromString("BA:D0:AD:BA:D0:AD", next_ad_.address);
  }
  next_ad_.ad_time +=
      steady_clock::duration(std::chrono::milliseconds(delay_before_send_ms));
  packet_num_++;
}
}  // namespace test_vendor_lib
