var itemComponent = null;
var draggedItem = null;
var startingMouse;
var posnInWindow;       //!< current position in \a window
var posnInWindowCorr;   //!< corrected position in \a window while \a draggedItem inside \a diagramField
var posnInDiagramContainer  //!< current position in \a diagramContainer
var posnInDiagramField  //!< current position in \a diagramField
var posnDraggingX       //!< calculated X-coorditate of draggedItem while being dragged
var posnDraggingY       //!< calculated Y-coorditate of draggedItem while being dragged

//! Check \a draggedItem is inside visible area of \a diagramContainer
function isItemInsideDiagramContainer(x, y) {
    return ((0 < x)
            && (x < (diagramContainer.width - draggedItem.width))
            && (toolbarHeight < y)
            && (y < (diagramContainer.height - draggedItem.height)))
}

//! Check \a draggedItem is inside \a diagramField
function isItemInsideDiagramField(x, y) {
    return ((-draggedItem.itemRectMargin < x)
            && (x < (diagramContainer.diagramField.width - draggedItem.width + draggedItem.itemRectMargin))
            && (-draggedItem.itemRectMargin < y)
            && (y < (diagramContainer.diagramField.height - draggedItem.height + draggedItem.itemRectMargin)))
}

function startDrag(item, source, mouse)
{
    console.debug('startDrag:')
    console.debug('item:  ' + item.x  + ' ' + item.y)
    console.debug('source:', source)
    console.debug('mouse: ' + mouse.x + ' ' + mouse.y)
    console.debug('parent:' + item.parent + item.parent.objectName)

//    posnInWindow = item.mapToItem(diagramContainer.diagramField, 0, 0);
    posnInWindow = window.mapFromItem(item, mouse.x, mouse.y);
    console.debug('posnInWindow: ' + posnInWindow.x + ' ' + posnInWindow.y)
    startingMouse = { x: mouse.x, y: mouse.y }
    loadComponent(source);
    continueDrag(mouse)
}

function loadComponent(source) {
    if (itemComponent != null) { // component has been previously loaded
        createItem();
        return;
    }

    itemComponent = Qt.createComponent(source);
    console.debug("loadComponent(): status:", itemComponent.status);
    console.debug("loadComponent(): errorString:", itemComponent.errorString);
    createItem();
}

function createItem() {
    draggedItem = itemComponent.createObject(diagramContainer.diagramField)
    draggedItem.parent = window

    console.debug("createItem(): draggedItem = " + draggedItem);
    if (draggedItem === null) {
        console.error("ERROR:", itemComponent.errorString);
        delete itemComponent;
        itemComponent = null;
        return;
    }

    draggedItem.objectName = 'diagramObject_' + diagramContainer.diagramField.draggedItemCount
    draggedItem.pageIndex = diagramContainer.pageIndex;
}

function continueDrag(mouse)
{
    if (draggedItem == null)
        return;

    posnDraggingX = posnInWindow.x + mouse.x - startingMouse.x;
    posnDraggingY = posnInWindow.y + mouse.y - startingMouse.y;

    posnInDiagramContainer = diagramContainer.mapFromItem(window, posnDraggingX, posnDraggingY);
    console.debug('posnInDiagramContainer:', posnInDiagramContainer.x, posnInDiagramContainer.y);

    posnInDiagramField = diagramContainer.diagramField.mapFromItem(window, posnDraggingX, posnDraggingY)
    console.debug('posnInDiagramField:', posnInDiagramField.x, posnInDiagramField.y)
    // if item inside field recalc its coordinates taking acale and alignment into account
    if (isItemInsideDiagramContainer(posnInDiagramContainer.x, posnInDiagramContainer.y)
            && isItemInsideDiagramField(posnInDiagramField.x, posnInDiagramField.y))
    {
        draggedItem.selected = true
        draggedItem.scaleFactor = diagramContainer.diagramField.diagramScaleFactor
        posnInDiagramField = diagramContainer.diagramField.getAlignedPoint(posnInDiagramField)
        posnInWindowCorr = window.mapFromItem(diagramContainer.diagramField,
                                              posnInDiagramField.x, posnInDiagramField.y)
        draggedItem.x = posnInWindowCorr.x
        draggedItem.y = posnInWindowCorr.y
    }
    // ...or stay as is
    else {
        draggedItem.selected = false
        draggedItem.scaleFactor = 1
        draggedItem.x = posnDraggingX
        draggedItem.y = posnDraggingY
    }

    console.debug('draggedItem:', draggedItem.x, draggedItem.y, draggedItem.scale)

}

function endDrag(mouse)
{
    if (draggedItem == null)
        return;


    console.debug('mouse:              ' +mouse.x + ' ' + mouse.y)
    console.debug('draggedItem:        ' +draggedItem.x + ' ' + draggedItem.y)
    console.debug('diagramRect:        ' +diagramContainer.diagramField.x + ' ' + diagramContainer.diagramField.y)
    posnInDiagramContainer = diagramContainer.mapFromItem(window, draggedItem.x, draggedItem.y);
    console.debug('posnInDiagramContainer:', posnInDiagramContainer.x, posnInDiagramContainer.y);
    posnInDiagramField = diagramContainer.diagramField.mapFromItem(window, draggedItem.x, draggedItem.y)
    console.debug('posnInDiagramField:', posnInDiagramField.x, posnInDiagramField.y)

    // Drop only in diagramRect
    if (isItemInsideDiagramContainer(posnInDiagramContainer.x, posnInDiagramContainer.y)
            && isItemInsideDiagramField(posnInDiagramField.x, posnInDiagramField.y))
    {
        // adjust to diagramField
        posnInDiagramField = diagramContainer.diagramField.mapFromItem(window, draggedItem.x, draggedItem.y)
        draggedItem.x = posnInDiagramField.x
        draggedItem.y = posnInDiagramField.y
        draggedItem.scaleFactor = 1
        draggedItem.selected = false

        diagramContainer.diagramField.draggedItemCount += 1;
        diagramContainer.diagramField.itemReleased(draggedItem);
        diagramContainer.diagramField.itemSelected(draggedItem, undefined)
        diagramContainer.forceActiveFocus();
        draggedItem.created = true;
        draggedItem.parent = diagramContainer.diagramField;
        draggedItem = null;
        console.debug('draggedItem remained');

        diagramContainer.diagramField.dumpChildren();
    }
    else
    {
        draggedItem.destroy();
        draggedItem = null;
        console.debug('draggedItem destroyed');
    }
    delete itemComponent;
    itemComponent = null;
    console.debug('-----------------------------');
}

function cancelDrag()
{
    if (draggedItem != null) {
        draggedItem.destroy();
        draggedItem = null;
    }

    delete itemComponent;
    itemComponent = null;

    console.debug('draggedItem canceled');
    console.debug('-----------------------------');
}
