// Constants
let MIN_DISTANCE = 12;
let MAX_PER_GROUP = 3;
let NB_USERS = 10;

// Utils
let rand = function(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
};

let compareDistances = function(distA, distB) {
    if (distA.distance < distB.distance) {
        return -1;
    }
    if (distA.distance > distB.distance) {
        return 1;
    }
    return 0;
};

let computeDistance = function (user1, user2) {
    return Math.sqrt(Math.pow(user2.X - user1.X, 2) + Math.pow(user2.Y - user1.Y, 2));
};

// Test Data
let users = [];
for(let i = 1; i <= NB_USERS; i++) {
    let user = {};
    user.id = rand(0,99999);
    user.X = rand(0, 40);
    user.Y = rand(0, 40);
    users.push(user);
}

// Compute distance between each user
let getDistanceOfEachUser = function(users) {
    let i = 0;
    let distances = [];

    users.forEach(function(user1, key1) {
        users.forEach(function(user2, key2) {
            if(key1 < key2) {
                let distanceObj = {};
                distanceObj.distance = computeDistance(user1, user2);
                distanceObj.first = user1;
                distanceObj.second = user2;

                distances[i] = distanceObj;
                i++;
            }
        });
    });

    return distances;
};

// Organise groups
let createGroups = function(distances) {
    let i = 0;
    let groups = [];
    let alreadyInAGroup = [];

    for(let j = 0; j < distances.length; j++) {
        let dist = distances[j];

        if(dist.distance <= MIN_DISTANCE) {
            if(typeof groups[i] === 'undefined') {
                groups[i] = [];
            }

            if(groups[i].indexOf(dist.first) === -1 && typeof alreadyInAGroup[dist.first.id] === 'undefined') {
                if(groups[i].length > 1) {
                    // if group is not empty we check current user can be added in the group according to its distance to the others already in it
                    for(let l = 0; l < groups[i].length; l++) {
                        let userTotest = groups[i][l];
                        if(computeDistance(dist.first, userTotest) <= MIN_DISTANCE) {
                            groups[i].push(dist.first);
                            alreadyInAGroup[dist.first.id] = true;
                            break;
                        }
                    }
                } else {
                    groups[i].push(dist.first);
                    alreadyInAGroup[dist.first.id] = true;
                }
            }

            if(groups[i].length === MAX_PER_GROUP) {
                i++; // on créé un nouveau groupe
                if(i > (NB_USERS / MAX_PER_GROUP)) {
                    console.log('There is no room left for user ID : ' + dist.second.id + ' !');
                    break;
                }
                continue;
            }

            if(groups[i].indexOf(dist.second) === -1 && typeof alreadyInAGroup[dist.second.id] === 'undefined') {
                if(groups[i].length > 1) {
                    // if group is not empty we check current user can be added in the group according to its distance to the others already in it
                    for(let l = 0; l < groups[i].length; l++) {
                        let userTotest = groups[i][l];
                        if(computeDistance(dist.second, userTotest) <= MIN_DISTANCE) {
                            groups[i].push(dist.second);
                            alreadyInAGroup[dist.second.id] = true;
                            break;
                        }
                    }
                } else {
                    groups[i].push(dist.second);
                    alreadyInAGroup[dist.second.id] = true;
                }
            }
        }
    }

    return groups;
};

let distances = getDistanceOfEachUser(users);

// ordonner par distance pour prioriser l'association en groupe des utilisateurs les plus proches
distances.sort(compareDistances);

let groups = createGroups(distances);

// Compute distance between each user of a already existing group
let checkGroupDistance = function(groups) {
    for(let i = 0; i < groups.length; i++) {
        let group = groups[i];
            group.forEach(function(user1, key1) {
                group.forEach(function(user2, key2) {
                    if(key1 < key2) {
                        let distance = computeDistance(user1, user2);
                        if(distance > MIN_DISTANCE) {
                            // TODO : message a user1 et user2
                        }
                    }
            });
        });
    }
};

console.log(users);
console.log(distances);
console.log(groups);