/* Copyright (c) 2025, Canaan Bright Sight Co., Ltd
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstddef>
#include <cstdint>
#include <cstdio>
#include "api/Ticker.h"
#include "hal_syscall.h"

namespace arduino {

// 静态成员初始化
drv_soft_timer_inst_t* Ticker::_shared_timer = nullptr;
Ticker::TickerNode* Ticker::_ticker_list_head = nullptr;
volatile uint64_t Ticker::_tick_count = 0;
volatile bool Ticker::_timer_initialized = false;
std::atomic<int> Ticker::_ticker_count(0);
pthread_mutex_t Ticker::_param_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t Ticker::_init_lock = PTHREAD_MUTEX_INITIALIZER;

Ticker::Ticker(): _node(nullptr) {
    _ticker_count.fetch_add(1);
}

Ticker::~Ticker() {
    detach();

    // 当最后一个 Ticker 被销毁时，清理共享资源
    if (_ticker_count.fetch_sub(1) == 1) {  // 如果减1后为0
        _cleanup_shared_timer();
    }
}

bool Ticker::_init_shared_timer() {
    pthread_mutex_lock(&_init_lock);

    if (_timer_initialized) {
        pthread_mutex_unlock(&_init_lock);
        return true;
    }

    bool success = false;

    do {
        if (0 != drv_soft_timer_create(&_shared_timer)) {
            printf("%s: drv_soft_timer_create failed\n", __func__);
            break;
        }

        if (0 != drv_soft_timer_register_irq(_shared_timer, _timer_callback, nullptr)) {
            printf("%s: drv_soft_timer_register_irq failed\n", __func__);
            drv_soft_timer_destroy(&_shared_timer);
            _shared_timer = nullptr;
            break;
        }

        // 设置1ms周期
        if (0 != drv_soft_timer_set_period(_shared_timer, 1)) {
            printf("%s: drv_soft_timer_set_period failed\n", __func__);
            drv_soft_timer_unregister_irq(_shared_timer);
            drv_soft_timer_destroy(&_shared_timer);
            _shared_timer = nullptr;
            break;
        }

        if (0 != drv_soft_timer_set_mode(_shared_timer, HWTIMER_MODE_PERIOD)) {
            printf("%s: drv_soft_timer_set_mode period failed\n", __func__);
            drv_soft_timer_unregister_irq(_shared_timer);
            drv_soft_timer_destroy(&_shared_timer);
            _shared_timer = nullptr;
            break;
        }

        if (0 != drv_soft_timer_start(_shared_timer)) {
            printf("%s: drv_soft_timer_start failed\n", __func__);
            drv_soft_timer_unregister_irq(_shared_timer);
            drv_soft_timer_destroy(&_shared_timer);
            _shared_timer = nullptr;
            break;
        }

        _tick_count = 0;
        _timer_initialized = true;
        success = true;

    } while(0);

    pthread_mutex_unlock(&_init_lock);
    return success;
}

void Ticker::_cleanup_shared_timer() {
    pthread_mutex_lock(&_init_lock);

    if (!_timer_initialized) {
        pthread_mutex_unlock(&_init_lock);
        return;
    }

    // 停止并销毁定时器
    if (_shared_timer) {
        drv_soft_timer_stop(_shared_timer);
        drv_soft_timer_unregister_irq(_shared_timer);
        drv_soft_timer_destroy(&_shared_timer);
        _shared_timer = nullptr;
    }

    // 清理所有节点
    pthread_mutex_lock(&_param_lock);
    while (_ticker_list_head) {
        TickerNode* next = _ticker_list_head->next;
        delete _ticker_list_head;
        _ticker_list_head = next;
    }
    pthread_mutex_unlock(&_param_lock);

    _timer_initialized = false;
    _tick_count = 0;

    pthread_mutex_unlock(&_init_lock);
}

void Ticker::_timer_callback(void* arg) {
    // 递增tick计数 - 使用中断禁用保护
    uint32_t level = rt_hw_interrupt_disable();
    uint64_t current_tick = ++_tick_count;
    rt_hw_interrupt_enable(level);

    TickerNode* node = _ticker_list_head;
    while (node) {
        TickerNode* next_node = node->next;  // 先保存next，防止回调中节点被删除

        if (node->active) {
            // 计算应该触发的次数
            uint64_t elapsed_us = (current_tick - node->start_tick) * 1000;  // 转换为微秒
            uint64_t expected_triggers = elapsed_us / node->period_us;

            // 如果需要触发
            if (expected_triggers > node->trigger_count) {
                node->trigger_count = expected_triggers;

                // 如果是once模式，先标记为非活动
                if (!node->repeat) {
                    node->active = false;
                }

                if (node->callback) {
                    node->callback(node->arg);
                }
            }
        }
        node = next_node;
    }

    pthread_mutex_unlock(&_param_lock);
}

void Ticker::_attach_us(uint64_t micros, bool repeat, callback_with_arg_t callback, void *arg) {
    // 先分离之前的定时器
    detach();

    // 初始化共享定时器（如果还没有初始化）
    if (!_init_shared_timer()) {
        return;
    }

    // 最小1000微秒（1ms）
    if (micros < 1000) {
        micros = 1000;
    }

    // 创建新节点
    _node = new TickerNode();
    if (!_node) {
        printf("%s: Failed to allocate TickerNode\n", __func__);
        return;
    }

    // 获取当前tick的快照
    uint32_t level = rt_hw_interrupt_disable();
    uint64_t current_tick = _tick_count;
    rt_hw_interrupt_enable(level);

    _node->ticker = this;
    _node->callback = callback;
    _node->arg = arg;
    _node->period_us = micros;
    _node->start_tick = current_tick;
    _node->trigger_count = 0;
    _node->repeat = repeat;
    _node->active = true;
    _node->next = nullptr;

    // 添加到链表
    _add_ticker(_node);
}

void Ticker::_add_ticker(TickerNode* node) {
    if (!node) return;

    pthread_mutex_lock(&_param_lock);
    node->next = _ticker_list_head;
    _ticker_list_head = node;
    pthread_mutex_unlock(&_param_lock);
}

void Ticker::_remove_ticker(TickerNode* node) {
    if (!node) return;

    pthread_mutex_lock(&_param_lock);

    if (_ticker_list_head == node) {
        _ticker_list_head = node->next;
    } else {
        TickerNode* prev = _ticker_list_head;
        while (prev && prev->next != node) {
            prev = prev->next;
        }
        if (prev) {
            prev->next = node->next;
        }
    }

    pthread_mutex_unlock(&_param_lock);
}

void Ticker::detach() {
    if (_node) {
        // 先标记为非活动，防止在回调中被触发
        _node->active = false;

        // 从链表中移除
        _remove_ticker(_node);

        // 删除节点
        delete _node;
        _node = nullptr;
        _callback_function = nullptr;
    }
}

bool Ticker::active() const {
    if (!_node) {
        return false;
    }

    bool is_active = _node->active;

    return is_active;
}

void Ticker::_static_callback(void *arg) {
    Ticker *_this = reinterpret_cast<Ticker *>(arg);
    if (_this && _this->_callback_function) {
        _this->_callback_function();
    }
}

}
