

var dragEvent = null


var theCounter = 0
var counter = function() {
    return theCounter
}
var bump = function() {
    theCounter += 1
}


var DraggableNode = function(n) {
    var _this = this
    this.node = n
    n.onmousedown = function(e) {
        dragEvent = new DragEvent(e, _this)
        document.onmousemove = function(e) {
            if (!dragEvent.startedDragging) {
                if (Math.abs(e.pageX - dragEvent.e.pageX) <= 3 &&                    Math.abs(e.pageY - dragEvent.e.pageY) <= 3) return
               dragEvent.startedDragging = true
               _this.startedDragging(e)            }
            _this.continueDragging(e)
        }
        document.onmouseup = function(e) {
            _this.stoppedDragging(e)
            document.onmousemove = null
            document.onmouseup = null
            dragEvent = null
        }
        e.preventDefault()
    }
    n.onmouseover = function(e) { }
    this.startedDragging = function(e) {
        var ghost = _this.getDragGhost()
        
        var top = document.getElementById('drag-feedback-top')
        top.style.width = ghost.clientWidth+"px"
        top.style.display = "block"
        var bottom = document.getElementById('drag-feedback-bottom')
        bottom.style.width = ghost.clientWidth+"px"
        bottom.style.display = "block"
        var left = document.getElementById('drag-feedback-left')
        left.style.height = ghost.clientHeight+"px"
        left.style.display = "block"
        var right = document.getElementById('drag-feedback-right')
        right.style.height = ghost.clientHeight+"px"
        right.style.display = "block"
    }
    this.continueDragging = function(e) {
        var ghost = _this.getDragGhost()
        var top = document.getElementById('drag-feedback-top')
        var left = document.getElementById('drag-feedback-left')
        top.style.top = (e.pageY+dragEvent.yOffset)+"px"
        left.style.top = (e.pageY+dragEvent.yOffset)+"px"
        top.style.left = (e.pageX+dragEvent.xOffset)+"px"
        left.style.left = (e.pageX+dragEvent.xOffset)+"px"
        var bottom = document.getElementById('drag-feedback-bottom')
        bottom.style.top = (e.pageY+dragEvent.yOffset)+ghost.clientHeight+"px"
        bottom.style.left = (e.pageX+dragEvent.xOffset)+"px"
        var right = document.getElementById('drag-feedback-right')
        right.style.top = (e.pageY+dragEvent.yOffset)+"px"
        right.style.left =  (e.pageX+dragEvent.xOffset)+ghost.clientWidth+"px"
    }
    this.clearFeedback = function(e) {
        document.getElementById('drag-feedback-top').style.display = "none"
        document.getElementById('drag-feedback-left').style.display = "none"
        document.getElementById('drag-feedback-bottom').style.display = "none"
        document.getElementById('drag-feedback-right').style.display = "none"
    }
    this.stoppedDragging = function(e) {
        _this.clearFeedback(e)
        if (dragEvent.hovering) dragEvent.hovering.stoppedDragging(_this)
        else {
            n.parentNode.style.top = (e.pageY+dragEvent.yOffset)+"px"
            n.parentNode.style.left = (e.pageX+dragEvent.xOffset)+"px"
            server.handle('moved', n.parentNode.id, n.parentNode.style.left, n.parentNode.style.top)
        }
    }
    this.getDragGhost = function() { return n.parentNode }
}

var DragEvent = function(e, no) {
    cur = no.node
    left = cur.offsetLeft
    top = cur.offsetTop
    while(cur.offsetParent) {
        cur = cur.offsetParent
        left += cur.offsetLeft
        top += cur.offsetTop
    }
    this.xOffset = left - e.pageX
    this.yOffset = top - e.pageY
    this.e = e
    this.no = no
    this.node = no.node
    this.feedbackNode = no.getDragGhost()
    this.startedDragging = false
    this.hovering = null
}

var DroppableNode = function(no) {
    this_ = this
    no.onmouseover = function() {
        if (!dragEvent) return
        if (this_.canAcceptDrop(dragEvent.node)) {
            this_.startHovering()
        }
    }
    no.onmouseout = function() {
        if (!dragEvent) return
        if (dragEvent.hovering == this_) {
            this_.stopHovering()
        }
    }
    this.canAcceptDrop = function(what) {
        if (what.className == 'cloneable') return false
        if (what == no.previousSibling)
            return false
        return true
    }
    this.startHovering = function() {
        no.style.border="1px solid black"
        dragEvent.hovering = this_
    }
    this.stopHovering = function() {
        dragEvent.hovering = null
        this_.stoppedDragging()
    }
    this.stoppedDragging = function(consumed) {
        no.style.border="none"
        if (consumed) {
            server.handle('consume', no.parentNode.id, consumed.node.parentNode.id)
        }
    }
}

var ResizableNode = function(no) {
    _this = this
    no.onmousedown = function(e) {
        cur = no.parentNode
        left = cur.offsetLeft
        top = cur.offsetTop
        while(cur.offsetParent) {
            cur = cur.offsetParent
            left += cur.offsetLeft
            top += cur.offsetTop
        }
        _this.curleft = left
        _this.curtop = top
        _this.xOffset = left + no.parentNode.clientWidth - e.pageX
        _this.yOffset = top + no.parentNode.clientHeight - e.pageY

        document.onmousemove = function(e) {
            _this.resize(e)
        }
        document.onmouseup = function(e) {
            server.handle('resized', no.parentNode.id, no.parentNode.style.width, no.parentNode.style.height)
            document.onmousemove = null
            document.onmouseup = null
        }
        e.preventDefault()
    }
    this.resize = function(e) {
        no.parentNode.style.width=e.pageX - _this.curleft + _this.xOffset + "px"
        no.parentNode.style.height=e.pageY - _this.curtop + _this.yOffset + "px"
    }
}

var node_setup = {
    droppable: function(n) {
        new DroppableNode(n)
    },

    draggable: function(n) {
      new DraggableNode(n)
    },

    resizable: function(n) {
        new ResizableNode(n)
    },

    cloneable: function(n) {
        _ths = this
        var cl = new DraggableNode(n)
        cl.cloneable = true
        cl.stoppedDragging = function(e) {
            cl.clearFeedback(e)
            cl.onClone(e)
        }
        cl.getDragGhost = function() { return n }
        cl.onClone = function(e) {
            server.handle('clone', e.clientX+'px', e.clientY+'px')
        }
        return cl
    },

    linkable: function(n) {
        var cl = node_setup.cloneable(n)
        cl.onClone = function(e) {
            var pagename = prompt("Link to which page?")
            if (pagename)
                server.handle('link', pagename, e.clientX+'px', e.clientY+'px')
        }
        n.ondoubleclick = function(e) {
            alert('double click')
        }
        return cl
    },

    editable: function(n) {
        n.onclick = function(e) {
            server.handle('edit', n.id, n.innerHTML)
        }
    }
}

var setup = function(node) {  var i, f, names  if (node.className) {    names = node.className.split(" ");    for (i = 0; i < names.length; i++) {      if (names[i]) {
        f = node_setup[names[i]]
        if (f)          f(node)      }    }  }  for (var i in node.childNodes) {    setup(node.childNodes[i])  }}
setup(document)

