# Copyright (C) 2006 James Tauber and contributors
# Copyright (C) 2009, 2010, 2012 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
# Copyright (C) 2011 Rasiel@fliper.cc

def init():
    JS("""
    // Set up event dispatchers.
    $wnd.__dispatchEvent = function() {
        if ($wnd.event.returnValue == null) {
            $wnd.event.returnValue = true;
            if (!@{{previewEvent}}($wnd.event))
                return;
        }

        var listener, curElem = this;
        while (curElem && !(listener = curElem.__listener))
            curElem = curElem.parentElement;
    
        if (listener)
            @{{dispatchEvent}}($wnd.event, curElem, listener);
    };

    $wnd.__dispatchDblClickEvent = function() {
        var newEvent = $doc.createEventObject();
        this.fireEvent('onclick', newEvent);
        if (this.__eventBits & 2)
            $wnd.__dispatchEvent.call(this);
    };

    $doc.body.onclick       =
    $doc.body.onmousedown   =
    $doc.body.onmouseup     =
    $doc.body.onmousemove   =
    $doc.body.onkeydown     =
    $doc.body.onkeypress    =
    $doc.body.onkeyup       =
    $doc.body.onfocus       =
    $doc.body.onblur        =
    $doc.body.onselectstart =
    $doc.body.ondblclick    = $wnd.__dispatchEvent;
    """)

def compare(elem1, elem2):
    JS("""
    if (!@{{elem1}} && !@{{elem2}})
        return true;
    else if (!@{{elem1}} || !@{{elem2}})
        return false;
    return (@{{elem1}}.uniqueID == @{{elem2}}.uniqueID);
    """)

def createInputRadio(group):
    JS("""
    ua = navigator.userAgent.toLowerCase();
    if (ua.indexOf('msie 9.0') != -1) {
        var elem = $doc.createElement("INPUT");
        elem.type = 'radio';
        elem.name = @{{group}};
        return elem
    }

    return $doc.createElement("<INPUT type='RADIO' name='" + @{{group}} + "'>");
    """)

def eventGetType(event):
    etype = event.type
    if etype == 'propertychange':
        return 'input'
    return etype

def eventGetCurrentTarget(event):
    return event.currentEventTarget

def eventGetTarget(evt):
    JS("""
    var elem = @{{evt}}.srcElement;
    return elem ? elem : null;
    """)

def eventGetToElement(evt):
    JS("""
    return @{{evt}}.toElement ? @{{evt}}.toElement : null;
    """)

def eventPreventDefault(evt):
    JS("""
    @{{evt}}.returnValue = false;
    """)

def eventToString(evt):
    JS("""
    if (@{{evt}}.toString) return @{{evt}}.toString();
    return "[object Event]";
    """)

def getBodyOffsetTop():
    JS("""
    return $doc.body.parentElement.clientTop;
    """)

def getBodyOffsetLeft():
    JS("""
    return $doc.body.parentElement.clientLeft;
    """)

def getAbsoluteLeft(elem):
    JS("""
    // getBoundingClientRect() throws a JS exception if the elem is not attached
    // to the document, so we wrap it in a try/catch block
    var zoomMultiple = $doc.body.parentElement.offsetWidth / 
                       $doc.body.offsetWidth;
    try {
        return Math.floor((@{{elem}}.getBoundingClientRect().left / zoomMultiple) +
                            $doc.body.parentElement.scrollLeft );
    } catch (e) {
        return 0;
    }
    """)

def getAbsoluteTop(elem):
    JS("""
    // getBoundingClientRect() throws a JS exception if the elem is not attached
    // to the document, so we wrap it in a try/catch block
    var zoomMultiple = $doc.body.parentElement.offsetWidth / 
                       $doc.body.offsetWidth;
    try {
        var scrollTop = $doc.parent ? $doc.parent.body.scrollTop : 0;
        scrollTop += $doc.body.scrollTop;
        return Math.floor((@{{elem}}.getBoundingClientRect().top / zoomMultiple) +
                            scrollTop);
    } catch (e) {
        return 0;
    }
    """)


def getChild(elem, index):
    JS("""
    var child = @{{elem}}.children[@{{index}}];
    return child ? child : null;
    """)

def getChildCount(elem):
    JS("""
    return @{{elem}}.children.length;
    """)

def getChildIndex(parent, child):
    JS("""
    var count = @{{parent}}.children.length;
    for (var i = 0; i < count; ++i) {
        if (@{{child}}.uniqueID == @{{parent}}.children[i].uniqueID)
            return i;
    }
    return -1;
    """)

def getFirstChild(elem):
    JS("""
    var child = @{{elem}}.firstChild;
    return child ? child : null;
    """)

def getInnerText(elem):
    JS("""
    var ret = @{{elem}}.innerText;
    return (ret == null) ? null : ret;
    """)

def getNextSibling(elem):
    JS("""
    var sib = @{{elem}}.nextSibling;
    return sib ? sib : null;
    """)

def getParent(elem):
    JS("""
    var parent = @{{elem}}.parentElement;
    return parent ? parent : null;
    """)

def insertChild(parent, child, index):
    JS("""
    if (@{{index}} == @{{parent}}.children.length)
        @{{parent}}.appendChild(@{{child}});
    else
        @{{parent}}.insertBefore(@{{child}}, @{{parent}}.children[@{{index}}]);
    """)

def insertListItem(select, text, value, index):
    JS("""
    var newOption = document.createElement("Option");
    if(@{{index}}==-1) {
        @{{select}}.add(newOption);
    } else {
        @{{select}}.add(newOption,@{{index}});
    }
    newOption.text=@{{text}};
    newOption.value=@{{value}};
    """)

def isOrHasChild(parent, _child):
    JS("""
    var child = @{{_child}};
    while (child) {
        if (@{{parent}}.uniqueID == child.uniqueID)
            return true;
        child = child.parentElement;
    }
    return false;
    """)

def releaseCapture_impl(elem):
    JS("""
    @{{elem}}.releaseCapture();
    """)

def setCapture_impl(elem):
    JS("""
    @{{elem}}.setCapture();
    """)

def setInnerText(elem, text):
    JS("""
    if (!@{{text}})
        @{{elem}}.innerText = '';
    else
        @{{elem}}.innerText = @{{text}};
    """)

def toString(elem):
    JS("""
    return @{{elem}}.outerHTML;
    """)

def eventStopPropagation(evt):
    eventCancelBubble(evt,True)

def eventGetMouseWheelVelocityY(evt):
    JS("""
    return Math.round(-@{{evt}}.wheelDelta / 40) || 0;
    """)
