#include "file_delete.h"
#include "smartbox/smartbox.h"
#include "system/includes.h"
#include "system/fs/fs.h"
#include "btstack_3th_protocol_user.h"
#include "dev_manager.h"
#include "key_event_deal.h"
#include "app_task.h"
#include "common/dev_status.h"
#include "bt/bt.h"
#include "common/dev_status.h"
#include "app_task.h"
#include "app_msg.h"
#include "clock_cfg.h"
#include "file_operate/file_manager.h"
#include "browser/browser.h"
#include "music/music_player.h"

#if (SMART_BOX_EN && TCFG_DEV_MANAGER_ENABLE)

#define FILE_DELELET_TIMEOUT 				(10*1000)

#define FILE_DEL_DEBUG_EN
#ifdef FILE_DEL_DEBUG_EN
#define file_del_printf printf
#else
#define file_del_printf(...)
#endif

struct __file_del {
    struct __dev 			*dev;//当前设备节点
    struct vfscan			*fsn;//设备扫描句柄
    u8 						scandisk_break;
    u8						busy;
    u16 					timerout;
    void	(*end_callback)(void);
};

struct __file_del *file_d = NULL;
#define __this	   file_d

///播放参数，文件扫描时用，文件后缀等
static const char scan_parm[] = "-t"
#if (WATCH_FILE_TO_FLASH)
                                "ALL"
#else // WATCH_FILE_TO_FLASH
                                DEC_EXT_NAME
                                "TMP"
#endif // WATCH_FILE_TO_FLASH
                                " -sn -r"
                                ;

//*----------------------------------------------------------------------------*/
/**@brief    文件删除扫盘匹配文件过程系统消息获取处理接口
   @param
   @return   1：中断文件扫描处理， 0:继续扫盘
   @note	 可以在这个函数内相应所需的消息事件
*/
/*----------------------------------------------------------------------------*/
static int file_delete_scandisk_break(void)
{
    ///注意：
    ///需要break fsn的事件， 请在这里拦截,
    int msg[32] = {0};
    struct sys_event *event = NULL;
    char *logo = NULL;
    char *evt_logo = NULL;
    app_task_get_msg(msg, ARRAY_SIZE(msg), 0);
    switch (msg[0]) {
    case APP_MSG_SYS_EVENT:
        event = (struct sys_event *)(&msg[1]);
        switch (event->type) {
        case SYS_DEVICE_EVENT:
            switch ((u32)event->arg) {
            case DRIVER_EVENT_FROM_SD0:
            case DRIVER_EVENT_FROM_SD1:
            case DRIVER_EVENT_FROM_SD2:
                evt_logo = (char *)event->u.dev.value;
            case DEVICE_EVENT_FROM_OTG:
                if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) {
                    evt_logo = (char *)"udisk0";
                }
                ///设备上下线底层推出的设备逻辑盘符是跟跟音乐设备一致的（音乐/录音设备, 详细看接口注释）
                logo = dev_manager_get_phy_logo(__this->dev);
                ///响应设备插拔打断
                if (event->u.dev.event == DEVICE_EVENT_OUT) {
                    log_i("__func__ = %s logo=%s evt_logo=%s \n", __FUNCTION__, logo, evt_logo);
                    if (logo && evt_logo && (0 == strcmp(logo, evt_logo))) {
                        ///相同的设备才响应
                        __this->scandisk_break = 1;
                    }
                } else {
                    ///响应新设备上线
                    __this->scandisk_break = 1;
                }
                if (__this->scandisk_break == 0) {
                    log_i("__func__ = %s DEVICE_EVENT_OUT TODO\n", __FUNCTION__);
                    dev_status_event_filter(event);
                    log_i("__func__ = %s DEVICE_EVENT_OUT OK\n", __FUNCTION__);
                }
                break;
            }
            break;
        case SYS_BT_EVENT:
            if (bt_background_event_handler_filter(event)) {
                __this->scandisk_break = 1;
            }
            break;
        case SYS_KEY_EVENT:
            switch (event->u.key.event) {
            case KEY_CHANGE_MODE:
                ///响应切换模式事件
                __this->scandisk_break = 1;
                break;
            }
            if (__this->scandisk_break) {
                app_task_put_key_msg(event->u.key.event, (int)event->u.key.value);
                return -1;
            }
            break;
        }
        break;
    }
    if (__this->scandisk_break) {
        ///查询到需要打断的事件， 返回1， 并且重新推送一次该事件,跑主循环处理流程
        file_del_printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__);
        sys_event_notify(event);
        file_del_printf("scandisk_break!!!!!!\n");
        return 1;
    } else {
        return 0;
    }
}

static void scan_enter(struct __dev *dev)
{
    __this->busy = 1;
    clock_add_set(SCAN_DISK_CLK);
}

static void scan_exit(struct __dev *dev)
{
    clock_remove_set(SCAN_DISK_CLK);
    __this->busy = 0;
}

static const struct __scan_callback scan_cb = {
    .enter = scan_enter,
    .exit = scan_exit,
    .scan_break = file_delete_scandisk_break,
};


//*----------------------------------------------------------------------------*/
/**@brief    文件删除超时处理
   @param
   @return
   @note	 这里是等待手机删除命令超时(即没有等到删除命令)
*/
/*----------------------------------------------------------------------------*/
static void file_delete_timeout(void *p)
{
    //批量删除超时， 退出删除流程
    if (__this && __this->timerout) {
        file_del_printf("file_delete_timeout !!\n");
        file_delete_end();
    }
}

//*----------------------------------------------------------------------------*/
/**@brief    文件删除结束处理
   @param
   @return
   @note	 释放资源
*/
/*----------------------------------------------------------------------------*/
void file_delete_end(void)
{
    if (__this) {
        dev_manager_scan_disk_release(__this->fsn);
        if (__this->timerout) {
            sys_timeout_del(__this->timerout);
            __this->timerout = 0;
        }
        if (__this->end_callback) {
            __this->end_callback();
        }
        free(__this);
        __this = NULL;
        file_del_printf("file_delete_end\n");
    }
}

//*----------------------------------------------------------------------------*/
/**@brief    文件删除开始处理
   @param	 OpCode_SN:命名包的sn码， 命名回复时用到
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
extern int smartbox_file_transfer_watch_opt(u8 flag, char *root_path);
static void file_transfer_watch_opt(u32 dev_handle, u8 flag)
{
    if (BS_FLASH == dev_handle) { // 外挂flash存放非表盘文件，则和存放sd卡操作一致
        char *root_path = NULL;
        if (__this->dev) {
            root_path = dev_manager_get_root_path(__this->dev);
        }
        smartbox_file_transfer_watch_opt(flag, root_path);
    }
}

static int file_delete_func(FILE *file)
{
    int err = 0;
    if (NULL == file) {
        err = -1;
        goto __file_delete_func_end;
    }
    int cur_file = music_player_get_file_cur();
    char *cur_dev = music_player_get_dev_cur();
    int music_state = music_player_get_play_status();
    if (FILE_DEC_STATUS_PLAY == music_state) {
        app_task_put_key_msg(KEY_MUSIC_PP, 0);
    }
    err = fdelete(file);
    if (err) {
        printf("[%s, %d] fail!!, replay cur file\n", __FUNCTION__, __LINE__);
        err = -1;
        goto __file_delete_func_end;
    } else {
        printf("[%s, %d] ok, play next file\n", __FUNCTION__, __LINE__);
        if (FILE_DEC_STATUS_PLAY == music_state) {
            err = app_task_put_key_msg(KEY_MUSIC_PP, 0);
        }
    }

__file_delete_func_end:
    return err;
}

void file_delete_start(u8 OpCode_SN, u8 *data, u16 len)
{
    FILE *file = NULL;
    u8 reason = 0;
    u8 last = data[0];
    u32 dev_handle = READ_BIG_U32(data + 1);
    u8  type = data[5];
    u32 sclust = READ_BIG_U32(data + 6);
    file_del_printf("last = %d,dev_handle = %d,sclust = %d,type = %d,\n", last, dev_handle, sclust, type);

    char *logo = smartbox_browser_dev_remap(dev_handle);
    if (logo == NULL) {
        goto __err;
    }

    if (__this == NULL) {
        __this = zalloc(sizeof(struct __file_del));
        if (__this == NULL) {
            goto __err;
        }
    }

    if (__this->timerout) {
        sys_timeout_del(__this->timerout);
        __this->timerout = 0;
    }

    if (__this->fsn == NULL) {
        __this->dev = dev_manager_find_spec(logo, 0);

        if (!__this->dev) {
            free(__this);
            __this = NULL;
            goto __err;
        }

        if (__this->dev) {
            __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, 0, (struct __scan_callback *)&scan_cb);
            if (__this->fsn == NULL) {
                free(__this);
                __this = NULL;
                goto __err;
            }
            file_del_printf("%s, fscan ok\n", __FUNCTION__);
        }


    } else {
        file_del_printf("%s, fscan aready\n", __FUNCTION__);
        if (__this->busy) {
            //正在执行删除， 回复APP繁忙
            printf("file delete busy\n");
            JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_BUSY, OpCode_SN, NULL, 0);
            return ;
        }
    }

    file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, sclust, (struct __scan_callback *)&scan_cb);//根据文件簇号查找断点文件
    if (file) {
        file_delete_func(file);
        /* fdelete(file); */
        file_del_printf("delete file ok!!\n");
        JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0);
        if (last == 0) {
            if (__this->timerout == 0) {
                __this->timerout = sys_timeout_add(NULL, file_delete_timeout, FILE_DELELET_TIMEOUT);
            } else {
                sys_timer_modify(__this->timerout, FILE_DELELET_TIMEOUT);
            }
            //批量删除， 还没有删除完毕， 等待继续删除
            file_del_printf("wait delete file more\n");
            return;
        }

        file_transfer_watch_opt(dev_handle, 4);
    } else {
        file_del_printf("file delete, no this file\n");
        JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_PARAM_ERR, OpCode_SN, NULL, 0);
    }
    file_delete_end();
    return ;

__err:
    JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0);
    file_delete_end();
}


//*----------------------------------------------------------------------------*/
/**@brief    文件删除初始化
   @param	 end_callback:文件删除结束回调处理
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
void file_delete_init(void (*end_callback)(void))
{
    if (__this) {
        printf("file_delete_init aready err!!\n");
        return ;
    }
    __this = zalloc(sizeof(struct __file_del));
    if (__this == NULL) {
        printf("file_delete_init fail\n");
        if (end_callback) {
            end_callback();
        }
        return ;
    }
    __this->end_callback = end_callback;
    //启动定时器， 防止APP后续没有发执行删除的命令过来， 可以超时退出
    __this->timerout = sys_timeout_add(NULL, file_delete_timeout, 2000);
}
#else
void file_delete_init(void (*end_callback)(void))
{
}
void file_delete_start(u8 OpCode_SN, u8 *data, u16 len)
{
}
void file_delete_end(void)
{
}
#endif


