//
//  Leaves.js
//  examples
//
//  Created by Bing Shearer on 14 Jul 2015
//  Copyright 2015 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
//
var leafName = "scriptLeaf";
var leafSquall = function (properties) {
    var // Properties
    squallOrigin,
    squallRadius,
    leavesPerMinute = 60,
        leafSize = {
            x: 0.1,
            y: 0.1,
            z: 0.1
        },
        leafFallSpeed = 1, // m/s
        leafLifetime = 60, // Seconds
        leafSpinMax = 0, // Maximum angular velocity per axis; deg/s
        debug = false, // Display origin circle; don't use running on Stack Manager
        // Other
        squallCircle,
        SQUALL_CIRCLE_COLOR = {
            red: 255,
            green: 0,
            blue: 0
        },
        SQUALL_CIRCLE_ALPHA = 0.5,
        SQUALL_CIRCLE_ROTATION = Quat.fromPitchYawRollDegrees(90, 0, 0),
        leafProperties,
        leaf_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ozan/support/forBing/palmLeaf.fbx",
        leafTimer,
        leaves = [], // HACK: Work around leaves not always getting velocities
        leafVelocities = [], // HACK: Work around leaves not always getting velocities
        DEGREES_TO_RADIANS = Math.PI / 180,
        leafDeleteOnTearDown = true,
        maxLeaves,
        leafCount,
        nearbyEntities,
        complexMovement = false,
        movementTime = 0,
        maxSpinRadians = properties.leafSpinMax * DEGREES_TO_RADIANS,
        windFactor,
        leafDeleteOnGround = false,
        floorHeight = null;


    function processProperties() {
        if (!properties.hasOwnProperty("origin")) {
            print("ERROR: Leaf squall origin must be specified");
            return;
        }
        squallOrigin = properties.origin;

        if (!properties.hasOwnProperty("radius")) {
            print("ERROR: Leaf squall radius must be specified");
            return;
        }
        squallRadius = properties.radius;

        if (properties.hasOwnProperty("leavesPerMinute")) {
            leavesPerMinute = properties.leavesPerMinute;
        }

        if (properties.hasOwnProperty("leafSize")) {
            leafSize = properties.leafSize;
        }

        if (properties.hasOwnProperty("leafFallSpeed")) {
            leafFallSpeed = properties.leafFallSpeed;
        }

        if (properties.hasOwnProperty("leafLifetime")) {
            leafLifetime = properties.leafLifetime;
        }

        if (properties.hasOwnProperty("leafSpinMax")) {
            leafSpinMax = properties.leafSpinMax;
        }

        if (properties.hasOwnProperty("debug")) {
            debug = properties.debug;
        }
        if (properties.hasOwnProperty("floorHeight")) {
            floorHeight = properties.floorHeight;
        }
        if (properties.hasOwnProperty("maxLeaves")) {
            maxLeaves = properties.maxLeaves;
        }
        if (properties.hasOwnProperty("complexMovement")) {
            complexMovement = properties.complexMovement;
        }
        if (properties.hasOwnProperty("leafDeleteOnGround")) {
            leafDeleteOnGround = properties.leafDeleteOnGround;
        }
        if (properties.hasOwnProperty("windFactor")) {
            windFactor = properties.windFactor;
        } else if (complexMovement == true){
            print("ERROR: Wind Factor must be defined for complex movement")
        }

        leafProperties = {
            type: "Model",
            name: leafName,
            modelURL: leaf_MODEL_URL,
            lifetime: leafLifetime,
            dimensions: leafSize,
            velocity: {
                x: 0,
                y: -leafFallSpeed,
                z: 0
            },
            damping: 0,
            angularDamping: 0,
            collisionless: true

        };
    }

    function createleaf() {
        var angle,
        radius,
        offset,
        leaf,
        spin = {
            x: 0,
            y: 0,
            z: 0
        },
        i;

        // HACK: Work around leaves not always getting velocities set at creation
        for (i = 0; i < leaves.length; i++) {
            Entities.editEntity(leaves[i], leafVelocities[i]);
        }

        angle = Math.random() * leafSpinMax;
        radius = Math.random() * squallRadius;
        offset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, angle, 0), {
            x: 0,
            y: -0.1,
            z: radius
        });
        leafProperties.position = Vec3.sum(squallOrigin, offset);
        if (properties.leafSpinMax > 0 && !complexMovement) {
            spin = {
                x: Math.random() * maxSpinRadians,
                y: Math.random() * maxSpinRadians,
                z: Math.random() * maxSpinRadians
            };
            leafProperties.angularVelocity = spin;
        } else if (complexMovement) {
            spin = {
                x: 0,
                y: 0,
                z: 0
            };
            leafProperties.angularVelocity = spin
        }
        leaf = Entities.addEntity(leafProperties);

        // HACK: Work around leaves not always getting velocities set at creation
        leaves.push(leaf);
        leafVelocities.push({
            velocity: leafProperties.velocity,
            angularVelocity: spin
        });
        if (leaves.length > 5) {
            leaves.shift();
            leafVelocities.shift();
        }
    }

    function setUp() {
        if (debug) {
            squallCircle = Overlays.addOverlay("circle3d", {
                size: {
                    x: 2 * squallRadius,
                    y: 2 * squallRadius
                },
                color: SQUALL_CIRCLE_COLOR,
                alpha: SQUALL_CIRCLE_ALPHA,
                solid: true,
                visible: debug,
                position: squallOrigin,
                rotation: SQUALL_CIRCLE_ROTATION
            });
        }

        leafTimer = Script.setInterval(function () {
            if (leafCount <= maxLeaves - 1) {
                createleaf()
            }
        }, 60000 / leavesPerMinute);
    }
    Script.setInterval(function () {
        nearbyEntities = Entities.findEntities(squallOrigin, squallRadius);
        newLeafMovement()
    }, 100);

    function newLeafMovement() { //new additions to leaf code. Operates at 10 Hz or every 100 ms
        movementTime += 0.1;
        var currentLeaf,
        randomRotationSpeed = {
            x: maxSpinRadians * Math.sin(movementTime),
            y: maxSpinRadians * Math.random(),
            z: maxSpinRadians * Math.sin(movementTime / 7)
        };
        for (var i = 0; i < nearbyEntities.length; i++) {
            var entityProperties = Entities.getEntityProperties(nearbyEntities[i]);
            var entityName = entityProperties.name;
            if (leafName === entityName) {
                currentLeaf = nearbyEntities[i];
                var leafHeight = entityProperties.position.y;
                if (complexMovement && leafHeight > floorHeight || complexMovement && floorHeight == null) { //actual new movement code;
                    var leafCurrentVel = entityProperties.velocity,
                        leafCurrentRot = entityProperties.rotation,
                        yVec = {
                            x: 0,
                            y: 1,
                            z: 0
                        },
                        leafYinWFVec = Vec3.multiplyQbyV(leafCurrentRot, yVec),
                        leafLocalHorVec = Vec3.cross(leafYinWFVec, yVec),
                        leafMostDownVec = Vec3.cross(leafYinWFVec, leafLocalHorVec),
                        leafDesiredVel = Vec3.multiply(leafMostDownVec, windFactor),
                        leafVelDelt = Vec3.subtract(leafDesiredVel, leafCurrentVel),
                        leafNewVel = Vec3.sum(leafCurrentVel, Vec3.multiply(leafVelDelt, windFactor));
                    Entities.editEntity(currentLeaf, {
                        angularVelocity: randomRotationSpeed,
                        velocity: leafNewVel
                    })
                } else if (leafHeight <= floorHeight) {
                    if (!leafDeleteOnGround) {
                        Entities.editEntity(nearbyEntities[i], {
                            locked: false,
                            velocity: {
                                x: 0,
                                y: 0,
                                z: 0
                            },
                            angularVelocity: {
                                x: 0,
                                y: 0,
                                z: 0
                            }
                        })
                    } else {
                        Entity.deleteEntity(currentLeaf);
                    }
                }
            }
        }
    }



    getLeafCount = Script.setInterval(function () {
        leafCount = 0
        for (var i = 0; i < nearbyEntities.length; i++) {
            var entityName = Entities.getEntityProperties(nearbyEntities[i]).name;
            //Stop Leaves at floorHeight
            if (leafName === entityName) {
                leafCount++;
                if (i == nearbyEntities.length - 1) {
                    //print(leafCount);
                }
            }
        }
    }, 1000)



    function tearDown() {
        Script.clearInterval(leafTimer);
        Overlays.deleteOverlay(squallCircle);
        if (leafDeleteOnTearDown) {
            for (var i = 0; i < nearbyEntities.length; i++) {
                var entityName = Entities.getEntityProperties(nearbyEntities[i]).name;
                if (leafName === entityName) {
                    //We have a match - delete this entity
                    Entities.editEntity(nearbyEntities[i], {
                        locked: false
                    });
                    Entities.deleteEntity(nearbyEntities[i]);
                }
            }
        }
    }



    processProperties();
    setUp();
    Script.scriptEnding.connect(tearDown);

    return {};
};

var leafSquall1 = new leafSquall({
    origin: {
        x: 3071.5,
        y: 2170,
        z: 6765.3
    },
    radius: 100,
    leavesPerMinute: 30,
    leafSize: {
        x: 0.3,
        y: 0.00,
        z: 0.3
    },
    leafFallSpeed: 0.4,
    leafLifetime: 100,
    leafSpinMax: 30,
    debug: false,
    maxLeaves: 100,
    leafDeleteOnTearDown: true,
    complexMovement: true,
    floorHeight: 2143.5,
    windFactor: 0.5,
    leafDeleteOnGround: false
});

// todo
//deal with depth issue