// 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 "pw_display/display.h"

#include <stdio.h>
#include <stdlib.h>

#include <cinttypes>
#include <cstdint>

#define LIB_CMSIS_CORE 0
#define LIB_PICO_STDIO_USB 0
#define LIB_PICO_STDIO_SEMIHOSTING 0

#include "hardware/gpio.h"
#include "pico/stdlib.h"
#include "pw_color/color.h"
#include "pw_digital_io_pico/digital_io.h"
#include "pw_display_driver_ili9341/display_driver.h"
#include "pw_framebuffer/rgb565.h"
#include "pw_log/log.h"
#include "pw_spi_pico/chip_selector.h"
#include "pw_spi_pico/initiator.h"
#include "pw_spin_delay/delay.h"
#include "pw_sync/borrow.h"
#include "pw_sync/mutex.h"

using pw::display_driver::DisplayDriverILI9341;

namespace pw::display {

namespace {

// Pico spi0 Pins
#define SPI_PORT spi0
constexpr int TFT_SCLK = 18;  // SPI0 SCK
constexpr int TFT_MOSI = 19;  // SPI0 TX
// Unused
// const int TFT_MISO = 4;   // SPI0 RX
constexpr int TFT_CS = 9;    // SPI0 CSn
constexpr int TFT_DC = 10;   // GP10
constexpr int TFT_RST = 11;  // GP11

constexpr int kDisplayWidth = 320;
constexpr int kDisplayHeight = 240;
constexpr int kNumDisplayPixels = kDisplayWidth * kDisplayHeight;
constexpr uint32_t kBaudRate = 31'250'000;

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

class InstanceData {
 public:
  InstanceData()
      : chip_selector_gpio_(TFT_CS),
        data_cmd_gpio_(TFT_DC),
        reset_gpio_(TFT_RST),
        spi_chip_selector_(chip_selector_gpio_),
        spi_initiator_(SPI_PORT, kBaudRate),
        borrowable_spi_initiator_(spi_initiator_, spi_initiator_mutex_),
        spi_device_(borrowable_spi_initiator_, kSpiConfig, spi_chip_selector_),
        driver_config_{
            .data_cmd_gpio = data_cmd_gpio_,
            .reset_gpio = &reset_gpio_,
            .spi_device = spi_device_,
        },
        display_driver_(driver_config_) {}

  void Init() {
    InitGPIO();
    InitSPI();
    InitDisplayDriver();
  }

  void Update(pw::framebuffer::FramebufferRgb565* frame_buffer) {
    display_driver_.Update(frame_buffer);
  }

  void UpdatePixelDouble(pw::framebuffer::FramebufferRgb565* frame_buffer) {
    display_driver_.UpdatePixelDouble(frame_buffer);
  }

 private:
  void InitGPIO() {
    stdio_init_all();

    chip_selector_gpio_.Enable();
    data_cmd_gpio_.Enable();
    reset_gpio_.Enable();
  }

  void InitSPI() {
    uint actual_baudrate = spi_init(SPI_PORT, kBaudRate);
    PW_LOG_DEBUG("Actual Baudrate: %u", actual_baudrate);
    spi_set_format(SPI_PORT, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);

    // Not currently used (not yet reading from display).
    // gpio_set_function(TFT_MISO, GPIO_FUNC_SPI);
    gpio_set_function(TFT_SCLK, GPIO_FUNC_SPI);
    gpio_set_function(TFT_MOSI, GPIO_FUNC_SPI);
  }

  Status InitDisplayDriver() {
    auto s = display_driver_.Init();
    if (!s.ok())
      return s;
    // From hereon only display pixel updates are made, so switch to 16-bit
    // mode which is expected by DisplayDriver::Update();
    spi_set_format(SPI_PORT, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
    return OkStatus();
  }

  pw::digital_io::PicoDigitalOut chip_selector_gpio_;
  pw::digital_io::PicoDigitalOut data_cmd_gpio_;
  pw::digital_io::PicoDigitalOut reset_gpio_;
  pw::spi::PicoChipSelector spi_chip_selector_;
  pw::spi::PicoInitiator spi_initiator_;
  pw::sync::VirtualMutex spi_initiator_mutex_;
  pw::sync::Borrowable<pw::spi::Initiator> borrowable_spi_initiator_;
  pw::spi::Device spi_device_;
  DisplayDriverILI9341::Config driver_config_;
  DisplayDriverILI9341 display_driver_;
};  // namespace

InstanceData s_instance_data;

}  // namespace

void Init() { s_instance_data.Init(); }

int GetWidth() { return kDisplayWidth; }

int GetHeight() { return kDisplayHeight; }

void Update(pw::framebuffer::FramebufferRgb565* frame_buffer) {
  s_instance_data.Update(frame_buffer);
}

void UpdatePixelDouble(pw::framebuffer::FramebufferRgb565* frame_buffer) {
  s_instance_data.UpdatePixelDouble(frame_buffer);
}

bool TouchscreenAvailable() { return false; }

bool NewTouchEvent() { return false; }

pw::coordinates::Vec3Int GetTouchPoint() {
  return pw::coordinates::Vec3Int{0, 0, 0};
}

}  // namespace pw::display
