//
// facialExpressions.js
// A script to set different emotions using blend shapes
//
// Author: Elisa Lupin-Jimenez
// Copyright High Fidelity 2018
//
// Licensed under the Apache 2.0 License
// See accompanying license file or http://apache.org/
//
// All assets are under CC Attribution Non-Commerical
// http://creativecommons.org/licenses/
//

(function() {

    var TABLET_BUTTON_NAME = "EMOTIONS";
    // TODO: ADD HTML LANDING PAGE

    var TRANSITION_TIME_SECONDS = 0.25;

    var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
    var icon = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/icons/emoji-i.svg";
    var activeIcon = "https://hifi-content.s3.amazonaws.com/elisalj/emoji_scripts/icons/emoji-a.svg";
    var isActive = true;

    var controllerMappingName;
    var controllerMapping;

    var tabletButton = tablet.addButton({
        icon: icon,
        activeIcon: activeIcon,
        text: TABLET_BUTTON_NAME,
        isActive: true
    });

    var toggle = function() {
        isActive = !isActive;
        tabletButton.editProperties({isActive: isActive});
        if (isActive) {
            Controller.enableMapping(controllerMappingName);
        } else {
            setEmotion(DEFAULT);
            Controller.disableMapping(controllerMappingName);
        }
    };

    tabletButton.clicked.connect(toggle);

    var DEFAULT = {
        "EyeOpen_L": 0.00,
        "EyeOpen_R": 0.00,
        "EyeBlink_L": 0.00,
        "EyeBlink_R": 0.00,
        "EyeSquint_L": 0.00,
        "EyeSquint_R": 0.00,
        "BrowsD_L": 0.00,
        "BrowsD_R": 0.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 0.00,
        "JawOpen": 0.00,
        "JawFwd": 0.00,
        "MouthFrown_L": 0.00,
        "MouthFrown_R": 0.00,
        "MouthSmile_L": 0.00,
        "MouthSmile_R": 0.00,
        "MouthDimple_L": 0.00,
        "MouthDimple_R": 0.00,
        "LipsUpperClose": 0.00,
        "LipsLowerClose": 0.00,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.00,
        "Sneer": 0.00,
        "Puff": 0.00
    };

    var SMILE = {
        "EyeOpen_L": 0.00,
        "EyeOpen_R": 0.00,
        "EyeBlink_L": 0.30,
        "EyeBlink_R": 0.30,
        "EyeSquint_L": 0.90,
        "EyeSquint_R": 0.90,
        "BrowsD_L": 1.00,
        "BrowsD_R": 1.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 0.00,
        "JawOpen": 0.00,
        "JawFwd": 0.00,
        "MouthFrown_L": 0.00,
        "MouthFrown_R": 0.00,
        "MouthSmile_L": 1.00,
        "MouthSmile_R": 1.00,
        "MouthDimple_L": 1.00,
        "MouthDimple_R": 1.00,
        "LipsUpperClose": 0.40,
        "LipsLowerClose": 0.30,
        "LipsLowerOpen": 0.25,
        "ChinUpperRaise": 0.35,
        "Sneer": 0.00,
        "Puff": 0.00
    };

    var LAUGH = {
        "EyeOpen_L": 0.00,
        "EyeOpen_R": 0.00,
        "EyeBlink_L": 0.45,
        "EyeBlink_R": 0.45,
        "EyeSquint_L": 0.75,
        "EyeSquint_R": 0.75,
        "BrowsD_L": 0.00,
        "BrowsD_R": 0.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 0.50,
        "JawOpen": 0.50,
        "JawFwd": 0.00,
        "MouthFrown_L": 0.00,
        "MouthFrown_R": 0.00,
        "MouthSmile_L": 1.00,
        "MouthSmile_R": 1.00,
        "MouthDimple_L": 1.00,
        "MouthDimple_R": 1.00,
        "LipsUpperClose": 0.00,
        "LipsLowerClose": 0.00,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.30,
        "Sneer": 1.00,
        "Puff": 0.30
    };

    var FLIRT = {
        "EyeOpen_L": 0.00,
        "EyeOpen_R": 0.00,
        "EyeBlink_L": 0.50,
        "EyeBlink_R": 0.50,
        "EyeSquint_L": 0.25,
        "EyeSquint_R": 0.25,
        "BrowsD_L": 0.00,
        "BrowsD_R": 1.00,
        "BrowsU_L": 0.55,
        "BrowsU_C": 0.00,
        "JawOpen": 0.00,
        "JawFwd": 0.00,
        "MouthFrown_L": 0.00,
        "MouthFrown_R": 0.00,
        "MouthSmile_L": 0.50,
        "MouthSmile_R": 0.00,
        "MouthDimple_L": 1.00,
        "MouthDimple_R": 1.00,
        "LipsUpperClose": 0.00,
        "LipsLowerClose": 0.00,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.00,
        "Sneer": 0.00,
        "Puff": 0.00
    };

    var SAD = {
        "EyeOpen_L": 0.00,
        "EyeOpen_R": 0.00,
        "EyeBlink_L": 0.30,
        "EyeBlink_R": 0.30,
        "EyeSquint_L": 0.30,
        "EyeSquint_R": 0.30,
        "BrowsD_L": 0.00,
        "BrowsD_R": 0.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 0.50,
        "JawOpen": 0.00,
        "JawFwd": 0.80,
        "MouthFrown_L": 0.80,
        "MouthFrown_R": 0.80,
        "MouthSmile_L": 0.00,
        "MouthSmile_R": 0.00,
        "MouthDimple_L": 0.00,
        "MouthDimple_R": 0.00,
        "LipsUpperClose": 0.00,
        "LipsLowerClose": 0.50,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.00,
        "Sneer": 0.00,
        "Puff": 0.00
    };

    var ANGRY = {
        "EyeOpen_L": 1.00,
        "EyeOpen_R": 1.00,
        "EyeBlink_L": 0.00,
        "EyeBlink_R": 0.00,
        "EyeSquint_L": 1.00,
        "EyeSquint_R": 1.00,
        "BrowsD_L": 1.00,
        "BrowsD_R": 1.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 0.00,
        "JawOpen": 0.00,
        "JawFwd": 0.00,
        "MouthFrown_L": 0.50,
        "MouthFrown_R": 0.50,
        "MouthSmile_L": 0.00,
        "MouthSmile_R": 0.00,
        "MouthDimple_L": 0.00,
        "MouthDimple_R": 0.00,
        "LipsUpperClose": 0.50,
        "LipsLowerClose": 0.50,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.00,
        "Sneer": 0.50,
        "Puff": 0.00
    };

    var FEAR = {
        "EyeOpen_L": 1.00,
        "EyeOpen_R": 1.00,
        "EyeBlink_L": 0.00,
        "EyeBlink_R": 0.00,
        "EyeSquint_L": 0.00,
        "EyeSquint_R": 0.00,
        "BrowsD_L": 0.00,
        "BrowsD_R": 0.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 1.00,
        "JawOpen": 0.15,
        "JawFwd": 0.00,
        "MouthFrown_L": 0.30,
        "MouthFrown_R": 0.30,
        "MouthSmile_L": 0.00,
        "MouthSmile_R": 0.00,
        "MouthDimple_L": 0.00,
        "MouthDimple_R": 0.00,
        "LipsUpperClose": 0.00,
        "LipsLowerClose": 0.00,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.00,
        "Sneer": 0.00,
        "Puff": 0.00
    };

    var DISGUST = {
        "EyeOpen_L": 0.00,
        "EyeOpen_R": 0.00,
        "EyeBlink_L": 0.25,
        "EyeBlink_R": 0.25,
        "EyeSquint_L": 1.00,
        "EyeSquint_R": 1.00,
        "BrowsD_L": 1.00,
        "BrowsD_R": 1.00,
        "BrowsU_L": 0.00,
        "BrowsU_C": 0.00,
        "JawOpen": 0.00,
        "JawFwd": 0.00,
        "MouthFrown_L": 1.00,
        "MouthFrown_R": 1.00,
        "MouthSmile_L": 0.00,
        "MouthSmile_R": 0.00,
        "MouthDimple_L": 0.00,
        "MouthDimple_R": 0.00,
        "LipsUpperClose": 0.00,
        "LipsLowerClose": 0.75,
        "LipsLowerOpen": 0.00,
        "ChinUpperRaise": 0.75,
        "Sneer": 1.00,
        "Puff": 0.00
    };


    function mixValue(valueA, valueB, percentage) {
        return valueA + ((valueB - valueA) * percentage);
    }

    var lastEmotionUsed = DEFAULT;
    var emotion = DEFAULT;
    var isChangingEmotion = false;
    var changingEmotionPercentage = 0.0;

    Script.update.connect(function(deltaTime) {
        if (!isChangingEmotion) {
            return;
        }
        changingEmotionPercentage += deltaTime / TRANSITION_TIME_SECONDS;
        if (changingEmotionPercentage >= 1.0) {
            changingEmotionPercentage = 1.0;
            isChangingEmotion = false;
            if (emotion === DEFAULT) {
                MyAvatar.hasScriptedBlendshapes = false;
            }
        }
        for (var blendshape in emotion) {
            MyAvatar.setBlendshape(blendshape,
                mixValue(lastEmotionUsed[blendshape], emotion[blendshape], changingEmotionPercentage));
        }
    });

    function setEmotion(currentEmotion) {
        if (emotion !== lastEmotionUsed) {
            lastEmotionUsed = emotion;
        }
        if (currentEmotion !== lastEmotionUsed) {
            changingEmotionPercentage = 0.0;
            emotion = currentEmotion;
            isChangingEmotion = true;
            MyAvatar.hasScriptedBlendshapes = true;
        }
    }


    controllerMappingName = 'Hifi-FacialExpressions-Mapping';
    controllerMapping = Controller.newMapping(controllerMappingName);

    controllerMapping.from(Controller.Hardware.Keyboard.H).to(function(value) {
        if (value !== 0) {
            setEmotion(SMILE);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.J).to(function(value) {
        if (value !== 0) {
            setEmotion(LAUGH);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.K).to(function(value) {
        if (value !== 0) {
            setEmotion(FLIRT);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.L).to(function(value) {
        if (value !== 0) {
            setEmotion(SAD);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.V).to(function(value) {
        if (value !== 0) {
            setEmotion(ANGRY);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.B).to(function(value) {
        if (value !== 0) {
            setEmotion(FEAR);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.M).to(function(value) {
        if (value !== 0) {
            setEmotion(DISGUST);
        }
    });

    controllerMapping.from(Controller.Hardware.Keyboard.N).to(function(value) {
        if (value !== 0) {
            setEmotion(DEFAULT);
        }
    });

    Controller.enableMapping(controllerMappingName);

    Script.scriptEnding.connect(function() {
        tabletButton.clicked.disconnect(toggle);
        tablet.removeButton(tabletButton);
        Controller.disableMapping(controllerMappingName);

        if (emotion !== DEFAULT || isChangingEmotion) {
            isChangingEmotion = false;
            for (var blendshape in DEFAULT) {
                MyAvatar.setBlendshape(blendshape, DEFAULT[blendshape]);
            }
            MyAvatar.hasScriptedBlendshapes = false;
        }
    });

}());