//gcc -o aoi aoi.c utils.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include "utils.h"
#include "aoi.h"

static int NEARBY_CEIL_OFFSETS[9][2] = {
    {0, 0},  // center
    {-1, 1}, // TL
    {0, 1},  // T
    {1, 1},  // TR

    {-1, 0}, // L
    {1, 0},  // R

    {-1, -1}, // BL
    {0, -1},  // B
    {1, -1},  // BR
};

static double cost_time_in_lua = 0.0;
static double cost_time_in_cal = 0.0;
static double cost_time_in_get_event = 0.0;

static int get_grid_idx(World *w, int x, int y)
{
    return (x - 1) * (w->col) + y - 1;
};

static void get_xy_by_grididx(World *w, int grid_idx, int *x, int *y)
{
    *x = (grid_idx / w->col) + 1;
    *y = grid_idx - ((*x) - 1) * w->col + 1;
    return;
}

static int out_of_range(World *w, int grid_idx, int idx)
{
    int x1, y1;
    get_xy_by_grididx(w, grid_idx, &x1, &y1);
    int x2, y2;
    get_xy_by_grididx(w, idx, &x2, &y2);
    if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > 2)
    {
        return 1;
    }
    return 0;
}

static HashTable *get_nearby_grids(World *w, Grid *grid)
{
    int grid_num = w->row * w->col;
    HashTable *ret = hashtbl_create();

    int x, y;
    get_xy_by_grididx(w, grid->idx, &x, &y);
    int i, _x, _y;
    for (i = 0; i < 9; i++)
    {
        _x = x + NEARBY_CEIL_OFFSETS[i][0];
        _y = y + NEARBY_CEIL_OFFSETS[i][1];
        if (_x >= 1 && _x <= w->row && _y >= 1 && _y <= w->col)
        {
            int tmp_idx = get_grid_idx(w, _x, _y);
            Grid *grid = w->grids[tmp_idx];
            hashtbl_upsert(ret, tmp_idx, grid);
            //printf("get_nearby_grids %d %d\n",grid->idx,tmp_idx);
        }
    }

    // for (int i = -1; i<=1; i++){
    //     for (int j= -1; j<=1; j++){
    //         int index = i*w->col + grid->idx + j;
    //         if(index >= 0 && index < grid_num){
    //             Grid* grid = w->grids[index];
    //             hashtbl_upsert(ret, index, grid);
    //         }
    //     }
    // }
    //         local k = i*col + cur_grididx + j
    //         local grid = grids[k]
    //         if grid and not ret[k] then
    //             ret[k] = grid
    //         end
    //     end
    // end
    // return ret

    return ret;
}

static void print_event(int grid_idx, char flag, HashTable *events)
{
    HashTableIter iter;
    hashtbl_iter_reset(&iter);
    while (hashtbl_iter(events, &iter))
    {
        Event *e = (Event *)(iter.node->value);
        printf("flag:%c grid_idx:%d event:%c,id:%d,x:%d,y:%d\n", flag, grid_idx, e->e, e->id, e->x, e->y);
    }
}

static void get_grid_add_event(Grid *grid, lua_State *L)
{                                      //你进入某个格子，要知道该格子的事情
    int idx_grid_info = lua_gettop(L); //2
    lua_rawgeti(L, idx_grid_info, grid->idx);
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_grid_info, grid->idx);
    }
    int idx_grid_detail = lua_gettop(L); //3
    lua_rawgeti(L, idx_grid_detail, 1);  //key_idx==1
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_grid_detail, 1);
    }
    int idx_grid_add_del_update = lua_gettop(L); //4
    size_t tbl_len = lua_rawlen(L, idx_grid_add_del_update);
    if (tbl_len == 0)
    {
        int len = 1;

        HashTableIter iter;
        hashtbl_iter_reset(&iter);
        while (hashtbl_iter(grid->caches, &iter))
        {
            Cache *cache = (Cache *)(iter.node->value);
            if (cache->e == 'A' || cache->e == 'U')
            {
                lua_newtable(L);
                lua_pushinteger(L, 1); //'A'
                lua_rawseti(L, -2, 1);
                lua_pushinteger(L, cache->id);
                lua_rawseti(L, -2, 2);
                lua_pushinteger(L, cache->x);
                lua_rawseti(L, -2, 3);
                lua_pushinteger(L, cache->y);
                lua_rawseti(L, -2, 4);

                lua_rawseti(L, idx_grid_add_del_update, len);
                len = len + 1;
            }
        }

        hashtbl_iter_reset(&iter);
        while (hashtbl_iter(grid->makers, &iter))
        {
            Obj *obj = (Obj *)(iter.node->value);
            if (!hashtbl_get(grid->caches, obj->id))
            { //如果在cache中且没进入event_adds，说明e是D
                lua_newtable(L);
                lua_pushinteger(L, 1); //'A'
                lua_rawseti(L, -2, 1);
                lua_pushinteger(L, obj->id);
                lua_rawseti(L, -2, 2);
                lua_pushinteger(L, obj->x);
                lua_rawseti(L, -2, 3);
                lua_pushinteger(L, obj->y);
                lua_rawseti(L, -2, 4);

                lua_rawseti(L, idx_grid_add_del_update, len);
                len = len + 1;
            }
        }
    }
}

static void get_grid_del_event(Grid *grid, lua_State *L)
{                                      //你离开某个格子，要知道该格子的事情
    int idx_grid_info = lua_gettop(L); //2
    lua_rawgeti(L, idx_grid_info, grid->idx);
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_grid_info, grid->idx);
    }
    int idx_grid_detail = lua_gettop(L); //3
    lua_rawgeti(L, idx_grid_detail, 2);  //key_idx==2
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_grid_detail, 2);
    }
    int idx_grid_add_del_update = lua_gettop(L); //4
    size_t tbl_len = lua_rawlen(L, idx_grid_add_del_update);
    if (tbl_len == 0)
    {
        int len = 1;

        HashTableIter iter;
        hashtbl_iter_reset(&iter);
        //cache中还没加进makers的就不管了
        while (hashtbl_iter(grid->makers, &iter))
        {
            Obj *obj = (Obj *)(iter.node->value);
            lua_newtable(L);

            lua_pushinteger(L, 2); //'D'
            lua_rawseti(L, -2, 1);
            lua_pushinteger(L, obj->id);
            lua_rawseti(L, -2, 2);
            lua_pushinteger(L, obj->x);
            lua_rawseti(L, -2, 3);
            lua_pushinteger(L, obj->y);
            lua_rawseti(L, -2, 4);

            lua_rawseti(L, idx_grid_add_del_update, len);
            len = len + 1;
        }
    }
}

static void get_grid_update_event(Grid *grid, lua_State *L)
{                                      //你在某个格子附近晃，要知道该格子的事情
    int idx_grid_info = lua_gettop(L); //2
    lua_rawgeti(L, idx_grid_info, grid->idx);
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_grid_info, grid->idx);
    }
    int idx_grid_detail = lua_gettop(L); //3
    lua_rawgeti(L, idx_grid_detail, 3);  //key_idx==3
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_grid_detail, 3);
    }
    int idx_grid_add_del_update = lua_gettop(L); //4
    size_t tbl_len = lua_rawlen(L, idx_grid_add_del_update);
    if (tbl_len == 0)
    {
        int len = 1;

        HashTableIter iter;
        hashtbl_iter_reset(&iter);
        while (hashtbl_iter(grid->caches, &iter))
        {
            Cache *cache = (Cache *)(iter.node->value);
            lua_newtable(L);
            if (cache->e == 'A')
            {
                lua_pushinteger(L, 1); //'A'
            }
            else if (cache->e == 'D')
            {
                lua_pushinteger(L, 2);
            }
            else
            {
                lua_pushinteger(L, 3);
            }
            lua_rawseti(L, -2, 1);
            lua_pushinteger(L, cache->id);
            lua_rawseti(L, -2, 2);
            lua_pushinteger(L, cache->x);
            lua_rawseti(L, -2, 3);
            lua_pushinteger(L, cache->y);
            lua_rawseti(L, -2, 4);

            lua_rawseti(L, idx_grid_add_del_update, len);
            len = len + 1;
        }
    }
}

//结果处理
static void add_grid_events_to_watchers(Grid *grid, char e, int id, lua_State *L)
{
    //printf("add_grid_events_to_watchers %d %c %d\n", grid->idx, e, id);
    //clock_t t1 = clock();
    //HashTable* events;
    int key_idx;
    if (e == 'U')
    { //3
        get_grid_update_event(grid, L);
        key_idx = 3;
    }
    else if (e == 'A')
    { //1
        get_grid_add_event(grid, L);
        key_idx = 1;
    }
    else if (e == 'D')
    { //2
        get_grid_del_event(grid, L);
        key_idx = 2;
    }
    //clock_t t2 = clock();
    //double t3 = (double)(t2-t1)/CLOCKS_PER_SEC;
    //cost_time_in_get_event += t3;

    //clock_t time_begin = clock();
    //不copy，直接用引用
    int idx_ret = 1;
    //将events upsert进L
    //printf("upsert events succ %d\n",idx_grid_add_del_update);

    lua_rawgeti(L, idx_ret, id);
    if (lua_isnil(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushvalue(L, -1);
        lua_rawseti(L, idx_ret, id);
    }
    int idx_watcher_ret = lua_gettop(L); //5
    size_t tbl_len = lua_rawlen(L, idx_watcher_ret);
    lua_pushvalue(L, 4);
    lua_rawseti(L, idx_watcher_ret, tbl_len + 1);
    lua_pop(L, 3);

    // lua_rawgeti(L, idx_watcher_ret, grid->idx);
    // if(lua_isnil(L,-1)){
    //     lua_pop(L,1);
    //     lua_newtable(L);
    //     lua_pushvalue(L,-1);
    //     lua_rawseti(L, idx_watcher_ret, grid->idx);
    // }
    // int idx_watcher_grid_ret = lua_gettop(L);//6
    // lua_pushvalue(L, 4);//引用,idx_grid_add_del_update==4
    // lua_rawseti(L, idx_watcher_grid_ret, key_idx);
    // lua_pop(L,4);
    //clock_t time_end = clock();
    //double time_cost = (double)(time_end-time_begin)/CLOCKS_PER_SEC;
    //cost_time_in_lua += time_cost;
    //printf("===cost_time_in_lua:%f====\n", cost_time_in_lua);
}

//watcher到了grid
static void resolve_change_watcher(World *w, Grid *grid, HashTable *right_grid_map, int pre_idx, int id, lua_State *L)
{
    //printf("resolve_change_watcher id:%d grid_idx:%d pre_idx:%d\n",id, grid->idx, pre_idx);
    HashTableIter iter;
    HashTable *left_grid_map;
    if (pre_idx != -1)
    {
        // int x,y;
        // get_xy_by_grididx(w,pre_idx,&x,&y);
        // int i, _x, _y;
        // for(i=0; i<9; i++) {
        //     _x = x + NEARBY_CEIL_OFFSETS[i][0];
        //     _y = y + NEARBY_CEIL_OFFSETS[i][1];
        //     if (!(_x>=1&&_x<=w->row&&_y>=1&&_y<=w->col)){
        //         continue;
        //     }
        //     int tmp_idx = get_grid_idx(w, _x, _y);
        //     Grid* tmp_grid = w->grids[tmp_idx];

        //     if(out_of_range(w, grid->idx, tmp_idx)){
        //         add_grid_events_to_watchers(tmp_grid, 'D', id, L);
        //     }
        //     else{
        //         add_grid_events_to_watchers(tmp_grid, 'U', id, L);
        //     }
        // }
        Grid *old_grid = w->grids[pre_idx];
        left_grid_map = get_nearby_grids(w, old_grid);

        hashtbl_iter_reset(&iter);
        while (hashtbl_iter(left_grid_map, &iter))
        {
            Grid *tmp_grid = (Grid *)(iter.node->value);
            if (hashtbl_get(right_grid_map, tmp_grid->idx))
            {
                add_grid_events_to_watchers(tmp_grid, 'U', id, L);
            }
            else
            {
                add_grid_events_to_watchers(tmp_grid, 'D', id, L);
            }
        }
    }

    hashtbl_iter_reset(&iter);
    while (hashtbl_iter(right_grid_map, &iter))
    {
        Grid *tmp_grid = (Grid *)(iter.node->value);
        if (pre_idx == -1 || !hashtbl_get(left_grid_map, tmp_grid->idx))
        {
            add_grid_events_to_watchers(tmp_grid, 'A', id, L);
        }
    }
    if (pre_idx != -1)
    {
        hashtbl_destroy(left_grid_map);
    }
    // for (int i = 0; i<9;i++){
    //     Grid* tmp_grid = grid_list[i];
    //     if(!tmp_grid){
    //         continue;
    //     }
    //     if(pre_idx!=-1 && !out_of_range(w, pre_idx, tmp_grid->idx)){
    //         continue;//之前已经get 'U'过了
    //     }
    //     add_grid_events_to_watchers(tmp_grid, 'A', id, L);
    // }
}
static int grid_add_obj(World *w, Grid *grid, int id, int x, int y, int is_maker, int is_watcher)
{
    if (is_maker)
    {
        if (hashtbl_get(grid->caches, id))
        {
            //之前可能有D 在里面
            Cache *old_cache = (Cache *)hashtbl_get(grid->caches, id);
            skynet_free(old_cache);
            hashtbl_remove(grid->caches, id);
            old_cache = NULL;
            //printf("old cache id:%d e:%c x:%d y:%d \n", old_cache->id, old_cache->e, old_cache->x, old_cache->y);
        }
        Cache *cache = (Cache *)skynet_malloc(sizeof(Cache));
        cache->id = id;
        cache->x = x;
        cache->y = y;
        cache->e = 'A';
        hashtbl_insert(grid->caches, id, cache);
    }
    if (is_watcher)
    {
        Obj *obj = (Obj *)skynet_malloc(sizeof(Obj));
        obj->id = id;
        obj->x = x;
        obj->y = y;
        obj->is_maker = is_maker;
        obj->is_watcher = is_watcher;
        hashtbl_insert(grid->watchers, obj->id, obj);
        hashtbl_upsert(w->watcher_grids, grid->idx, NULL);
    }
    return 0;
}

static int grid_del_obj(World *w, Grid *grid, int id)
{
    if (hashtbl_get(grid->makers, id))
    { //已经落地了
        //旧的cache清除
        if (hashtbl_get(grid->caches, id))
        {
            Cache *old_cache = (Cache *)hashtbl_get(grid->caches, id);
            skynet_free(old_cache);
            hashtbl_remove(grid->caches, id);
            old_cache = NULL;
        }
        //添加新的
        Obj *obj = (Obj *)hashtbl_get(grid->makers, id);
        Cache *cache = (Cache *)skynet_malloc(sizeof(Cache));
        cache->id = obj->id;
        cache->x = obj->x;
        cache->y = obj->y;
        cache->e = 'D';
        hashtbl_insert(grid->caches, obj->id, cache);
    }
    else if (hashtbl_get(grid->caches, id))
    { //只是存在cache中
        //当你从来没有出现过
        //printf("grid_del_obj remove_caches %d\n", id);
        Cache *cache = (Cache *)hashtbl_get(grid->caches, id);
        skynet_free(cache);
        hashtbl_remove(grid->caches, id);
        cache = NULL;
    }

    if (hashtbl_get(grid->watchers, id))
    {
        //printf("grid_del_obj remove_watchers %d\n", id);
        Obj *obj = (Obj *)hashtbl_get(grid->watchers, id);
        hashtbl_remove(grid->watchers, id);
        if (!obj->is_maker)
        {
            //如果只是watcher的话，释放对象
            skynet_free(obj);
            obj = NULL;
        }
        if (grid->watchers->count == 0)
        {
            hashtbl_remove(w->watcher_grids, grid->idx);
        }
    }
    return 0;
}

static void grid_update_obj(Grid *grid, int id)
{
    //watcher不需要update
    if (hashtbl_get(grid->makers, id) && !hashtbl_get(grid->caches, id))
    {
        //之前已经在的且没有caches的才需要添加cache
        Obj *obj = (Obj *)hashtbl_get(grid->makers, id);
        Cache *cache = (Cache *)skynet_malloc(sizeof(Cache));
        cache->id = obj->id;
        cache->x = obj->x;
        cache->y = obj->y;
        cache->e = 'U';
        hashtbl_insert(grid->caches, obj->id, cache);
    }
}

static void handle_cache(Grid *grid)
{
    HashTableIter iter;
    hashtbl_iter_reset(&iter);
    while (hashtbl_iter(grid->caches, &iter))
    {
        Cache *cache = (Cache *)(iter.node->value);
        iter.node->value = NULL;
        if (cache->e == 'A' && !hashtbl_get(grid->makers, cache->id))
        { //之前在makers，D了再A，就会重复，无须处理
            //先D了去了其他格子，再回来，就不需要add_makers了
            Obj *obj;
            if (hashtbl_get(grid->watchers, cache->id))
            {
                obj = (Obj *)hashtbl_get(grid->watchers, cache->id);
            }
            else
            {
                obj = (Obj *)skynet_malloc(sizeof(Obj));
                obj->id = cache->id;
                obj->x = cache->x;
                obj->y = cache->y;
                obj->is_maker = 1;
                obj->is_watcher = 0;
            }
            hashtbl_insert(grid->makers, obj->id, obj);
        }
        else if (cache->e == 'D')
        {
            Obj *obj = (Obj *)hashtbl_get(grid->makers, cache->id);
            hashtbl_remove(grid->makers, cache->id);
            skynet_free(obj);
            obj = NULL;
        }
        skynet_free(cache);
        cache = NULL;
    }
    hashtbl_destroy(grid->caches);
    grid->caches = hashtbl_create();
}

static void handle_aoi(World *w, Grid *grid, lua_State *L)
{

    HashTable *grid_map = get_nearby_grids(w, grid);
    HashTableIter iter2;

    HashTableIter iter;
    hashtbl_iter_reset(&iter);
    //Grid** grid_list = get_nearby_grids(w, grid);
    while (hashtbl_iter(grid->watchers, &iter))
    {
        Obj *watcher = (Obj *)(iter.node->value);
        int pre_idx = -1;
        int id = watcher->id;
        //printf("handle_aoi %d %d\n",grid->idx, id);
        if (hashtbl_get(w->pre_where_is, id))
        {
            int *p_idx = (int *)hashtbl_get(w->pre_where_is, id);
            pre_idx = *p_idx;
        }
        if (pre_idx == grid->idx)
        {

            hashtbl_iter_reset(&iter2);
            while (hashtbl_iter(grid_map, &iter2))
            {
                Grid *tmp_grid = (Grid *)(iter2.node->value);
                // if(id==6) {
                //     printf("tmp_grid %d\n",tmp_grid->idx);
                // }
                add_grid_events_to_watchers(tmp_grid, 'U', id, L);
            }
            // for (int i = 0; i<9;i++){
            //     Grid* tmp_grid = grid_list[i];
            //     if(!tmp_grid){
            //         continue;
            //     }
            //     add_grid_events_to_watchers(tmp_grid, 'U', id, L);
            // }
        }
        else
        {
            resolve_change_watcher(w, grid, grid_map, pre_idx, id, L);
            if (hashtbl_get(w->pre_where_is, id))
            {
                int *p_idx = (int *)hashtbl_get(w->pre_where_is, id);
                *p_idx = grid->idx;
            }
            else
            {
                int *p_idx = (int *)skynet_malloc(sizeof(int));
                *p_idx = grid->idx;
                hashtbl_insert(w->pre_where_is, id, p_idx);
            }
        }
    }
    hashtbl_destroy(grid_map);
}

World *aoi_create_world(int row, int col)
{
    //printf("aoi_create_world %d %d\n",row, col);
    World *w = (World *)skynet_malloc(sizeof(World));
    w->row = row;
    w->col = col;

    int grid_num = w->row * w->col;
    w->grids = (Grid **)skynet_malloc(grid_num * sizeof(Grid *));
    for (int i = 0; i < grid_num; i++)
    {
        Grid *grid = (Grid *)skynet_malloc(sizeof(Grid));
        grid->idx = i;
        grid->watchers = hashtbl_create();
        grid->makers = hashtbl_create();
        grid->caches = hashtbl_create();

        w->grids[i] = grid;
    }
    w->where_is = hashtbl_create();
    w->pre_where_is = hashtbl_create();
    w->watcher_grids = hashtbl_create();
    return w;
}

void aoi_get_cost_time(void *l)
{
    lua_State *L = (lua_State *)l;
    lua_pushnumber(L, cost_time_in_get_event);
    lua_pushnumber(L, cost_time_in_lua);
    lua_pushnumber(L, cost_time_in_cal);
    cost_time_in_get_event = 0.0;
    cost_time_in_lua = 0.0;
    cost_time_in_cal = 0.0;
    return;
}

void aoi_update_aoi(World *w, void *l)
{
    //clock_t time_begin = clock();
    lua_State *L = (lua_State *)l;
    //printf("=========start update_aoi=========\n");
    int grid_num = w->row * w->col;
    //抛出事件

    //for(int i=0;i<grid_num;i++){
    //    Grid* grid = w->grids[i];
    //    handle_aoi(w, grid, L);
    //}
    HashTableIter iter;
    hashtbl_iter_reset(&iter);
    while (hashtbl_iter(w->watcher_grids, &iter))
    {
        int grid_idx = (iter.node->key);
        //printf("handle_aoi grid_idx %d\n", grid_idx);
        Grid *grid = w->grids[grid_idx];
        handle_aoi(w, grid, L);
    }
    //clock_t time_end = clock();
    //处理cache
    //printf("handle_cache\n");
    for (int i = 0; i < grid_num; i++)
    {
        Grid *grid = w->grids[i];
        handle_cache(grid);
    }

    //清空每个格子的events 通过lua_state自己清
    //printf("clean all grids events\n");

    //printf("=========end update_aoi=========\n");
    //clock_t time_end = clock();
    //double time_cost = (double)(time_end-time_begin)/CLOCKS_PER_SEC;
    //cost_time_in_cal += time_cost;
    //printf("===time_cost:%f====\n",cost_time_in_cal);
}

int aoi_add_obj(World *w, int id, int x, int y, int is_maker, int is_watcher)
{
    int idx = get_grid_idx(w, x, y); //函数结束会释放idx的，不能hashtbl_insert(&idx)
    Grid *grid = w->grids[idx];

    if (hashtbl_get(w->where_is, id) || hashtbl_get(grid->caches, id) || hashtbl_get(grid->watchers, id) || hashtbl_get(grid->makers, id))
    {
        printf("add_obj duplicated %d\n", id);
        return 1;
    }
    if (!is_maker && !is_watcher)
    {
        printf("add_obj no watcher_and_maker %d\n", id);
        return 2;
    }
    int *p_idx = (int *)skynet_malloc(sizeof(int));
    *p_idx = idx; //不同于p_idx=&idx
    hashtbl_insert(w->where_is, id, p_idx);
    grid_add_obj(w, grid, id, x, y, is_maker, is_watcher);
    return 0;
}

int aoi_del_obj(World *w, int id)
{
    int *p_idx = (int *)hashtbl_get(w->where_is, id);
    if (!p_idx)
    {
        printf("del_obj not_exist %d\n", id);
        return 1;
    }
    Grid *grid = w->grids[*p_idx];
    grid_del_obj(w, grid, id);

    hashtbl_remove(w->where_is, id);
    skynet_free(p_idx);
    return 0;
}

int aoi_set_obj(World *w, int id, int x, int y)
{
    int *p_idx = (int *)hashtbl_get(w->where_is, id);
    if (!p_idx)
    {
        printf("set_obj not_exist %d\n", id);
        return 1;
    }
    int idx = get_grid_idx(w, x, y);
    if (idx == *p_idx)
    {
        Grid *grid = w->grids[idx];
        grid_update_obj(grid, id);
    }
    else
    {
        Grid *old_grid = w->grids[*p_idx];
        Grid *new_grid = w->grids[idx];
        int is_maker = 0;
        int is_watcher = 0;
        if (hashtbl_get(old_grid->makers, id) || hashtbl_get(old_grid->caches, id))
        {
            is_maker = 1;
        }
        if (hashtbl_get(old_grid->watchers, id))
        {
            is_watcher = 1;
        }
        grid_del_obj(w, old_grid, id);
        grid_add_obj(w, new_grid, id, x, y, is_maker, is_watcher);

        *p_idx = idx;
    }
    return 0;
}

// int main() {
//     // World* w = aoi_create_world(3,3);
//     // aoi_add_obj(w,7,2,2,1,1);
//     // aoi_add_obj(w,1,2,2,1,1);
//     // aoi_add_obj(w,6,3,3,1,1);
//     // //aoi_update_aoi(w);
//     // //aoi_update_aoi(w);
//     // aoi_set_obj(w,7,2,3);
//     // //aoi_update_aoi(w);
//     // aoi_add_obj(w,2,1,1,1,1);
//     // aoi_set_obj(w,2,1,2);
//     // //aoi_update_aoi(w);
//     // //先加再删，等于从来没出现过
//     // aoi_add_obj(w,3,2,2,1,1);
//     // aoi_del_obj(w,3);
//     // //aoi_update_aoi(w);

//     // aoi_set_obj(w,2,3,3);
//     // aoi_set_obj(w,7,1,1);
//     //aoi_update_aoi(w);
//     // update_aoi(w);
//     // printf("======\n");
//     // del_obj(w,7);
//     // update_aoi(w);
//     // printf("=======\n");
//     // int grid_idx = get_grid_idx(w,1,2);
//     // int x,y;
//     // get_xy_by_grididx(w,grid_idx,&x,&y);
//     // printf("x:%d y:%d\n", x, y);
//     // add_obj(w,2,5,5,1,1);
//     // show_world(w);
//     // set_obj(w,1,6,6);
//     // show_world(w);
//     // del_obj(w,1);
//     // show_world(w);

//     // World* w = aoi_create_world(3,3);
//     // for(int i=1;i<=10000;i++)
//     // {
//     //     aoi_add_obj(w,i,1,1,1,1);
//     // }
//     // HashTable* aoi_results = hashtbl_create();
//     // aoi_update_aoi(w, aoi_results);
//     // //打印aoi_results
//     // HashTableIter iter;
//     // hashtbl_iter_reset(&iter);
//     // int i = 0;
//     // while(hashtbl_iter(aoi_results, &iter)){
//     //     Result* re=(Result*)(iter.node->value);

//     //     printf("watcher:%ld\n", iter.node->key);
//     //     int watcher_id = (int)iter.node->key;
//     //     HashTableIter tmp_iter;
//     //     hashtbl_iter_reset(&tmp_iter);
//     //     while(hashtbl_iter(re->add_results, &tmp_iter)){
//     //         Event* e=(Event*)(tmp_iter.node->value);
//     //         //printf("event:%c,id:%d,x:%d,y:%d\n",e->e,e->id,e->x,e->y);
//     //         i=i+1;
//     //         printf("i is %d\n",i);
//     //     }
//     //     // hashtbl_iter_reset(&tmp_iter);
//     //     // while(hashtbl_iter(re->del_results, &tmp_iter)){
//     //     //     Event* e=(Event*)(tmp_iter.node->value);
//     //     //     //printf("event:%c,id:%d,x:%d,y:%d\n",e->e,e->id,e->x,e->y);
//     //     // }
//     //     // hashtbl_iter_reset(&tmp_iter);
//     //     // while(hashtbl_iter(re->update_results, &tmp_iter)){
//     //     //     Event* e=(Event*)(tmp_iter.node->value);
//     //     //     //printf("event:%c,id:%d,x:%d,y:%d\n",e->e,e->id,e->x,e->y);
//     //     // }

//     //     hashtbl_destroy(re->add_results);
//     //     hashtbl_destroy(re->del_results);
//     //     hashtbl_destroy(re->update_results);
//     // }
//     // printf("clean aoi_results\n");
//     // //todo清空aoi_results
//     // hashtbl_destroy(aoi_results);
//     return 0;
// }
