// 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 <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_span/span.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::RpcChannelOutput 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 rpc_channels[] = {
    pw::rpc::Channel::Create<1>(&hdlc_channel_output)};

// Declare the pw_rpc server with the HDLC channel.
pw::rpc::Server server(rpc_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: %llu",
                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());
}

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