// Copyright 2021 The Pigweed Authors
//
// 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
//
//     https://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 <array>
#include <span>
#include <string_view>

#include "pw_board_led/led.h"
#include "pw_hdlc/encoder.h"
#include "pw_hdlc/rpc_channel.h"
#include "pw_hdlc/rpc_packets.h"
#include "pw_log/log.h"
#include "pw_rpc/echo_service_nanopb.h"
#include "pw_rpc/server.h"
#include "pw_spin_delay/delay.h"
#include "pw_stream/sys_io_stream.h"
#include "remoticon/remoticon_service_nanopb.h"

// ------------------- superloop data -------------------
// This is some "application" state that eventually exported by RPCs.

unsigned superloop_iterations;

// ------------------- pw_rpc subsystem setup -------------------
// There are multiple ways to plumb pw_rpc in your product. In the future,
// Pigweed may offer an optional pre-canned setup; but for now, you must
// manually snap together the modular pieces.
//
// The RPC system in this code is layered as:
//
//   UART --> pw_sys_io ------> hdlc -------> pw_rpc
//   (phy)                   (transport)
//
// HDLC converts the raw UART/serial byte stream into a packet stream. Then RPC
// operates at the packet level.
//
// This is just one way to configure pw_rpc, which is designed to be flexible
// and work over wh atever physical or logical transport you have available.

constexpr size_t kMaxTransmissionUnit = 256;  // bytes

// Used to write HDLC data to pw::sys_io. This is an implementation of the
// pw::stream::Stream interface.
pw::stream::SysIoWriter sys_io_writer;

// Set up the output channel for the pw_rpc server to use. This one happens to
// implement the packet in / packet out with HDLC. pw_rpc can use any
// ChannelOptput implementation, including custom ones for your product.
pw::hdlc::RpcChannelOutputBuffer<kMaxTransmissionUnit> hdlc_channel_output(
    sys_io_writer, pw::hdlc::kDefaultRpcAddress, "HDLC channel");

// A pw::rpc::Server can have multiple channels (e.g. a UART and a BLE
// connection). In this case, there is only one (HDLC over UART).
pw::rpc::Channel channels[] = {
    pw::rpc::Channel::Create<1>(&hdlc_channel_output)};

// Declare the pw_rpc server with the HDLC channel.
pw::rpc::Server server(channels);

// Declare a buffer for decoding incoming HDLC frames.
std::array<std::byte, kMaxTransmissionUnit> input_buffer;

// Decoder object consumes bytes and return if a HDLC packet was completed.
pw::hdlc::Decoder hdlc_decoder(input_buffer);

// ------------------- pw_rpc service registration  -------------------
pw::rpc::EchoService echo_service;
remoticon::SuperloopService superloop_service(superloop_iterations);

// TODO FOR WORKSHOP: Declare your service object here!

void RegisterServices() {
  server.RegisterService(echo_service);
  server.RegisterService(superloop_service);
  // TODO FOR WORKSHOP: Register your service here!
}

// ------------------- pw_rpc  -------------------

constexpr unsigned kHdlcChannelForRpc = pw::hdlc::kDefaultRpcAddress;
constexpr unsigned kHdlcChannelForLogs = 1;

void ParseByteFromUartAndHandleRpcs() {
  // Read a byte from the UART if one is available; if not, bail.
  std::byte data;
  if (!pw::sys_io::TryReadByte(&data).ok()) {
    return;
  }

  // Byte received. Send the byte to the HDLC decoder; see if a packet finished.
  auto result = hdlc_decoder.Process(data);

  // Packet didn't parse correctly, so ignore it. In production, this should
  // perhaps log or increment a metric (see pw_metric) to track bad packets.
  if (!result.ok()) {
    // POST-WORKSHOP EXERCISE: Add a tracking metric for bad packets, and
    // expose the metric via the pw_metric RPC service. This will require
    // making some metrics objects, incrementing them; then creating and
    // registering a metric RPC service.
    //
    // See https://pigweed.dev/pw_metric/
    //     https://pigweed.dev/pw_metric/#exporting-metrics
    return;
  }

  PW_LOG_INFO("Got complete HDLC packet");

  // A frame was completed.
  pw::hdlc::Frame& hdlc_frame = result.value();
  if (hdlc_frame.address() != kHdlcChannelForRpc) {
    // We ignore frames that are for unknown addresses, but you could put
    // some code here if you wanted to stream custom data from PC --> device.
    PW_LOG_WARN("Got packet with no destination; address: %d",
                hdlc_frame.address());
    return;
  }

  // Packet was validated and correct (CRC, etc); so send it to the RPC server.
  // The RPC server may send response packets before returning from this call.
  server.ProcessPacket(hdlc_frame.data(), hdlc_channel_output);
}

// TODO FOR WORKSHOP: Add an RPC to change the blink time.
int state = 0;
int counter = 0;
// TODO FOR WORKSHOP: Change this value. 5M is good for Teensy 4.0; what value
// is good for the Discovery?
int counter_max = 5'000'000;

void Blink() {
  // Toggle the state if needed.
  counter += 1;
  // PW_LOG_INFO("Counter: %d", counter);
  if (counter < counter_max) {
    // Haven't hit a toggle event yet; bail.
    return;
  }
  state = 1 - state;
  counter = 0;

  if (state == 0) {
    PW_LOG_INFO("Blink High!");
    pw::board_led::TurnOn();
  } else {
    PW_LOG_INFO("Blink Low!");
    pw::board_led::TurnOff();
  }
}

// TODO FOR WORKSHOP: Why doesn't this work, when of Blink() above does?
void BlinkNoWorky() {
  PW_LOG_INFO("Blink High!");
  pw::board_led::TurnOn();
  pw::spin_delay::WaitMillis(1000);

  PW_LOG_INFO("Blink Low!");
  pw::board_led::TurnOff();
  pw::spin_delay::WaitMillis(1000);
}

int main() {
  pw::board_led::Init();

  PW_LOG_INFO("Registering pw_rpc services");
  RegisterServices();

  // Superloop!
  while (true) {
    // Toggle the LED if needed.
    Blink();
    // BlinkNoWorky();  // Pop quiz: This doesn't work. Why?

    // Examine incoming serial byte; if a packet finished, send it to RPC.
    ParseByteFromUartAndHandleRpcs();

    // Increment the number of iterations.
    superloop_iterations++;
  }

  return 0;
}
