<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<style>
#dropTarget, #dragMe { text-align: center; display: table-cell; vertical-align: middle }
#dropTarget {width: 256px; height: 256px; border: 1px dashed}
#dragMe {-webkit-user-drag: element; -webkit-user-select: none; background: #ff0000; width: 64px; height: 64px; color: white}
</style>
<script>
    var dragMe;
    var dropTarget;
    var effectAllowedElem;
    var dropEffectElem;
    var consoleElm;
    var event;
    
    window.onload = function()
    {
        dragMe = document.getElementById("dragMe");
        dropTarget = document.getElementById("dropTarget");
        effectAllowedElem = document.getElementById("effectAllowed");
        dropEffectElem = document.getElementById("dropEffect");
        consoleElm = document.getElementById("console");
        
        if (!dragMe || !dropTarget || !effectAllowedElem || !dropEffectElem || !consoleElm)
            return;
        
        dragMe.ondragstart = dragStart;
        dragMe.ondragend = dragEnd;
        
        dropTarget.ondragenter = dragEntered;
        dropTarget.ondragover = dragOver;
        dropTarget.ondrop = drop;
        
        runTest();
    }
    
    function dragStart(e)
    {
        event = e;
        if (effectAllowedElem.options[effectAllowedElem.selectedIndex].value != "undefined")
            e.dataTransfer.effectAllowed = effectAllowedElem.options[effectAllowedElem.selectedIndex].value;

        e.dataTransfer.setData('Text', e.target.textContent);
    }
    
    function dragEnd(e)
    {
        checkDragState(e);
        return;
    }
    
    function dragEntered(e)
    {
        dragEnteredAndUpdated(e);
    }
    
    function dragOver(e)
    {
        dragEnteredAndUpdated(e);
    }
    
    function dragEnteredAndUpdated(e)
    {
        event = e;
        e.dataTransfer.dropEffect = dropEffectElem.options[dropEffectElem.selectedIndex].value;
        cancelDrag(e);
    }
    
    function drop(e)
    {
        cancelDrag(e);
    }
    
    function cancelDrag(e)
    {
        if (e.preventDefault)
            e.preventDefault();
        else {
            // Assume this script is executing within Internet Explorer
            e.returnValue = false;
        }
    }
    
    function checkDragState(e)
    {
        event = e;
        var chosenDropEffect = dropEffectElem.options[dropEffectElem.selectedIndex].value;
        var chosenEffectAllowed = effectAllowedElem.options[effectAllowedElem.selectedIndex].value;
        var actualDropEffect = e.dataTransfer.dropEffect;
        
        if (chosenEffectAllowed === "undefined") {
            // If no effectAllowed is set, we should default to uninitialized. Make sure that's the case.
            shouldBeEqualToString("event.dataTransfer.effectAllowed", "uninitialized");
            
            // Then set the chosenEffectAllowed so isDropEffectAllowed matches the HTML5 spec, and
            // doesn't need special cases for undefined.
            chosenEffectAllowed = "uninitialized";
        }
        
        if (chosenEffectAllowed === "dummy") {
            // If a bad effectAllowed is attempted to be set, it should never be set, and the
            // effectAllowed should be uninitialized.
            shouldBeEqualToString("event.dataTransfer.effectAllowed", "uninitialized");
            
            // Then set the chosenEffectAllowed so isDropEffectAllowed matches the HTML5 spec, and
            // doesn't need special cases for undefined.
            chosenEffectAllowed = "uninitialized";
        }
        expected = dropEffectElem.options[dropEffectElem.selectedIndex].value;
        if (chosenDropEffect == "dummy") {
            switch (chosenEffectAllowed) {
                case "undefined":
                case "copyLink":
                case "uninitialized":
                case "all":
                    expected = "copy";
                    break;
                case "copyMove":
                case "move":
                case "linkMove":
                    expected = "move";
                    break;
                default:
                    expected = chosenEffectAllowed;
            }
        }
        if (isDropEffectAllowed(chosenDropEffect, chosenEffectAllowed))
            shouldBeEqualToString('event.dataTransfer.dropEffect', expected);
        else
            shouldBeEqualToString('event.dataTransfer.dropEffect', 'none');
            
    }
    
    function isDropEffectAllowed(chosenDropEffect, allowedDropEffect) {
        // Extracted from the HTML 5 drag-and-drop section, http://dev.w3.org/html5/spec/Overview.html#dnd
        if (chosenDropEffect == "none")
            return true;
        if (chosenDropEffect == "copy" && ["copy", "copyLink", "copyMove", "uninitialized", "all"].indexOf(allowedDropEffect) != -1)
            return true;
        if (chosenDropEffect == "move" && ["move", "copyMove", "linkMove", "uninitialized", "all"].indexOf(allowedDropEffect) != -1)
            return true;
        if (chosenDropEffect == "link" && ["link", "copyLink", "linkMove", "uninitialized", "all"].indexOf(allowedDropEffect) != -1)
            return true;
        if (chosenDropEffect == "dummy" && ["copy", "link", "move", "copyLink", "copyMove", "linkMove", "uninitialized", "all"].indexOf(allowedDropEffect) != -1)
            return true; 
        return false;
    }

    function runTest()
    {
        if (!window.eventSender)
            return;
            
        if (window.testRunner)
            testRunner.dumpAsText();
            
        var startX = dragMe.offsetLeft + 10;
        var startY = dragMe.offsetTop + dragMe.offsetHeight / 2;
        var endX = dropTarget.offsetLeft + 10;
        var endY = dropTarget.offsetTop + dropTarget.offsetHeight / 2;
        
        var numEffectAllowed = effectAllowedElem.options.length;
        var numEffects = dropEffectElem.options.length;
        
        for (var i = 0; i < numEffectAllowed; ++i) {
            effectAllowedElem.options[i].selected = true;
            debug('<br />When effectAllowed == "' + effectAllowedElem.options[i].value + '"<br />');
            for (var j = 0; j < numEffects; ++j) {
                dropEffectElem.options[j].selected = true;
                eventSender.mouseMoveTo(startX, startY);
                eventSender.mouseDown();
                eventSender.leapForward(100);
                eventSender.mouseMoveTo(endX, endY);
                eventSender.mouseUp();
            }
        }
        var testContainer = document.getElementById("test-container");
        if (testContainer)
            document.body.removeChild(testContainer);
        debug('<br /><span class="pass">TEST COMPLETE</span>');
    }
</script>
</head>
<body>
    <p id="description"></p>
    <div id="test-container">
        <label for="effectAllowed">effectAllowed</label> <select id="effectAllowed">
            <option value="uninitialized">Uninitialized</option>
            <option value="undefined">Undefined</option>
            <option value="none">None</option>
            <option value="all">All</option>
            <option value="copy">Copy</option>
            <option value="move">Move</option>
            <option value="link">Link</option>
            <option value="copyMove">CopyMove</option>
            <option value="copyLink">CopyLink</option>
            <option value="linkMove">LinkMove</option>
            <option value="dummy">Nonexistent (Dummy) Effect</option>
        </select>
        <br/><br/>
        <div id="dropTarget">Drop the red square onto me.<br/><br/>
            <label for="dropEffect">Expects dropEffect</label> <select id="dropEffect">
                <option value="none">None</option>
                <option value="copy">Copy</option>
                <option value="move">Move</option>
                <option value="link">Link</option>
                <option value="dummy">Nonexistent (Dummy) Effect</option>
            </select>
        </div>
        <hr/>
        <p>Items that can be dragged to the drop target:</p>
        <div id="dragMe" draggable="true">Square</div>
        <hr/>
    </div>
    <div id="console"></div>
    <script>
        description("This test checks that drag-and-drop support works and conforms to the HTML 5 specification.<br/>" +
                    "For each effectAllowed, iterates through the possible dropEffects: none, copy, move, link, dummy.");
    </script>
</body>
</html>
