/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

define(function (require, exports, module) {

    var event = require("../lib/event");
    var useragent = require("../lib/useragent");

// mouse
    function isSamePoint(p1, p2) {
        return p1.row == p2.row && p1.column == p2.column;
    }

    function onMouseDown(e) {
        var ev = e.domEvent;
        var alt = ev.altKey;
        var shift = ev.shiftKey;
        var ctrl = ev.ctrlKey;
        var accel = e.getAccelKey();
        var button = e.getButton();

        if (ctrl && useragent.isMac)
            button = ev.button;

        if (e.editor.inMultiSelectMode && button == 2) {
            e.editor.textInput.onContextMenu(e.domEvent);
            return;
        }

        if (!ctrl && !alt && !accel) {
            if (button === 0 && e.editor.inMultiSelectMode)
                e.editor.exitMultiSelectMode();
            return;
        }

        if (button !== 0)
            return;

        var editor = e.editor;
        var selection = editor.selection;
        var isMultiSelect = editor.inMultiSelectMode;
        var pos = e.getDocumentPosition();
        var cursor = selection.getCursor();
        var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));

        var mouseX = e.x, mouseY = e.y;
        var onMouseSelection = function (e) {
            mouseX = e.clientX;
            mouseY = e.clientY;
        };

        var session = editor.session;
        var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
        var screenCursor = screenAnchor;

        var selectionMode;
        if (editor.$mouseHandler.$enableJumpToDef) {
            if (ctrl && alt || accel && alt)
                selectionMode = shift ? "block" : "add";
            else if (alt && editor.$blockSelectEnabled)
                selectionMode = "block";
        } else {
            if (accel && !alt) {
                selectionMode = "add";
                if (!isMultiSelect && shift)
                    return;
            } else if (alt && editor.$blockSelectEnabled) {
                selectionMode = "block";
            }
        }

        if (selectionMode && useragent.isMac && ev.ctrlKey) {
            editor.$mouseHandler.cancelContextMenu();
        }

        if (selectionMode == "add") {
            if (!isMultiSelect && inSelection)
                return; // dragging

            if (!isMultiSelect) {
                var range = selection.toOrientedRange();
                editor.addSelectionMarker(range);
            }

            var oldRange = selection.rangeList.rangeAtPoint(pos);


            editor.$blockScrolling++;
            editor.inVirtualSelectionMode = true;

            if (shift) {
                oldRange = null;
                range = selection.ranges[0] || range;
                editor.removeSelectionMarker(range);
            }
            editor.once("mouseup", function () {
                var tmpSel = selection.toOrientedRange();

                if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))
                    selection.substractPoint(tmpSel.cursor);
                else {
                    if (shift) {
                        selection.substractPoint(range.cursor);
                    } else if (range) {
                        editor.removeSelectionMarker(range);
                        selection.addRange(range);
                    }
                    selection.addRange(tmpSel);
                }
                editor.$blockScrolling--;
                editor.inVirtualSelectionMode = false;
            });

        } else if (selectionMode == "block") {
            e.stop();
            editor.inVirtualSelectionMode = true;
            var initialRange;
            var rectSel = [];
            var blockSelect = function () {
                var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
                var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);

                if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead))
                    return;
                screenCursor = newCursor;

                editor.$blockScrolling++;
                editor.selection.moveToPosition(cursor);
                editor.renderer.scrollCursorIntoView();

                editor.removeSelectionMarkers(rectSel);
                rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
                if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty())
                    rectSel[0] = editor.$mouseHandler.$clickSelection.clone();
                rectSel.forEach(editor.addSelectionMarker, editor);
                editor.updateSelectionMarkers();
                editor.$blockScrolling--;
            };
            editor.$blockScrolling++;
            if (isMultiSelect && !accel) {
                selection.toSingleRange();
            } else if (!isMultiSelect && accel) {
                initialRange = selection.toOrientedRange();
                editor.addSelectionMarker(initialRange);
            }

            if (shift)
                screenAnchor = session.documentToScreenPosition(selection.lead);
            else
                selection.moveToPosition(pos);
            editor.$blockScrolling--;

            screenCursor = {row: -1, column: -1};

            var onMouseSelectionEnd = function (e) {
                clearInterval(timerId);
                editor.removeSelectionMarkers(rectSel);
                if (!rectSel.length)
                    rectSel = [selection.toOrientedRange()];
                editor.$blockScrolling++;
                if (initialRange) {
                    editor.removeSelectionMarker(initialRange);
                    selection.toSingleRange(initialRange);
                }
                for (var i = 0; i < rectSel.length; i++)
                    selection.addRange(rectSel[i]);
                editor.inVirtualSelectionMode = false;
                editor.$mouseHandler.$clickSelection = null;
                editor.$blockScrolling--;
            };

            var onSelectionInterval = blockSelect;

            event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
            var timerId = setInterval(function () {
                onSelectionInterval();
            }, 20);

            return e.preventDefault();
        }
    }


    exports.onMouseDown = onMouseDown;

});
