#include "esp_system.h"
#include "esp_log.h"
#include "driver/i2c.h"

#include "H2201_i2c.h"
#include "H2201_buttons.h"
#include "H2201_V1_IC1.h"
#include "H2201_V1_IC1_PARAM.h"
#include "SigmaStudioFW.h"

SemaphoreHandle_t i2c_block_mutex = NULL;

void H2201_i2c_beep_task(void *arg)
{
    // printf("start beep task \n");
    if (xSemaphoreTake(i2c_block_mutex, (TickType_t)portMAX_DELAY) == pdTRUE)
    {
        ADI_REG_TYPE beep_on[4] = {0x00, 0x00, 0x00, 0x01};
        SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BEEPSWITCH_ISON_ADDR, 4, beep_on);
        vTaskDelay(400 / portTICK_PERIOD_MS);
        ADI_REG_TYPE beep_off[4] = {0x00, 0x00, 0x00, 0x00};
        SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BEEPSWITCH_ISON_ADDR, 4, beep_off);

        xSemaphoreGive(i2c_block_mutex);
    }
    else
    {
        printf("cannot get mutex \n");
    }
    vTaskDelete(NULL);
}
void H2201_i2c_beep(void)
{
    xTaskCreate(H2201_i2c_beep_task, "beep", 2048, NULL, configMAX_PRIORITIES - 3, NULL);
}

void H2201_i2c_doublebeep_task(void *arg)
{
    // printf("start beep task \n");
    if (xSemaphoreTake(i2c_block_mutex, (TickType_t)portMAX_DELAY) == pdTRUE)
    {
        ADI_REG_TYPE beep_on[4] = {0x00, 0x00, 0x00, 0x01};
        SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_DOUBLEBEEPSWITCH_ISON_ADDR, 4, beep_on);
        vTaskDelay(400 / portTICK_PERIOD_MS);
        ADI_REG_TYPE beep_off[4] = {0x00, 0x00, 0x00, 0x00};
        SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_DOUBLEBEEPSWITCH_ISON_ADDR, 4, beep_off);

        xSemaphoreGive(i2c_block_mutex);
    }
    else
    {
        printf("cannot get mutex \n");
    }
    vTaskDelete(NULL);
}
void H2201_i2c_doublebeep(void)
{
    xTaskCreate(H2201_i2c_doublebeep_task, "doublebeep", 2048, NULL, configMAX_PRIORITIES - 3, NULL);
}

void H2201_i2c_mastervolume_task(void *arg)
{
    uint8_t volume = (uint8_t)arg;
    if (xSemaphoreTake(i2c_block_mutex, (TickType_t)portMAX_DELAY) == pdTRUE)
    {
        printf("task master vol %u\n", volume);

        uint8_t vol = volume << R30_PB_HEADPHONE_LEFT_VOL_IC1_SHIFT;
        vol |= (1 << R30_PB_HEADPHONE_LEFT_PWRUP_IC1_SHIFT); // Headphone volume control enable.
        vol |= (1 << R30_PB_HEADPHONE_LEFT_MUTE_IC1_SHIFT);  // unmute
        SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_HEADPHONE_LEFT_IC1_ADDR, vol);

        vol &= ~(1 << R31_PB_HEADPHONE_RIGHT_PWRUP_IC1_SHIFT); // enable line output
        SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_HEADPHONE_RIGHT_IC1_ADDR, vol);

        xSemaphoreGive(i2c_block_mutex);
    }
    else
    {
        printf("cannot get mutex \n");
    }
    vTaskDelete(NULL);
}
void H2201_i2c_mastervolume(uint8_t *volume)
{
    xTaskCreate(H2201_i2c_mastervolume_task, "mastervolume", 2048, (void *)*volume, configMAX_PRIORITIES - 3, NULL);
}

void H2201_i2c_telephonevolume_task(void *arg)
{
    uint8_t volume = (uint8_t)arg;
    if (xSemaphoreTake(i2c_block_mutex, (TickType_t)portMAX_DELAY) == pdTRUE)
    {
        printf("telephone vol %u\n", volume);
        // printf("switch left %d\n", H2201_dipswitch_read(DIPSWITCH_TEL_LEFT));
        uint8_t vol = 0;
        if (H2201_dipswitch_read(DIPSWITCH_TEL_LEFT))
        {
            vol = volume << R23_PBC0_AUX_OUT_GAIN_IC1_SHIFT;
        }
        vol |= (1 << R23_PBC0_LEFT_DAC_MUTE_IC1_SHIFT); // unmute left DAC
        vol |= (1 << R23_PBC0_MIX_ENABLE_IC1_SHIFT);    // enable mixer
        // printf("vol %u\n", vol);
        SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_MIXER_LEFT_CONTROL_0_IC1_ADDR, vol);

        vol = 0;
        // printf("switch right %d\n", H2201_dipswitch_read(DIPSWITCH_TEL_RIGHT));
        if (H2201_dipswitch_read(DIPSWITCH_TEL_RIGHT))
        {
            vol = volume << R25_PBMRC0_AUX_GAIN_IC1_SHIFT;
        }
        vol |= (1 << R25_PBMRC0_R_DAC_MUTE_IC1_SHIFT); // unmute right DAC
        vol |= (1 << R25_PBMRC0_ENABLE_IC1_SHIFT);     // enable mixer
        // printf("vol %u\n", vol);
        SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLABACK_MIXER_RIGHT_CONTROL_0_IC1_ADDR, vol);

        xSemaphoreGive(i2c_block_mutex);
    }
    else
    {
        printf("cannot get mutex \n");
    }
    vTaskDelete(NULL);
}
void H2201_i2c_telephonevolume(uint8_t *volume)
{
    xTaskCreate(H2201_i2c_telephonevolume_task, "telvolume", 2048, (void *)*volume, configMAX_PRIORITIES - 3, NULL);
}

void H2201_i2c_pcvolume_task(void *arg)
{
    uint8_t volume = (uint8_t)arg;
    if (xSemaphoreTake(i2c_block_mutex, (TickType_t)portMAX_DELAY) == pdTRUE)
    {
        printf("pc vol %u\n", volume);

        bool left = H2201_dipswitch_read(DIPSWITCH_PC_LEFT);
        bool right = H2201_dipswitch_read(DIPSWITCH_PC_RIGHT);

        if (left == false && right == false)
        {
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_LEFT_CTRL_0_IC1_ADDR, 0x01);
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_RIGHT_CTRL_0_IC1_ADDR, 0x01);
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLABACK_MIXER_LEFT_CONTROL_1_IC1_ADDR, 0x00);
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_MIXER_RIGHT_CONTROL_1_IC1_ADDR, 0x00);
        }
        if (left == true && right == false)
        {
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_LEFT_CTRL_0_IC1_ADDR, 0x5B); // N = left P = right
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_RIGHT_CTRL_0_IC1_ADDR, 0x01);

            uint8_t vol = volume << 4;
            vol |= volume;
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLABACK_MIXER_LEFT_CONTROL_1_IC1_ADDR, vol);
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_MIXER_RIGHT_CONTROL_1_IC1_ADDR, 0x00);
        }
        if (left == false && right == true)
        {
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_LEFT_CTRL_0_IC1_ADDR, 0x01);
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_RIGHT_CTRL_0_IC1_ADDR, 0x5B); // N = left P = right

            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLABACK_MIXER_LEFT_CONTROL_1_IC1_ADDR, 0x00);
            uint8_t vol = volume << 4;
            vol |= volume;
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_MIXER_RIGHT_CONTROL_1_IC1_ADDR, vol);
        }
        if (left == true && right == true)
        {
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_LEFT_CTRL_0_IC1_ADDR, 0x0B);  // N = left
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_RECORD_MIXER_RIGHT_CTRL_0_IC1_ADDR, 0x51); // P = Right

            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLABACK_MIXER_LEFT_CONTROL_1_IC1_ADDR, volume);
            uint8_t vol = volume << R26_PBMRC1_R_PGA_OUT_GAIN_IC1_SHIFT;
            SIGMA_WRITE_REGISTER(DEVICE_ADDR_IC1, REG_PLAYBACK_MIXER_RIGHT_CONTROL_1_IC1_ADDR, vol);
        }

        xSemaphoreGive(i2c_block_mutex);
    }
    else
    {
        printf("cannot get mutex \n");
    }
    vTaskDelete(NULL);
}
void H2201_i2c_pcvolume(uint8_t *volume)
{
    xTaskCreate(H2201_i2c_pcvolume_task, "pcvolume", 2048, (void *)*volume, configMAX_PRIORITIES - 3, NULL);
}

void H2201_i2c_bluetoothvolume_task(void *arg)
{
    if (xSemaphoreTake(i2c_block_mutex, (TickType_t)portMAX_DELAY) == pdTRUE)
    {
        bool left = H2201_dipswitch_read(DIPSWITCH_BT_LEFT);
        bool right = H2201_dipswitch_read(DIPSWITCH_BT_RIGHT);

        ADI_REG_TYPE unmute[4] = {0x00, 0x80, 0x00, 0x00};
        ADI_REG_TYPE mute[4] = {0x00, 0x00, 0x00, 0x00};

        ADI_REG_TYPE volume[4] = {0x00, 0x00, 0x00, 0x00};

        volume[3] = (uint8_t)arg;
        printf("bluetooth vol %d\n", volume[3]);

        if (left == false && right == false)
        {
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_L_MUTENOSLEWALG1MUTE_ADDR, 4, mute); // L -L mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_R_MUTENOSLEWALG2MUTE_ADDR, 4, mute); // L -R mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_L_MUTENOSLEWALG3MUTE_ADDR, 4, mute); // R -L mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_R_MUTENOSLEWALG4MUTE_ADDR, 4, mute); // R -R mute
        }
        if (left == true && right == false)
        {
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_L_MUTENOSLEWALG1MUTE_ADDR, 4, unmute); // L -L
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_R_MUTENOSLEWALG2MUTE_ADDR, 4, mute);   // L -R mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_L_MUTENOSLEWALG3MUTE_ADDR, 4, unmute); // R -L
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_R_MUTENOSLEWALG4MUTE_ADDR, 4, mute);   // R -R mute

            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTVOLUME_DCINPALG1_ADDR, 4, volume);
        }
        if (left == false && right == true)
        {
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_L_MUTENOSLEWALG1MUTE_ADDR, 4, mute);   // L -L mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_R_MUTENOSLEWALG2MUTE_ADDR, 4, unmute); // L -R
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_L_MUTENOSLEWALG3MUTE_ADDR, 4, mute);   // R -L mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_R_MUTENOSLEWALG4MUTE_ADDR, 4, unmute); // R -R

            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTVOLUME_DCINPALG1_ADDR, 4, volume);
        }
        if (left == true && right == true)
        {
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_L_MUTENOSLEWALG1MUTE_ADDR, 4, unmute); // L -L
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTL_R_MUTENOSLEWALG2MUTE_ADDR, 4, mute);   // L -R mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_L_MUTENOSLEWALG3MUTE_ADDR, 4, mute);   // R -L mute
            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTR_R_MUTENOSLEWALG4MUTE_ADDR, 4, unmute); // R -R

            SIGMA_WRITE_REGISTER_BLOCK(DEVICE_ADDR_IC1, MOD_BTVOLUME_DCINPALG1_ADDR, 4, volume);
        }

        xSemaphoreGive(i2c_block_mutex);
    }
    else
    {
        printf("cannot get mutex \n");
    }
    vTaskDelete(NULL);
}
void H2201_i2c_bluetoothvolume(uint8_t *volume)
{
    xTaskCreate(H2201_i2c_bluetoothvolume_task, "blvolume", 2048, (void *)*volume, configMAX_PRIORITIES - 3, NULL);
}

void H2201_i2c_master_init(void)
{
    i2c_config_t i2c_config = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_DISABLE,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_DISABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
        // .clk_flags = 0,          /*!< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here. */
    };
    esp_err_t err;
    if ((err = i2c_param_config(I2C_MASTER_NUM, &i2c_config)) != ESP_OK)
    {
        ESP_LOGE(H2201_I2C_TAG, "%s i2c param config failed: %s\n", __func__, esp_err_to_name(err));
        return;
    }
    if ((err = i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0)) != ESP_OK)
    {
        ESP_LOGE(H2201_I2C_TAG, "%s i2c driver config failed: %s\n", __func__, esp_err_to_name(err));
        return;
    }

    i2c_block_mutex = xSemaphoreCreateBinary();
    xSemaphoreGive(i2c_block_mutex);
}

void H2201_i2c_adau1761_init(void)
{
    default_download_IC1();
}