"use strict";

//
//  controllers/squeezeHands.js
//
//  Created by Anthony J. Thibault
//  Copyright 2015 High Fidelity, Inc.
//
//  Default script to drive the animation of the hands based on hand controllers.
//
//  Distributed under the Apache License, Version 2.0.
//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global Script, MyAvatar, Messages, Controller */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */

(function() { // BEGIN LOCAL_SCOPE

var lastLeftTrigger = 0;
var lastRightTrigger = 0;
var leftHandOverlayAlpha = 0;
var rightHandOverlayAlpha = 0;

// var CONTROLLER_DEAD_SPOT = 0.25;
var TRIGGER_SMOOTH_TIMESCALE = 0.1;
var OVERLAY_RAMP_RATE = 8.0;

var animStateHandlerID;

var leftIndexPointingOverride = 0;
var rightIndexPointingOverride = 0;
var leftThumbRaisedOverride = 0;
var rightThumbRaisedOverride = 0;

var HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index";

var isLeftIndexPointing = false;
var isRightIndexPointing = false;
var isLeftThumbRaised = false;
var isRightThumbRaised = false;

function clamp(val, min, max) {
    return Math.min(Math.max(val, min), max);
}

// function normalizeControllerValue(val) {
//     return clamp((val - CONTROLLER_DEAD_SPOT) / (1 - CONTROLLER_DEAD_SPOT), 0, 1);
// }

function lerp(a, b, alpha) {
    return a * (1 - alpha) + b * alpha;
}

function init() {
    Script.update.connect(update);
    animStateHandlerID = MyAvatar.addAnimationStateHandler(
        animStateHandler,
        [
            "leftHandOverlayAlpha", "leftHandGraspAlpha",
            "rightHandOverlayAlpha", "rightHandGraspAlpha",
            "isLeftHandGrasp", "isLeftIndexPoint", "isLeftThumbRaise", "isLeftIndexPointAndThumbRaise",
            "isRightHandGrasp", "isRightIndexPoint", "isRightThumbRaise", "isRightIndexPointAndThumbRaise"
        ]
    );
    Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL);
    Messages.messageReceived.connect(handleMessages);
}

function animStateHandler(props) {
    return {
        leftHandOverlayAlpha: leftHandOverlayAlpha,
        leftHandGraspAlpha: lastLeftTrigger,
        rightHandOverlayAlpha: rightHandOverlayAlpha,
        rightHandGraspAlpha: lastRightTrigger,

        isLeftHandGrasp: !isLeftIndexPointing && !isLeftThumbRaised,
        isLeftIndexPoint: isLeftIndexPointing && !isLeftThumbRaised,
        isLeftThumbRaise: !isLeftIndexPointing && isLeftThumbRaised,
        isLeftIndexPointAndThumbRaise: isLeftIndexPointing && isLeftThumbRaised,

        isRightHandGrasp: !isRightIndexPointing && !isRightThumbRaised,
        isRightIndexPoint: isRightIndexPointing && !isRightThumbRaised,
        isRightThumbRaise: !isRightIndexPointing && isRightThumbRaised,
        isRightIndexPointAndThumbRaise: isRightIndexPointing && isRightThumbRaised
    };
}

function update(dt) {
    var leftTrigger = clamp(Controller.getValue(Controller.Standard.LT) + Controller.getValue(Controller.Standard.LeftGrip), 0, 1);
    var rightTrigger = clamp(Controller.getValue(Controller.Standard.RT) + Controller.getValue(Controller.Standard.RightGrip), 0, 1);

    //  Average last few trigger values together for a bit of smoothing
    var tau = clamp(dt / TRIGGER_SMOOTH_TIMESCALE, 0, 1);
    lastLeftTrigger = lerp(leftTrigger, lastLeftTrigger, tau);
    lastRightTrigger = lerp(rightTrigger, lastRightTrigger, tau);

    // ramp on/off left hand overlay
    var leftHandPose = Controller.getPoseValue(Controller.Standard.LeftHand);
    if (leftHandPose.valid) {
        leftHandOverlayAlpha = clamp(leftHandOverlayAlpha + OVERLAY_RAMP_RATE * dt, 0, 1);
    } else {
        leftHandOverlayAlpha = clamp(leftHandOverlayAlpha - OVERLAY_RAMP_RATE * dt, 0, 1);
    }

    // ramp on/off right hand overlay
    var rightHandPose = Controller.getPoseValue(Controller.Standard.RightHand);
    if (rightHandPose.valid) {
        rightHandOverlayAlpha = clamp(rightHandOverlayAlpha + OVERLAY_RAMP_RATE * dt, 0, 1);
    } else {
        rightHandOverlayAlpha = clamp(rightHandOverlayAlpha - OVERLAY_RAMP_RATE * dt, 0, 1);
    }

    // Pointing index fingers and raising thumbs
    isLeftIndexPointing = (leftIndexPointingOverride > 0) || (leftHandPose.valid && Controller.getValue(Controller.Standard.LeftIndexPoint) === 1);
    isRightIndexPointing = (rightIndexPointingOverride > 0) || (rightHandPose.valid && Controller.getValue(Controller.Standard.RightIndexPoint) === 1);
    isLeftThumbRaised = (leftThumbRaisedOverride > 0) || (leftHandPose.valid && Controller.getValue(Controller.Standard.LeftThumbUp) === 1);
    isRightThumbRaised = (rightThumbRaisedOverride > 0) || (rightHandPose.valid && Controller.getValue(Controller.Standard.RightThumbUp) === 1);
}

function handleMessages(channel, message, sender) {
    if (sender === MyAvatar.sessionUUID && channel === HIFI_POINT_INDEX_MESSAGE_CHANNEL) {
        var data = JSON.parse(message);

        if (data.pointIndex !== undefined) {
            if (data.pointIndex) {
                leftIndexPointingOverride++;
                rightIndexPointingOverride++;
            } else {
                leftIndexPointingOverride--;
                rightIndexPointingOverride--;
            }
        }
        if (data.pointLeftIndex !== undefined) {
            if (data.pointLeftIndex) {
                leftIndexPointingOverride++;
            } else {
                leftIndexPointingOverride--;
            }
        }
        if (data.pointRightIndex !== undefined) {
            if (data.pointRightIndex) {
                rightIndexPointingOverride++;
            } else {
                rightIndexPointingOverride--;
            }
        }
        if (data.raiseThumbs !== undefined) {
            if (data.raiseThumbs) {
                leftThumbRaisedOverride++;
                rightThumbRaisedOverride++;
            } else {
                leftThumbRaisedOverride--;
                rightThumbRaisedOverride--;
            }
        }
        if (data.raiseLeftThumb !== undefined) {
            if (data.raiseLeftThumb) {
                leftThumbRaisedOverride++;
            } else {
                leftThumbRaisedOverride--;
            }
        }
        if (data.raiseRightThumb !== undefined) {
            if (data.raiseRightThumb) {
                rightThumbRaisedOverride++;
            } else {
                rightThumbRaisedOverride--;
            }
        }
    }
}

function shutdown() {
    Script.update.disconnect(update);
    MyAvatar.removeAnimationStateHandler(animStateHandlerID);
    Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL);
    Messages.messageReceived.disconnect(handleMessages);
}

Script.scriptEnding.connect(shutdown);

init();

}()); // END LOCAL_SCOPE