//user control
struct user add_user(struct user db);
struct user edit_user(struct user db,int index);
struct user delete_user(struct user db,int index);
void * showUser(void * ddb,int index);
struct Map* SortUser(void * ddb,int choice);
void print_user(void * ddb, int cur, int end,struct Map* map);
void user_control(){
    struct user db = read_db_user();
    int choice = 0;
    while(choice != 3){
        Cls();
        char buf[1024];
        welcome_message(buf);
        sprintf(buf+strlen(buf),"User control\n");
        choice = choices_selecter((char*[]){
            "Add user",
            "List user",
        },2,buf);
        switch(choice){
            case 1:
                db = add_user(db);
                break;
            case 2:;
                char * SortItems[] = {
                    "Name",
                    "ID",
                    "Role",
                };
                lister(&db,NULL,db.db.row_count,"User",SortItems,3,print_user,SortUser,showUser);
                db = read_db_user();
                break;
            case 3:
                break;
            default:
                printf("Invalid choice\n");
                printf("press any key to continue\n");
                fflush_stdin();
                getchar();
                break;
        }
    }
}

void * showUser(void * ddb,int index){
    struct user db = *((struct user*)ddb);
    int choice = -1;
    do{
        Cls();
        char buff[1024];
        welcome_message(buff);
        sprintf(buff+strlen(buff),"User detail\n");
        sprintf(buff+strlen(buff),"%-20s%-10s%-10s\n","Username","ID","Role");
        sprintf(buff+strlen(buff),"%-20s%-10ld%-10s\n",db.row[index].name,db.row[index].id,db.row[index].role);
        choice = choices_selecter((char*[]){
            "Edit user",
            "Delete user",
        },2,buff);
        switch (choice){
            case 1:
                db = edit_user(db,index);
                break;
            case 2:
                db = delete_user(db,index);
                break;
            default:
                printf("Invalid choice\n");
                printf("press any key to continue\n");
                fflush_stdin();
                getchar();
                break;
        }
    }while(choice!=3);
    void * re = malloc(sizeof(db));
    memcpy(re,&db,sizeof(db));
    return re;
}


struct user add_user(struct user db){
    char* temp;
    int index = db.db.row_count;
    struct user_row *temprow = realloc(db.row, sizeof(struct user_row));
    if (
        !item_inputer("name",STRING,&temprow->name,false) ||
        !item_inputer("id",LONG,&temprow->id,false) ||
        !item_inputer("role",STRING,&temprow->role,false)
    ){
        free(temprow);
        return db;
    }
    
    if(unlikely(!append_user(temprow))){
        printf("Failed to add user\n");
        exit(1);//exit program to prevent errors
    }else{
        printf("User added\n");
    }
    printf("press any key to continue\n");
    fflush_stdin();
    getchar();

    return read_db_user();
}
struct user edit_user(struct user db,int index){
    char temp[100];
    printf("Update transaction(empty value to not change the value)\n");
    printf("%-20s%-10s%-10s\n","Username","ID","Role");
    printf("%-20s%-10ld%-10s\n",db.row[index].name,db.row[index].id,db.row[index].role);
    item_inputer("username",STRING,&db.row[index].name,true);
    item_inputer("id",LONG,&db.row[index].id,true);
    item_inputer("role",STRING,&db.row[index].role,true);

    if(unlikely(!update_db_user(db))){
        printf("Failed to update user\n");
        exit(1);//exit program to prevent errors
    }else{
        printf("User updated\n");
    }
    printf("press any key to continue\n");
    fflush_stdin();
    getchar();

    return db;
}
struct user delete_user(struct user db,int index){
    db.row[index].isdeleted = true;
    if(unlikely(!update_db_user(db))){
        printf("Failed to delete user\n");
        exit(1);//exit program to prevent errors
    }else{
        printf("User deleted\n");
    }
    printf("press any key to continue\n");
    fflush_stdin();
    getchar();

    return read_db_user();
}
struct Map* sortUser(struct user db,int choice);

void print_user(void * ddb, int cur, int end,struct Map* map){
    struct user db = *((struct user*)ddb);
    printf("%-5s%-20s%-10s%-10s%-10s\n","No.","Username","ID","Role","IsAdmin");
    for(int i = cur; i < end; i++){
        if(map == NULL){
            bool isadmin = is_admin(db.row[i].role);
            // printf("isadmin%s\n",db.row[i].id);
            printf("%-5d%-20s%-10ld%-10s%-10c\n",i+7,StringCompression(db.row[i].name,18),db.row[i].id,StringCompression(db.row[i].role,8),isadmin?'Y':'N');
        }else{
            int index = map[i].key;
            bool isadmin = is_admin(db.row[index].role);
            printf("%-5d%-20s%-10ld%-10s%-10c\n",i+7,StringCompression(db.row[index].name,18),db.row[index].id,StringCompression(db.row[index].role,8),isadmin?'Y':'N');
        }
    }
}

struct Map* sortUser(struct user db,int choice){
    struct Map *map = malloc(sizeof(struct Map) * db.db.row_count);
    for (int i = 0; i < db.db.row_count; i++){
        map[i].key = i;
        switch(choice){
            case 1:
            case 2:;
                char* temp = malloc(sizeof(char) * 100);
                strcpy(temp,db.row[i].name);
                map[i].value = (void*)temp;
                break;

            case 3:
            case 4:;
                char* temp2 = malloc(sizeof(char) * 100);
                strcpy(temp2,db.row[i].role);
                map[i].value = (void*)temp2;
                break;
            case 5:
            case 6:;
                long* tempstar3 = malloc(sizeof(long));
                *tempstar3 = db.row[i].id;
                map[i].value = (void*)tempstar3;
                break;
    
        }
    }
    switch (choice){
        case 1:
        case 3:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_decending_str);
            break;
        case 2:
        case 4:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_ascending_str);
            break;
        case 5:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_decending);
            break;
        case 6:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_ascending);
            break;

    }
    return map;
}

struct Map* SortUser(void * ddb,int choice){
    struct user db = *((struct user*)ddb);
    struct Map *map = malloc(sizeof(struct Map) * db.db.row_count);
    for (int i = 0; i < db.db.row_count; i++){
        map[i].key = i;
        switch(choice){
            case 1:
            case 2:;
                char* temp = malloc(sizeof(char) * 100);
                strcpy(temp,db.row[i].name);
                map[i].value = (void*)temp;
                break;

            case 3:
            case 4:;
                char* temp2 = malloc(sizeof(char) * 100);
                strcpy(temp2,db.row[i].role);
                map[i].value = (void*)temp2;
                break;
            case 5:
            case 6:;
                long* tempstar3 = malloc(sizeof(long));
                *tempstar3 = db.row[i].id;
                map[i].value = (void*)tempstar3;
                break;
    
        }
    }
    switch (choice){
        case 1:
        case 3:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_decending_str);
            break;
        case 2:
        case 4:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_ascending_str);
            break;
        case 5:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_decending);
            break;
        case 6:
            qsort(map, db.db.row_count, sizeof(struct Map), compare_ascending);
            break;

    }
    return map;
}


