// Copyright 2024 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 "system/system.h"

#include "device/bme688.h"
#include "device/ltr559_light_and_prox_sensor.h"
#include "device/pico_board.h"
#include "hardware/adc.h"
#include "hardware/exception.h"
#include "modules/air_sensor/air_sensor.h"
#include "modules/buttons/manager.h"
#include "pico/stdlib.h"
#include "pw_channel/rp2_stdio_channel.h"
#include "pw_cpu_exception/entry.h"
#include "pw_digital_io_rp2040/digital_io.h"
#include "pw_i2c_rp2040/initiator.h"
#include "pw_multibuf/simple_allocator.h"
#include "pw_system/system.h"
#if defined(PICO_RP2040) && PICO_RP2040
#include "system_RP2040.h"
#endif  // defined(PICO_RP2040) && PICO_RP2040
#if defined(PICO_RP2350) && PICO_RP2350
#include "RP2350.h"
#include "system_RP2350.h"
#endif  // defined(PICO_RP2350) && PICO_RP2350
#include "system/pubsub.h"
#include "system/worker.h"
#include "targets/rp2/enviro_pins.h"

using pw::digital_io::Rp2040DigitalIn;

namespace sense::system {
namespace {

pw::i2c::Initiator& I2cInitiator() {
  static constexpr pw::i2c::Rp2040Initiator::Config kI2c0Config{
      .clock_frequency_hz = 400'000,
      .sda_pin = board::kEnviroPinSda,
      .scl_pin = board::kEnviroPinScl,
  };

  static pw::i2c::Initiator& i2c0_bus = []() -> pw::i2c::Initiator& {
    static pw::i2c::Rp2040Initiator bus(kI2c0Config, i2c0);
    bus.Enable();
    return bus;
  }();

  return i2c0_bus;
}

Ltr559ProxAndLightSensorImpl& Ltr559() {
  static Ltr559ProxAndLightSensorImpl sensor(I2cInitiator());
  return sensor;
}

}  // namespace

namespace {
Rp2040DigitalIn io_sw_a({
    .pin = board::kEnviroPinSwA,
    .polarity = pw::digital_io::Polarity::kActiveLow,
    .enable_pull_up = true,
});

Rp2040DigitalIn io_sw_b({
    .pin = board::kEnviroPinSwB,
    .polarity = pw::digital_io::Polarity::kActiveLow,
    .enable_pull_up = true,
});

Rp2040DigitalIn io_sw_x({
    .pin = board::kEnviroPinSwX,
    .polarity = pw::digital_io::Polarity::kActiveLow,
    .enable_pull_up = true,
});

Rp2040DigitalIn io_sw_y({
    .pin = board::kEnviroPinSwY,
    .polarity = pw::digital_io::Polarity::kActiveLow,
    .enable_pull_up = true,
});
}  // namespace

void Init() {
  // PICO_SDK inits.
  SystemInit();
  stdio_init_all();
  setup_default_uart();
  stdio_usb_init();
  adc_init();

  // Install the CPU exception handler.
  exception_set_exclusive_handler(HARDFAULT_EXCEPTION, pw_cpu_exception_Entry);
#if defined(PICO_RP2350) && PICO_RP2350
  // TODO: b/373723963 - The pico sdk exception_number enum doesn't currently
  // have values for MemManage, BusFault or UsageFault, so cast the values for
  // now until pico sdk has been updated.
  // Enable the MemManage handler
  SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
  exception_set_exclusive_handler(static_cast<exception_number>(4),
                                  pw_cpu_exception_Entry);
  // Enable the BusFault handler
  SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
  exception_set_exclusive_handler(static_cast<exception_number>(5),
                                  pw_cpu_exception_Entry);
  // Enable the UsageFault handler
  SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk;
  exception_set_exclusive_handler(static_cast<exception_number>(6),
                                  pw_cpu_exception_Entry);
#endif  // defined(PICO_RP2350) && PICO_RP2350

}

void Start() {
  static std::byte channel_buffer[2048];
  static pw::multibuf::SimpleAllocator multibuf_alloc(channel_buffer,
                                                      pw::System().allocator());
  pw::SystemStart(pw::channel::Rp2StdioChannelInit(multibuf_alloc));
  PW_UNREACHABLE;
}

sense::AirSensor& AirSensor() {
  static Bme688 air_sensor(I2cInitiator(), sense::system::GetWorker());
  return air_sensor;
}

sense::Board& Board() {
  static ::sense::PicoBoard board;
  return board;
}

sense::ButtonManager& ButtonManager() {
  static ::sense::ButtonManager manager(io_sw_a, io_sw_b, io_sw_x, io_sw_y);
  return manager;
}

sense::AmbientLightSensor& AmbientLightSensor() { return Ltr559(); }

sense::ProximitySensor& ProximitySensor() { return Ltr559(); }

}  // namespace sense::system
