// Copyright 2022 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 "app_common/common.h"
#include "pw_digital_io_arduino/digital_io.h"
#include "pw_display_driver_ili9341/display_driver.h"
#include "pw_spi_arduino/chip_selector.h"
#include "pw_spi_arduino/initiator.h"
#include "pw_sync/borrow.h"
#include "pw_sync/mutex.h"

using pw::Status;
using pw::display::Display;
using DisplayDriver = pw::display_driver::DisplayDriverILI9341;
using pw::framebuffer::Framebuffer;
using pw::spi::Device;
using pw::spi::Initiator;
using pw::sync::Borrowable;
using pw::sync::VirtualMutex;
using DigitalOut = pw::digital_io::ArduinoDigitalOut;
using SpiChipSelector = pw::spi::ArduinoChipSelector;
using SpiInitiator = pw::spi::ArduinoInitiator;

namespace {

struct SpiValues {
  SpiValues(pw::spi::Config config,
            pw::spi::ChipSelector& selector,
            pw::sync::VirtualMutex& initiator_mutex);

  pw::spi::ArduinoInitiator initiator;
  pw::sync::Borrowable<pw::spi::Initiator> borrowable_initiator;
  pw::spi::Device device;
};

static_assert(DISPLAY_WIDTH > 0);
static_assert(DISPLAY_HEIGHT > 0);

constexpr uint16_t kFramebufferWidth =
    FRAMEBUFFER_WIDTH >= 0 ? FRAMEBUFFER_WIDTH : DISPLAY_WIDTH;
constexpr uint16_t kFramebufferHeight = DISPLAY_HEIGHT;

constexpr pw::geometry::Size<uint16_t> kDisplaySize = {DISPLAY_WIDTH,
                                                       DISPLAY_HEIGHT};
constexpr size_t kNumPixels = kFramebufferWidth * kFramebufferHeight;
constexpr uint16_t kDisplayRowBytes = sizeof(uint16_t) * kFramebufferWidth;

constexpr pw::spi::Config kSpiConfig8Bit{
    .polarity = pw::spi::ClockPolarity::kActiveHigh,
    .phase = pw::spi::ClockPhase::kFallingEdge,
    .bits_per_word = pw::spi::BitsPerWord(8),
    .bit_order = pw::spi::BitOrder::kMsbFirst,
};
constexpr pw::spi::Config kSpiConfig16Bit{
    .polarity = pw::spi::ClockPolarity::kActiveHigh,
    .phase = pw::spi::ClockPhase::kFallingEdge,
    .bits_per_word = pw::spi::BitsPerWord(16),
    .bit_order = pw::spi::BitOrder::kMsbFirst,
};

DigitalOut s_display_dc_pin({
    .pin = DISPLAY_DC_GPIO,
    .polarity = pw::digital_io::Polarity::kActiveHigh,
});
#if DISPLAY_RESET_GPIO != -1
DigitalOut s_display_reset_pin({
    .pin = DISPLAY_RESET_GPIO,
    .polarity = pw::digital_io::Polarity::kActiveLow,
});
#endif
DigitalOut s_display_cs_pin({
    .pin = DISPLAY_CS_GPIO,
    .polarity = pw::digital_io::Polarity::kActiveLow,
});
SpiChipSelector s_spi_chip_selector(s_display_cs_pin);
SpiInitiator s_spi_initiator;
VirtualMutex s_spi_initiator_mutex;
Borrowable<Initiator> s_borrowable_spi_initiator(s_spi_initiator,
                                                 s_spi_initiator_mutex);
SpiValues s_spi_8_bit(kSpiConfig8Bit,
                      s_spi_chip_selector,
                      s_spi_initiator_mutex);
SpiValues s_spi_16_bit(kSpiConfig16Bit,
                       s_spi_chip_selector,
                       s_spi_initiator_mutex);
uint16_t s_pixel_data[kNumPixels];
const pw::Vector<void*, 1> s_pixel_buffers{s_pixel_data};
pw::framebuffer_pool::FramebufferPool s_fb_pool({
    .fb_addr = s_pixel_buffers,
    .size = {kFramebufferWidth, kFramebufferHeight},
    .row_bytes = kDisplayRowBytes,
    .start = {0, 0},
});
DisplayDriver s_display_driver({
    .data_cmd_gpio = s_display_dc_pin,
#if DISPLAY_RESET_GPIO != -1
    .reset_gpio = &s_display_reset_pin,
#else
    .reset_gpio = nullptr,
#endif
    .spi_device_8_bit = s_spi_8_bit.device,
    .spi_device_16_bit = s_spi_16_bit.device,
});
Display s_display(s_display_driver, kDisplaySize, s_fb_pool);

SpiValues::SpiValues(pw::spi::Config config,
                     pw::spi::ChipSelector& selector,
                     pw::sync::VirtualMutex& initiator_mutex)
    : borrowable_initiator(initiator, initiator_mutex),
      device(borrowable_initiator, config, selector) {}

}  // namespace

// static
Status Common::Init() {
  s_display_cs_pin.Enable();
  s_display_dc_pin.Enable();
#if DISPLAY_RESET_GPIO != -1
  s_display_reset_pin.Enable();
#endif

  SPI.begin();

  return s_display_driver.Init();
}

// static
pw::display::Display& Common::GetDisplay() { return s_display; }
