//
//  Created by Thijs Wenker on 3/31/2017
//  Copyright 2017 High Fidelity, Inc.
//
//  Distributed under the Apache License, Version 2.0.
//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//

(function() {
    var _this;
    var DO_NOT_SNAP_WHEN_FARTHER_THAN_THIS = 0.25;

    function SnapToGrid() {
        _this = this;
    }

    SnapToGrid.prototype = {
        preload: function(id) {
            _this.entityID = id;
            _this.getAnchorPoints();
        },
        startGrab: function() {
            var userData = _this.getCurrentUserData();
            if (userData.gameTable.hasOwnProperty('attachedTo') && userData.gameTable.attachedTo !== null) {
                Entities.editEntity(userData.gameTable.attachedTo, {
                    userData: 'available'
                });
            }
        },
        releaseGrab: function() {
            _this.attachToNearestAnchor();
        },
        getAnchorPoints: function() {
            var availableAnchors = [];
            var results = _this.getEntitiesFromGroup('gameTable', 'anchor');
            results.forEach(function(item) {
                var properties = Entities.getEntityProperties(item, ['position', 'userData']);
                if (properties.userData === 'occupied') {
                    // don't put it on the stack
                } else if (properties.userData === 'available') {
                    availableAnchors.push(properties.position);
                }
            });
            return availableAnchors;
        },
        attachToNearestAnchor: function() {
            var myProps = Entities.getEntityProperties(_this.entityID, ['position', 'dimensions']);
            var anchors = _this.getAnchorPoints();
            var shortestDistance = DO_NOT_SNAP_WHEN_FARTHER_THAN_THIS;
            var nearestAnchor = null;
            anchors.forEach(function(anchor) {
                var howFar = Vec3.distance(myProps.position, anchor);
                if (howFar < shortestDistance) {
                    shortestDistance = howFar;
                    nearestAnchor = anchor;
                }
            });

            if (shortestDistance > DO_NOT_SNAP_WHEN_FARTHER_THAN_THIS) {
                _this.setCurrentUserData({
                    attachedTo: null
                });
            } else {
                if (nearestAnchor !== null) {
                    _this.positionOnAnchor(nearestAnchor, myProps);
                    _this.setCurrentUserData({
                        attachedTo: nearestAnchor
                    });
                    Entities.editEntity(nearestAnchor, {
                        userData: 'occupied'
                    });
                } else {
                    // there is no nearest anchor.  perhaps they are all occupied.
                    _this.setCurrentUserData({
                        attachedTo: null
                    });
                }
            }

        },
        getEntitiesFromGroup: function(groupName, entityName) {
            var position = Entities.getEntityProperties(_this.entityID, 'position').position;
            var nearbyEntities = Entities.findEntities(position, 7.5);
            var foundItems = [];
            nearbyEntities.forEach(function(entityID) {
                var description = Entities.getEntityProperties(entityID, 'description').description;
                var descriptionSplit = description.split(":");
                if (descriptionSplit[1] === groupName && descriptionSplit[2] === entityName) {
                    foundItems.push(entityID);
                }
            });
            return foundItems;
        },
        positionOnAnchor: function(anchor, myProps) {
            Entities.editEntity(_this.entityID, {
                position: {
                    x: anchor.x,
                    y: anchor.y + (0.5 * myProps.dimensions.y),
                    z: anchor.z
                }
            });
        },
        setCurrentUserData: function(data) {
            var userData = _this.getCurrentUserData();
            userData.gameTable = data;
            Entities.editEntity(_this.entityID, {
                userData: userData
            });
        },
        getCurrentUserData: function() {
            var userData = Entities.getEntityProperties(_this.entityID, 'userData').userData;
            try {
                return JSON.parse(userData);
            } catch (e) {
                // e;
            }
            return null;
        }
    };
});