#include <freertos/FreeRTOS.h>
#include <driver/i2s.h>

#include <Wire.h>
#include <WiFi.h>
#include <Arduino.h>


namespace mk
{
    bool contains_only_zeros(std::vector<uint16_t>& samples)
    {
        for (auto sample : samples)
            if (sample != 0)
                return false;
        return true;
    }

    void app_main_cpp()
    {
        auto enable_wifi = true;

        if (enable_wifi)
        {
            initArduino();
            WiFi.enableSTA(true);
            if (WiFi.begin() == WL_CONNECT_FAILED)
                WiFi.begin("Micky53-v2", "exoticbird639");
            WiFi.waitStatusBits(STA_HAS_IP_BIT, UINT32_MAX);
        }


        auto iteration = 0;
        while (true)
        {
            iteration++;

            {
                i2s_config_t i2s_config;
                i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN);
                i2s_config.sample_rate = 1000000;
                i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
                i2s_config.communication_format = I2S_COMM_FORMAT_I2S_MSB;
                i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
                i2s_config.intr_alloc_flags = 0;
                i2s_config.dma_buf_count = 2;
                i2s_config.dma_buf_len = 1024;
                i2s_config.use_apll = false;

                auto status = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, nullptr);
                ESP_ERROR_CHECK(status);

                status = i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_6);
                ESP_ERROR_CHECK(status);

                status = i2s_adc_enable(I2S_NUM_0);
                ESP_ERROR_CHECK(status);


                std::vector<uint16_t> samples;
                samples.resize(2048);

                size_t bytes_read;
                status = i2s_read(I2S_NUM_0, samples.data(), samples.size() * sizeof(uint16_t), &bytes_read, 100 / portTICK_PERIOD_MS);
                ESP_ERROR_CHECK(status);
                samples.resize(bytes_read / 2);

                if (contains_only_zeros(samples))
                    ESP_LOGE("adc_test", "iteration: %d, samples count: %d, all zeros", iteration, samples.size());
                else
                    ESP_LOGI("adc_test", "iteration: %d, samples count: %d, ok", iteration, samples.size());


                status = i2s_adc_disable(I2S_NUM_0);
                ESP_ERROR_CHECK(status);

                status = i2s_driver_uninstall(I2S_NUM_0);
                ESP_ERROR_CHECK(status);
            }

            sleep(1);
        }
    }

    extern "C" void app_main()
    {
        try
        {
            app_main_cpp();
        }
        catch (std::exception& ex)
        {
            ESP_LOGE("adc_test", "exception: %s", ex.what());
        }

        ESP_LOGI("adc_test", "Restart in 1 sec.");

        sleep(1);
        esp_restart();
    }

}
