<!DOCTYPE html>
<html>
<head>
<script src="../resources/js-test.js"></script>
<script src="resources/audio-testing.js"></script>
</head>

<body>
<div id="description"></div>
<div id="console"></div>

<script>
description("Basic tests for PannerNode.");

var context = 0;

function runTest() {
    window.jsTestIsAsync = true;

    context = new AudioContext();
    var panner = context.createPanner();
   
    if (panner.numberOfInputs === 1) 
        testPassed("PannerNode has one input.");
    else
        testFailed("PannerNode should have one input.");
    
    if (panner.numberOfOutputs === 1) 
        testPassed("PannerNode has one output.");
    else
        testFailed("PannerNode should have one output.");

    if (panner.refDistance === 1)
        testPassed("refDistance default value is 1.");
    else
        testFailed("refDistance default value should be 1.");
    
    panner.refDistance = 270.52
    if (panner.refDistance === 270.52)
        testPassed("refDistance value is set to 270.52.");
    else
        testFailed("refDistance value should be set to 270.52.");

    try {
        panner.refDistance = -1
        testFailed("Exception should be thrown when refDistance is set to negative value.");
    } catch(e) {
        testPassed("Exception has been thrown correctly when refDistance is set to negative value.");
    }
    
    if (panner.maxDistance === 10000)
        testPassed("maxDistance default value is 10000.");
    else
        testFailed("maxDistance default value should be 10000.");
    
    panner.maxDistance = 100.55
    if (panner.maxDistance === 100.55)
        testPassed("maxDistance value is set to 100.55.");
    else
        testFailed("maxDistance value should be set to 100.55.");

    try {
        panner.maxDistance = 0
        testFailed("Exception should be thrown when maxDistance is set to non-positive value (set to 0).");
    } catch(e) {
        testPassed("Exception has been thrown correctly when maxDistance is set to non-positive value (set to 0).");
    }

    try {
        panner.maxDistance = -1
        testFailed("Exception should be thrown when maxDistance is set to non-positive value (set to -1).");
    } catch(e) {
        testPassed("Exception has been thrown correctly when maxDistance is set to non-positive value (set to -1).");
    }
    
    if (panner.rolloffFactor === 1)
        testPassed("rolloffFactor default value is 1.");
    else
        testFailed("rolloffFactor default value should be 1.");
    
    panner.rolloffFactor = 0.83
    if (panner.rolloffFactor === 0.83)
        testPassed("rolloffFactor value is set to 0.83.");
    else
        testFailed("rolloffFactor value should be set to 0.83.");

    try {
        panner.rolloffFactor = -1
        testFailed("Exception should be thrown when rolloffFactor is set to ngative value.");
    } catch(e) {
        testPassed("Exception has been thrown correctly when rolloffFactor is set to negative value.");
    }
    
    if (panner.coneInnerAngle === 360)
        testPassed("coneInnerAngle default value is 360.");
    else
        testFailed("coneInnerAngle default value should be 360.");

    panner.coneInnerAngle = 0
    if (panner.coneInnerAngle === 0)
        testPassed("coneInnerAngle value is set to 0");
    else
        testFailed("coneInnerAngle value should be set to 0.");
    
    panner.coneInnerAngle = 240.45
    if (panner.coneInnerAngle === 240.45)
        testPassed("coneInnerAngle value is set to 240.45.");
    else
        testFailed("coneInnerAngle value should be set to 240.45.");
    
    if (panner.coneOuterAngle === 360)
        testPassed("coneOuterAngle default value is 360.");
    else
        testFailed("coneOuterAngle default value should be 360.");

    panner.coneOuterAngle = 0
    if (panner.coneOuterAngle === 0)
        testPassed("coneOuterAngle value is set to 0.");
    else
        testFailed("coneOuterAngle value should be set to 0.");
    
    panner.coneOuterAngle = 166.66
    if (panner.coneOuterAngle === 166.66)
        testPassed("coneOuterAngle value is set to 166.66.");
    else
        testFailed("coneOuterAngle value should be set to 166.66.");
    
    if (panner.coneOuterGain === 0)
        testPassed("coneOuterGain default value is 0.");
    else
        testFailed("coneOuterGain default value should be 0.");

    panner.coneOuterGain = 1
    if (panner.coneOuterGain === 1)
        testPassed("coneOuterGain value is set to 1.");
    else
        testFailed("coneOuterGain value should be set to 1.");

    panner.coneOuterGain = 0.35
    if (panner.coneOuterGain === 0.35)
        testPassed("coneOuterGain value is set to 0.35.");
    else
        testFailed("coneOuterGain value should be set to 0.35.");

    try {
        panner.coneOuterGain = -1
        testFailed("Exception should be thrown when coneOuterGain is set outside [0, 1] (was set to -1).");
    } catch(e) {
        testPassed("Exception has been thrown correctly when coneOuterGain is set outside [0, 1] (was set to -1).");
    }

    try {
        panner.coneOuterGain = 2
        testFailed("Exception should be thrown when coneOuterGain is set outside [0, 1] (was set to 2).");
    } catch(e) {
        testPassed("Exception has been thrown correctly when coneOuterGain is set outside [0, 1] (was set to 2).");
    }

    if (panner.panningModel === "equalpower")
        testPassed("PannerNode defaults to 'equalpower' panningModel.");
    else
        testFailed("PannerNode should default to 'equalpower' panningModel.");
    
    if (panner.distanceModel === "inverse")
        testPassed("PannerNode defaults to 'inverse' distanceModel.");
    else
        testFailed("PannerNode should default to 'inverse' distanceModel.");

    // Check that the .panningModel attribute can be set to all legal values.
    var panningModels = [{value: "equalpower"},
                         {value: "HRTF"},
                        ];

    for (var i = 0; i < panningModels.length; ++i) {
        try {
            panner.panningModel = panningModels[i].value;
            if (panner.panningModel === panningModels[i].value) {
                var message = "panningModel: '" + panningModels[i].value + "' is settable.";
                testPassed(message);
            } else {
                var message = "panningModel: '" + panningModels[i].value + "' was not correctly set.";
                testFailed(message);
            }
        } catch(e) {
            var message = "Setting panningModel to '" + panningModels[i].value + "' should not throw exception.";
            testFailed(message);
        }
    }

    // Check that the .distanceModel attribute can be set to all legal values.
    var distanceModels = [{value: "linear"},
                          {value: "inverse"},
                          {value: "exponential"}];

    for (var i = 0; i < distanceModels.length; ++i) {
        try {
            panner.distanceModel = distanceModels[i].value;
            if (panner.distanceModel === distanceModels[i].value) {
                var message = "distanceModel: '" + distanceModels[i].value + "' is settable.";
                testPassed(message);
            } else {
                var message = "distanceModel: '" + distanceModels[i].value + "' was not correctly set.";
                testFailed(message);
            }
        } catch(e) {
            var message = "Setting distanceModel to '" + distanceModels[i].value + "' should not throw exception.";
            testFailed(message);
        }
    }

    // Testing rolloffFactor when distanceModel is linear
    panner.distanceModel = distanceModels[0].value

    panner.rolloffFactor = 0
    if (panner.rolloffFactor === 0)
        testPassed("With linear distanceModel, rolloffFactor is set to 0.");
    else
        testFailed("With linear distanceModel, rolloffFactor should be set to 0.");

    panner.rolloffFactor = 0.5
    if (panner.rolloffFactor === 0.5)
        testPassed("With linear distanceModel, rolloffFactor is set to 0.5.");
    else
        testFailed("With linear distanceModel, rolloffFactor should be set to 0.5.");

    panner.rolloffFactor = 1
    if (panner.rolloffFactor === 1)
        testPassed("With linear distanceModel, rolloffFactor is set to 1.");
    else
        testFailed("With linear distanceModel, rolloffFactor should be set to 1.");

    // FIXME: Implement clamping test for linear model once feedback is received

    panner.distanceModel = distanceModels[1].value

    panner.rolloffFactor = 0
    if (panner.rolloffFactor === 0)
        testPassed("With inverse distanceModel, rolloffFactor is set to 0.");
    else
        testFailed("With inverse distanceModel, rolloffFactor should be set to 0.");

    panner.rolloffFactor = 10000
    if (panner.rolloffFactor === 10000)
        testPassed("With inverse distanceModel, rolloffFactor is set to 10000.");
    else
        testFailed("With inverse distanceModel, rolloffFactor should be set to 10000.");

    // Testing rollOffFactor when distanceModel is exponential
    panner.distanceModel = distanceModels[2].value

    panner.rolloffFactor = 0
    if (panner.rolloffFactor === 0)
        testPassed("With exponential distanceModel, rolloffFactor is set to 0.");
    else
        testFailed("With exponential distanceModel, rolloffFactor should be set to 0.");

    panner.rolloffFactor = 10000
    if (panner.rolloffFactor === 10000)
        testPassed("With exponential distanceModel, rolloffFactor is set to 10000.");
    else
        testFailed("With exponential distanceModel, rolloffFactor should be set to 10000.");

    // Check that we don't throw an exception for illegal .distanceModel values as per WebIDL.
    shouldNotThrowException(function() { panner.distanceModel = "xyz12349jfksd"; }, "Setting .distanceModel to illegal string value");
    shouldNotThrowException(function() { panner.distanceModel = new Float32Array(1); }, "Setting .distanceModel to illegal type");

    finishJSTest();
}

runTest();

</script>
</body>
</html>
