﻿function updateClassName(e, n) {
    if (e.className != n) e.className = n
}
function updateInnerHTML(e, t) {
    if (e.rawInnerHTML != t) {
        e.rawInnerHTML = t
        e.innerHTML = t
        return true
    }
    return false
}
function codePre(text) {
    return '<pre>' + text + '</pre>';
}
function box(title, body) {
    return '\
        <table rules="all" cellspacing="0" cellpadding="2" border="1" class="box">\
            <tr><th>' + title + '</th></tr>\
            <tr><td>' + body + '</td></tr>\
        </table>'
}
function getCode() {
    return document.getElementById('ProgramTextBox').value
}
var updateCodeContractsInterval = null
var starthereEnabled = true
function updateCodeContracts() {
    var logo = document.getElementById('logo')
    var programText = getCode()
    var showWithCodeContracts =
                programText.indexOf("System") != -1 &&
                programText.indexOf("Diagnostics") != -1 &&
                programText.indexOf("Contracts") != -1
    var showWithCodeContractsVerification = showWithCodeContracts &&
                programText.indexOf("ContractVerification") != -1
    var hiddenChallenge = document.getElementById("HiddenChallenge").value
    var showChallenge = hiddenChallenge != ""
    if (logo.className != 'hidden' &&
        (showWithCodeContracts != (document.getElementById('WithCodeContracts') != null) ||
        showChallenge != (document.getElementById("Challenge") != null)))
    {
        var pexweb = showChallenge ? "pexwebchallenge.png" : "pexweb2.png";
        var pexwebalt = showChallenge ? "Pex for fun - Coding Duel" : "Pex for fun";
        var id = showChallenge ? 'id="Challenge"' : '';
        if (showWithCodeContracts)
            logo.innerHTML = '<div style="width: 783px; height: 97px;"><img ' + id + ' src="Images/' + pexweb + '" alt="' + pexwebalt + '" width="585" height="97" style="border:none 0px White; padding: 0 99px;"/><a target="_blank" href="Documentation.aspx#CodeContracts"><img id="WithCodeContracts" src="Images/WithCodeContracts.png" alt="with Code Contracts" width="99" height="97" style="border:none 0px White; margin-left: -99px; margin-right: 0px;"/></a></div>';
        else
            logo.innerHTML = '<img ' + id + 'src="Images/' + pexweb + '" alt="' + pexwebalt + '" width="585" height="97" style="border:none 0px White;"/>';
    }
    var askCodeContractsVerifierButton = document.getElementById('AskCodeContractsVerifierButton')
    if (showWithCodeContractsVerification != (askCodeContractsVerifierButton.className != "hidden"))
        updateClassName(askCodeContractsVerifierButton, showWithCodeContractsVerification ? document.getElementById('AskPexButton').className : "hidden")
    if (showWithCodeContractsVerification)
        starthereEnabled = false
    if (updateCodeContractsInterval)
        clearInterval(updateCodeContractsInterval)
    updateCodeContractsInterval = setInterval(updateCodeContracts, 2000)
}
updateCodeContracts()
var askPexHistory = null;
function clearAskPexHistory() {
    document.getElementById('history').innerHTML = ""
    askPexHistory = new Array(0)
}
clearAskPexHistory()
var lastAskPex;
function askPexHistoryEntry(url, text) {
    var now = new Date().getTime();
    var h = askPexHistory
    var lastTime = (h == null || h.length == 0) ? now : h[h.length - 1].time;
    this.url = url;
    this.text = text;
    this.time = now;
    this.seconds = Math.round((now - lastTime) / 1000);
    this.pexSeconds = Math.round((now - lastAskPex) / 1000);
}
function initAskPexHistory(url) {
    var h = askPexHistory
    if (h != null && h.length == 0) {
        h.push(new askPexHistoryEntry(url, null))
        renderAskPexHistory()
    }
}
initAskPexHistory(askPexhistoryUrl)
function addAskPexHistory(url, text) {
    var h = askPexHistory
    if (h != null && h.length > 0) {
        h.push(new askPexHistoryEntry(url, text))
        renderAskPexHistory()
    }
}
var askPexHistoryShowPermalinks = false
function renderAskPexHistory() {
    var HTML =
                "Puzzle history " +
                "(<a href='javascript:askPexHistoryShowPermalinks=" + (!askPexHistoryShowPermalinks) + ";renderAskPexHistory()'>" + (askPexHistoryShowPermalinks ? "hide" : "show") + "</a> Permalinks): ";
    var seconds = 0
    for (var i = 0; i < askPexHistory.length; i++) {
        var e = askPexHistory[i];
        if (i == 0)
            if (askPexHistoryShowPermalinks)
                HTML += "<br/>initial: <a target='_blank' href='" + e.url + "'>" + e.url + "</a><br/>";
            else
                HTML += "<a target='_blank' href='" + e.url + "'>initial</a>;&nbsp;&nbsp; ";
        else {
            if (askPexHistoryShowPermalinks)
                HTML += "+" + e.seconds + "s: " + i + ". Ask Pex: " + e.text + "</a> (" + e.pexSeconds + "s): <a target='_blank' href='" + e.url + "'>" + e.url + "</a><br/>"
            else
                HTML += "+" + e.seconds + "s: <a target='_blank' href='" + e.url + "'>" + i + ". Ask Pex: " + e.text + "</a> (" + e.pexSeconds + "s);&nbsp;&nbsp; "
            seconds += e.seconds
        }
    }
    if (seconds > 0)
        HTML += "total time: " + seconds + "s"
    var historyElement = document.getElementById('history');
    historyElement.innerHTML = HTML;
}
var intellisenseNames = new Array()
var intellisenseKinds = new Array()
var intellisenseDoc = new Object()
var intellisenseSnippet = new Object()
var intellisenseImports = new Object()
var intellisenseHistory = new Array()
var intellisenseMembers = new Object()
var intellisensePrefix
var intellisenseStart = -1
var intellisenseMode
var intellisenseSelection
var intellisenseMemberSelection
var intellisenseLeft = null, intellisenseTop = null
var intellisenseCount = 0
var intellisenseLazyMembersId
function getIntellisenseName() {
    if (intellisenseSelection == undefined) return ""
    var name = intellisenseNames[intellisenseSelection]
    if (!name) return ""
    return name
}
function relocateIntellisense() {
    var programTextBox = document.getElementById('ProgramTextBox')
    var intellisense = document.getElementById("Intellisense")
    var intellisense2 = document.getElementById("Intellisense2")
    var intellisense3 = document.getElementById("Intellisense3")

    var compact = intellisenseMode == 'lookup'
    if (compact)
        updateClassName(intellisense, "hidden")
    if (intellisenseLazyMembersId)
        updateClassName(intellisense2, "hidden")

    var maxLength = 0
    for (var i = 0; i < intellisenseNames.length; i++)
        maxLength = Math.max(maxLength, intellisenseNames[i].length)
    var width = (40 + maxLength * 7)
    intellisense.style.width = width + "px"

    if (intellisenseLeft && intellisenseTop) {
        intellisense.style.height = (parseInt(programTextBox.offsetHeight) - 16) + "px"
        intellisense.style.left = parseInt(intellisenseLeft) + "px"
        intellisense.style.top = parseInt(intellisenseTop) + "px"

        intellisense2.style.height = Math.floor((parseInt(programTextBox.offsetHeight) - 16) * 0.6) + "px"
        if (compact)
            intellisense2.style.left = parseInt(intellisenseLeft) + "px"
        else
            intellisense2.style.left = (parseInt(intellisenseLeft) + width + 5) + "px"
        intellisense2.style.top = parseInt(intellisenseTop) + "px"
    } else {
        intellisense.style.height = Math.floor((parseInt(programTextBox.offsetHeight) - 16) * 0.6) + "px"
        intellisense.style.left = (parseInt(programTextBox.offsetLeft) + parseInt(programTextBox.offsetWidth) - width - 29) + "px"
        intellisense.style.top = (parseInt(programTextBox.offsetTop) + 5) + "px"

        intellisense2.style.height = Math.floor((parseInt(programTextBox.offsetHeight) - 16) * 0.4 - 4) + "px"
        intellisense2.style.left = (parseInt(programTextBox.offsetLeft) + parseInt(programTextBox.offsetWidth) - 306 - 23) + "px"
        intellisense2.style.top = (parseInt(programTextBox.offsetTop) + 5 + Math.floor((parseInt(programTextBox.offsetHeight) - 16) * 0.6) + 5) + "px"
    }

    intellisense3.style.left = (parseInt(intellisense2.style.left) + 8) + "px"
    intellisense3.style.top = (parseInt(intellisense2.style.top) - 17) + "px"

    if (!compact)
        updateClassName(intellisense, "intellisense")
    if (!intellisenseLazyMembersId)
        updateClassName(intellisense2, "intellisense2")
}
function intellisense(action, text) {
    var tutorial = document.getElementById("Community")
    var href = tutorial.getAttribute("href")
    document.getElementById("IntellisenseParam").value = action
    document.getElementById("IntellisenseText").value = text
    eval(href.substr(11))
}
function vote(w, t) {
    intellisense("vote:" + w, t);
}
function updateIntellisenseSelection() {
    var selectedMembers
    for (var i = 0; i < intellisenseNames.length; i++) {
        var element = document.getElementById("intellisense" + i)
        if (!element) continue;
        if (i == intellisenseSelection) {
            updateClassName(element, "intellisensesel")
            var container = document.getElementById("Intellisense")
            var scrollTop = element.offsetTop - Math.floor(parseInt(container.style.height) / 2)
            if (scrollTop < 0) scrollTop = 0
            if (container.scrollTop != scrollTop) container.scrollTop = scrollTop
            var name = intellisenseNames[i]
            selectedMembers = intellisenseMembers[name]
        }
        else
            updateClassName(element, "intellisense")
    }
    var intellisense2 = document.getElementById("Intellisense2")
    var selectedMember = selectedMembers ? selectedMembers[intellisenseMemberSelection] : undefined
    var doc = ""
    if (selectedMember) {
        doc = selectedMember.text
        var id = selectedMember.id
        if (id) {
            var d = intellisenseDoc[id]
            if (d || d == "") {
                if (d != "") doc += "<hr/>" + d
            }
            else
                intellisense("intellisense2:" + id, "")
        }
    } else
        doc = ""
    updateInnerHTML(intellisense2, doc)
    var intellisense3 = document.getElementById("Intellisense3")
    if (!intellisenseLazyMembersId && selectedMembers && selectedMembers.length > 1) {
        updateClassName(intellisense3, "intellisense3")
        var left = "&lt;&lt;"
        var right = "&gt;&gt;"
        if (intellisenseMemberSelection > 0)
            left = "<a href='javascript:setIntellisenseMemberSelection(" + (intellisenseMemberSelection - 1) + ")'>" + left + "</a>"
        if (intellisenseMemberSelection + 1 < selectedMembers.length)
            right = "<a href='javascript:setIntellisenseMemberSelection(" + (intellisenseMemberSelection + 1) + ")'>" + right + "</a>"
        updateInnerHTML(intellisense3, left + "&nbsp;" + (intellisenseMemberSelection + 1) + "&nbsp;/&nbsp;" + selectedMembers.length + "&nbsp;" + right)
    }
    else
        updateClassName(intellisense3, "hidden")
    var programTextBox = document.getElementById('ProgramTextBox')
    programTextBox.focus()
}
function intellisenseLazyMembers() {
    intellisense("intellisense3:" + intellisenseLazyMembersId, "")
}
function setDoc(id, text) {
    intellisenseDoc[id] = text;
    var intellisense = document.getElementById("Intellisense")
    var intellisense2 = document.getElementById("Intellisense2")
    if (intellisense.className == 'intellisense' || intellisense2.className == 'intellisense2')
        updateIntellisenseSelection()
}
function setIntellisenseMemberSelection(i) {
    intellisenseMemberSelection = i
    updateIntellisenseSelection()
}
function moveIntellisenseSelection(direction) {
    if (intellisenseCount > 0) {
        var newIntellisenseSelection = intellisenseSelection
        var steps = 0
        while (steps < intellisenseNames.length) {
            steps++;
            newIntellisenseSelection += direction
            if (newIntellisenseSelection < 0) {
                newIntellisenseSelection = -1
                direction = +1
                continue;
            }
            if (newIntellisenseSelection >= intellisenseNames.length) {
                newIntellisenseSelection = intellisenseNames.length
                direction = -1
                continue;
            }
            var element = document.getElementById("intellisense" + newIntellisenseSelection)
            if (element) {
                intellisenseSelection = newIntellisenseSelection
                intellisenseMemberSelection = 0
                updateIntellisenseSelection()
                return
            }
        }
    }
}
var intellisenseKindNames = ["Namespace", "Class", "Delegate", "Enum", "Interface", "Structure", "Constant", "Field", "Field", "Field", "Event", "Properties", "Method", "Snippet", "Keyword", "Constructor"]
function updateIntellisense() {
    var intellisense = document.getElementById("Intellisense")
    var intellisense2 = document.getElementById("Intellisense2")
    var intellisense3 = document.getElementById("Intellisense3")
    if (intellisenseNames.length == 0) {
        updateClassName(intellisense, "hidden")
        updateClassName(intellisense2, "hidden")
        updateClassName(intellisense3, "hidden")
    } else {
        var text = ""
        var intellisensePrefixLength = intellisensePrefix ? intellisensePrefix.length : 0
        intellisenseCount = 0
        var intellisensePrefixLowerCase = intellisensePrefix ? intellisensePrefix.toLowerCase() : ""
        var reverseIntellisenseNames = new Object()
        var firstIndex
        intellisenseSelection = undefined
        for (var i = 0; i < intellisenseNames.length; i++) {
            var name = intellisenseNames[i]
            var namePrefix = name.substr(0, intellisensePrefixLength)
            if (namePrefix.toLowerCase() == intellisensePrefixLowerCase) {
                if (firstIndex == undefined) firstIndex = i
                reverseIntellisenseNames[name] = i
                text += "<p class='intellisense' id='intellisense" + i + "'>"
                var kindName = intellisenseKindNames[intellisenseKinds[name]]
                text += "<img style='background-color:white;vertical-align:bottom;padding-right:3px;' src='Images/VSObject_" + kindName + ".png' alt='" + kindName + "' width='16' height='16'/>"
                text += "<b style='padding-left:2px;'>" + namePrefix + "</b>"
                var nameSuffix = name.substr(intellisensePrefixLength)
                if (nameSuffix == "") intellisenseSelection = i
                if (intellisenseMode != 'lookup') {
                    var code = 'javascript:intellisenseComplete(' + i + ')'
                    text += "<a href='" + code + "'>" + nameSuffix + "</a>"
                } else
                    text += nameSuffix;
                var members = intellisenseMembers[name]
                if (members.length > 1)
                    text += "&nbsp;(" + members.length + ")"
                text += "</p>"
                intellisenseCount++
            }
        }
        for (var i = intellisenseHistory.length - 1; intellisenseSelection == undefined && i >= 0; i--)
            intellisenseSelection = reverseIntellisenseNames[intellisenseHistory[i]]
        if (intellisenseSelection == undefined) intellisenseSelection = firstIndex
        if (updateInnerHTML(intellisense, text)) intellisense.scrollTop = "0px";
        relocateIntellisense()
        intellisenseMemberSelection = 0 
        updateIntellisenseSelection()
    }
}
function clearIntellisense() {
    intellisenseStart = -1
    intellisenseNames = new Array()
    intellisenseKinds = new Object()
    intellisenseMembers = new Object()
    intellisenseSelection = null
    intellisenseCount = 0
    intellisenseLazyMembersId = null
    updateIntellisense()
}
function clearResults(isChallenge, history) {
    var table = document.getElementById("ResultTable");
    if (table != null)
        while (table.firstChild)
            table.removeChild(table.firstChild);
    updateInnerHTML(document.getElementById('details'), "")
    updateClassName(document.getElementById('challenge0'), "hidden")
    updateClassName(document.getElementById('challenge2'), "hidden")
    updateClassName(document.getElementById('facebookAdvertisement'), "hidden")
    updateClassName(document.getElementById('advertisement'), "hidden")
    stopSpinning()
    if (updateCodeContractsInterval)
        clearInterval(updateCodeContractsInterval)
    updateCodeContractsInterval = setInterval(updateCodeContracts, 100)
    if (history)
        clearAskPexHistory()
    updateClassName(document.getElementById("starthere3"), "hidden")
    updateClassName(document.getElementById("starthere2"), "hidden")
    starthereEnabled = false
    clearIntellisense()
}
function addIntellisenseNames(elements) {
    for (var i = 0; i < elements.length; i++) {
        var e = elements[i]
        var kind = e[0]
        var name = e[1]
        var count = e[2]
        intellisenseNames.push(name)
        intellisenseKinds[name] = kind
        intellisenseMembers[name] = new Array(count)
    }
}
function intellisenseMember(text, id) {
    this.text = text; this.id = id;
}
function addIntellisenseMembers(name, members) {
    var a = intellisenseMembers[name]
    if (!a) return;
    for (var i = 0; i < members.length; i++) {
        var m = members[i]
        var text = m[0]
        var id = m[1]
        a[i] = new intellisenseMember(text, id)
    }
}
function clearPermalink() {
    var challenge3 = document.getElementById('challenge0')
    updateClassName(challenge3, 'hidden')
}
function r4fGetGraphUrl(source) { }
function setDetails(code, exception, stackTrace, output) {
    var s = ""
    if (output != "") {
        var title = "Output";
        var grul = r4fGetGraphUrl(output);
        if (grul != null) {
            title += " - <a href='" + grul + "' target='graphs'>Visualize Graph</a>";
        }
        s += box(title, codePre(output))
    }
    if (code)
        s += box("Code", codePre(code))
    if (exception != "" || stackTrace != "")
        s += box(exception, codePre(stackTrace))
    updateInnerHTML(document.getElementById('details'), s)
}
function getSpinner() { return document.getElementById('spinner'); }
var spinningSteps = ['/', '-', '\\', '|']
var spinningInterval = null;
var spinningCurrent;
function startSpinning() {
    if (spinningInterval == null) {
        spinningCurrent = spinningSteps[0]
        function spinningFunction() {
            var i, spinner = getSpinner()
            for (i = 0; i < spinningSteps.length; i++)
                if (spinningCurrent == spinningSteps[i]) {
                    spinningCurrent = spinningSteps[(i + 1) % spinningSteps.length]
                    break;
                }
            spinner.innerHTML = spinningCurrent
        }
        spinningInterval = setInterval(spinningFunction, 333)
    }
    getSpinner().innerHTML = spinningCurrent
}
function stopSpinning() {
    if (spinningInterval == null) return;
    clearInterval(spinningInterval)
    getSpinner().innerHTML = '&nbsp;'
    spinningInterval = null;
}
function startAsk(codeContractsVerifier) {
    var askPexButton = document.getElementById('AskPexButton')
    var askCodeContractsVerifierButton = document.getElementById('AskCodeContractsVerifierButton')
    if (askPexButton.className != 'bigbutton waiting' && askCodeContractsVerifierButton.className != 'bigbutton waiting') {
        updateClassName(askPexButton, 'bigbutton waiting')
        updateClassName(askCodeContractsVerifierButton, askCodeContractsVerifierButton.className == 'hidden' ? 'hidden' : 'bigbutton waiting')
        clearResults(false, false);
        startSpinning();
        updateInnerHTML(document.getElementById('ResultLabel'), document.getElementById('AskPexButton').value == 'Run!' ? '<i>Running</i>' : codeContractsVerifier ? '<i>Asking Code Contracts Verifier</i>' : '<i>Asking Pex</i>')
    }
    lastAskPex = new Date().getTime();
}
var userFrameState
function clickMyStudents() {
    if (userFrameState == "MyStudents")
        hideFrames()
    else {
        var userFrame = document.getElementById('UserFrame')
        userFrame.className = 'userFrame'
        userFrame.innerHTML =
            '<iframe width="100%" height="100%" scrolling="auto" frameborder="0" src="UserMyStudents.aspx"></iframe>'
        userFrameState = "MyStudents"
        updateUserMenu()
    }
}
function clickMyCourses() {
    if (userFrameState == "MyCourses")
        hideFrames()
    else {
        var userFrame = document.getElementById('UserFrame')
        userFrame.className = 'userFrame'
        userFrame.innerHTML =
            '<iframe width="100%" height="100%" scrolling="auto" frameborder="0" src="UserMyCourses.aspx"></iframe>'
        userFrameState = "MyCourses"
        updateUserMenu()
    }
}
function clickMyPages() {
    if (userFrameState == "MyPages")
        hideFrames()
    else {
        var userFrame = document.getElementById('UserFrame')
        userFrame.className = 'userFrame'
        userFrame.innerHTML =
            '<iframe width="100%" height="100%" scrolling="auto" frameborder="0" src="UserMyPages.aspx"></iframe>'
        userFrameState = "MyPages"
        updateUserMenu()
    }
}
function clickMyDuels() {
    if (userFrameState == "MyDuels")
        hideFrames()
    else {
        var userFrame = document.getElementById('UserFrame')
        userFrame.className = 'userFrame'
        userFrame.innerHTML =
            '<iframe width="100%" height="100%" scrolling="auto" frameborder="0" src="UserMyDuels.aspx"></iframe>'
        userFrameState = "MyDuels"
        updateUserMenu()
    }
}
function clickSettings() {
    if (userFrameState == "Settings")
        hideFrames()
    else {
        var userFrame = document.getElementById('UserFrame')
        userFrame.className = 'userFrame'
        userFrame.innerHTML =
            '<iframe width="100%" height="100%" scrolling="auto" frameborder="0" src="UserSettings.aspx"></iframe>'
        userFrameState = "Settings"
        updateUserMenu()
    }
}
function hideFrames() {
    if (userFrameState) {
        var userFrame = document.getElementById('UserFrame')
        userFrame.className = 'hidden'
        userFrameState = null
        updateUserMenu()
    }
}
function refresh(action) {
    var permalink = document.getElementById("Permalink")
    var href = permalink.getAttribute("href")
    var permalinkParam = document.getElementById("PermalinkParam")
    permalinkParam.value = action
    eval(href.substr(11))
}
function learn() {
    var permalink = document.getElementById("LearnButton")
    var href = permalink.getAttribute("href")
    eval(href.substr(11))
}
if (starthereEnabled && (parent == window || parent == document)) {
    var timeLeft3 = 1000
    function starthere3FadeIn(lastTick) {
        var curTick = new Date().getTime()
        var elapsedTicks = curTick - lastTick

        var starthere3 = document.getElementById("starthere3")
        if (timeLeft3 <= elapsedTicks) {
            starthere3.style.opacity = "1"
            starthere3.style.filter = "alpha(opacity = 100)"
        } else {
            timeLeft3 -= elapsedTicks
            var newOpacity = 1 - timeLeft3 / 1000
            starthere3.style.opacity = newOpacity
            starthere3.style.filter = "alpha(opacity = " + (newOpacity * 100) + ")"
            setTimeout("starthere3FadeIn(" + curTick + ")", 20)
        }
    }
    var timeLeft2 = 1000
    function starthere2FadeIn(lastTick) {
        var curTick = new Date().getTime()
        var elapsedTicks = curTick - lastTick

        var starthere2 = document.getElementById("starthere2")
        if (timeLeft2 <= elapsedTicks) {
            starthere2.style.opacity = "1"
            starthere2.style.filter = "alpha(opacity = 100)"
        } else {
            timeLeft2 -= elapsedTicks
            var newOpacity = 1 - timeLeft2 / 1000
            starthere2.style.opacity = newOpacity
            starthere2.style.filter = "alpha(opacity = " + (newOpacity * 100) + ")"
            setTimeout("starthere2FadeIn(" + curTick + ")", 20)
        }
    }

    function showStarthere3(init) {
        var starthere3 = document.getElementById("starthere3")
        if (!init && starthere3.className != "starthere3") return;
        updateClassName(starthere3, "starthere3")
    }
    function showStarthere2(init) {
        var starthere2 = document.getElementById("starthere2")
        if (!init && starthere2.className != "starthere2") return;
        var askPexButton = document.getElementById("AskPexButton")
        starthere2.style.top = (parseInt(askPexButton.offsetTop) + 40) + "px"
        starthere2.style.left = (parseInt(askPexButton.offsetLeft) + 35) + "px"
        updateClassName(starthere2, "starthere2")
    }

    function initStarthere() {
        window.onmousemove = null
        if (!starthereEnabled) return;

        showStarthere2(true)
        starthere2FadeIn(new Date().getTime())

        setTimeout("if (document.getElementById('logo').className != 'hidden' && document.getElementById('starthere2').className == 'starthere2') { showStarthere3(true); starthere3FadeIn(new Date().getTime()) }", 8000)

        starthereEnabled = false
    }
    function resize() {
        showStarthere3(false)
        showStarthere2(false)
    }
    window.onresize = resize
    window.onmousemoveover = initStarthere
}
function isIdentifier(s) {
    return /^[\d\w]*$/.test(s)
}
function isNotCompletion(c) {
    if (c == undefined) return false;
    return '\r\n <>[]()=,/+!*%^&|;{}-~?:'.indexOf(c) >= 0;
}
function getCodePosition() { // if position  is at first character of line, this might return end of previous line
    var programTextBox = document.getElementById('ProgramTextBox')
    var start, end
    if (document.selection) {
        programTextBox.focus()
        var range = document.selection.createRange()
        var rangedup = range.duplicate()
        rangedup.moveToElementText(programTextBox)
        rangedup.setEndPoint('EndToEnd', range)
        end = rangedup.text.length
        start = end - range.text.length
    } else if (programTextBox.selectionStart || (programTextBox.selectionStart == "0")) {
        start = programTextBox.selectionStart
        end = programTextBox.selectionEnd
    }
    else
        return -1;
    if (start != end)
        return -1
    return start
}
function getPreviousChar() {
    var i = getCodePosition()
    if (i > 0) {
        var code = getCode()
        if (i <= code.length)
            return code.charAt(i - 1)
    }
    return undefined
}
function key(c) {
    if (intellisenseMode != 'lookup' && intellisenseStart >= 0) {
        var intellisenseEnd = getCodePosition()
        if (intellisenseEnd > intellisenseStart) {
            var programTextBox = document.getElementById('ProgramTextBox')
            var text = programTextBox.value
            var offset = intellisenseMode == 'dotcompletion' ? 1 : 0
            intellisensePrefix = text.substr(intellisenseStart + offset, intellisenseEnd - intellisenseStart - offset) + c
            if (isIdentifier(intellisensePrefix)) {
                updateIntellisense()
                return true
            }
        }
    }
    return false
}
function moveCode(count) {
    var programTextBox = document.getElementById('ProgramTextBox')
    programTextBox.focus()
    if (document.selection) {
        var range = document.selection.createRange()
        range.moveStart('character', count)
        range.moveEnd('character', count)
        range.select()
    } else if (programTextBox.selectionStart || programTextBox.selectionStart == "0") {
        var start = programTextBox.selectionStart
        var end = programTextBox.selectionEnd
        if (start > count)
            programTextBox.setSelectionRange(start + count, end + count)
    }
}
function deleteCode(count) {
    var programTextBox = document.getElementById('ProgramTextBox')
    programTextBox.focus()
    if (document.selection) {
        var range = document.selection.createRange()
        range.moveStart('character', -count)
        range.text = ""
        range.select()
    } else if (programTextBox.selectionStart || programTextBox.selectionStart == "0") {
        var start = programTextBox.selectionStart
        var end = programTextBox.selectionEnd
        if (start > count) {
            programTextBox.value = programTextBox.value.substring(0, start - count) + programTextBox.value.substring(end, programTextBox.value.length)
            programTextBox.setSelectionRange(start - count, start - count)
        }
    }
}
function insertCode(text) {
    var programTextBox = document.getElementById('ProgramTextBox')
    programTextBox.focus()
    if (document.selection) {
        var range = document.selection.createRange()
        range.text = text
        range.select()
    } else if (programTextBox.selectionStart || programTextBox.selectionStart == "0") {
        var start = programTextBox.selectionStart
        var end = programTextBox.selectionEnd
        programTextBox.value = programTextBox.value.substring(0, start) + text + programTextBox.value.substring(end, programTextBox.value.length)
        programTextBox.setSelectionRange(start + text.length, start + text.length)
    }
    key("")
    return text.length
}
function insertCodeAtBeginning(text) {
    var programTextBox = document.getElementById('ProgramTextBox')
    if (document.selection) {
        var range = document.selection.createRange()
        var rangedup = range.duplicate()
        rangedup.moveToElementText(programTextBox)
        rangedup.collapse(true)
        rangedup.moveEnd('character', 0)
        rangedup.moveStart('character', 0)
        rangedup.text = text
    } else if (programTextBox.selectionStart || programTextBox.selectionStart == "0") {
        var start = programTextBox.selectionStart
        var end = programTextBox.selectionEnd
        programTextBox.value = text + programTextBox.value
        programTextBox.setSelectionRange(start + text.length, start + text.length)
    }
    return text.length
}
function indentCode(ignoreCurly) {
    var position = getCodePosition()
    if (position == 0) return;
    var prefix = getCode().substr(0, position)
    var end = prefix.length
    while (end > 0 && prefix.charCodeAt(end - 1) <= 32) end--;
    var indent = (!ignoreCurly && end > 0 && prefix.charAt(end - 1) == "{") ? 2 : 0
    var lastNonWhitespace = end + 1
    while (end > 0 && prefix.charAt(end - 1) != "\n" && prefix.charAt(end - 1) != "\r") {
        if (prefix.charCodeAt(end - 1) > 32) lastNonWhitespace = end
        end--
    }
    indent += lastNonWhitespace - end - 1
    var s = ""
    for (var i = 0; i < indent; i++) s += " "
    insertCode(s)
    return indent
}
function unindentCode() {
    var position = getCodePosition()
    if (position < 2) return;
    if (getCode().substr(position - 2, 2) == "  ")
        deleteCode(2)
}
function intellisenseComplete(index, allowSnippet) {
    var name = intellisenseNames[index]
    var snippetLines = name ? intellisenseSnippet[name] : undefined
    if (snippetLines && !allowSnippet) return
    if (intellisensePrefix && intellisensePrefix.length)
        deleteCode(intellisensePrefix.length)
    if (snippetLines) {
        clearIntellisense()
        var backward
        for (var i = 0; i < snippetLines.length; i++) {
            if (i > 0) { backward -= insertCode('\n'); backward -= indentCode(true); }
            var line = snippetLines[i]
            var j = line.indexOf("$end$")
            if (j != -1) line = line.substr(0, j) + line.substr(j + 5);
            backward -= insertCode(line)
            if (j != -1) backward = j - line.length
        }
        var importLines = intellisenseImports[name]
        if (importLines)
            for (var i = 0; i < importLines.length; i++) {
                var line = importLines[i];
                if (getCode().indexOf(line) == -1)
                    insertCodeAtBeginning(line + '\n')
            }
        if (backward)
            moveCode(backward)
    } else {
        insertCode(name)
        intellisenseHistory.push(name)
    }
}
function getHorizontalZoomFactor() {
    if (screen && screen.deviceXDPI) return screen.deviceXDPI / 96
    return 1
}
function getVerticalZoomFactor() {
    if (screen && screen.deviceXDPI) return screen.deviceYDPI / 96
    return 1
}
function keypress(e) {
    var charCode
    if (window.event)
        charCode = e.keyCode;
    else if (e.which)
        charCode = e.which;
    var c = String.fromCharCode(charCode)
    if (intellisenseMode != 'lookup' && intellisenseSelection != null) {
        if (charCode == 13) {
            intellisenseComplete(intellisenseSelection)
            return false;
        } else if (isNotCompletion(c) || c == '.') {
            intellisenseComplete(intellisenseSelection)
        }
    }
    if (c == '}')
        unindentCode()
    else if ('.(,'.indexOf(c) >= 0 || (intellisenseSelection == null || intellisenseMode != 'dotcompletion') && isIdentifier(c) && isNotCompletion(getPreviousChar())) {
        clearIntellisense()
        intellisenseStart = getCodePosition()
        if (intellisenseStart >= 0) {
            if (document.selection) {
                var programTextBox = document.getElementById('ProgramTextBox')
                programTextBox.focus()
                var range = document.selection.createRange()
                var html = document.body.parentNode
                intellisenseLeft = html.scrollLeft + Math.floor(range.offsetLeft / getHorizontalZoomFactor()) + 9
                intellisenseTop = html.scrollTop + Math.floor((range.offsetTop + range.boundingHeight) / getVerticalZoomFactor())
            }
            intellisenseMode = c == '.' ? 'dotcompletion' : isIdentifier(c) ? 'completion' : 'lookup'
            intellisensePrefix = intellisenseMode == 'completion' ? c : ""
            intellisense("intellisense:" + intellisenseStart + "|" + c, getCode())
            return true
        }
    }
    else if (isIdentifier(c) && key(c))
        return true;
    if (charCode && charCode != 8)
        clearIntellisense()
    return true
}
function keyup(e) {
    var charCode
    if (window.event)
        charCode = e.keyCode;
    else if (e.which)
        charCode = e.which;
    var c = String.fromCharCode(charCode)
    if (charCode == 13) {
        if (intellisenseSelection == null) indentCode()
    }
    else if (charCode == 8) {
        if (!key(""))
            clearIntellisense()
    }
    else if (charCode == 35 || charCode == 36 || charCode == 37 || charCode == 39)
        clearIntellisense()
}
function keydown(e) {
    var charCode
    if (window.event)
        charCode = e.keyCode;
    else if (e.which)
        charCode = e.which;
    if (charCode == 9) {
        if (intellisenseMode != 'lookup' && intellisenseSelection != null)
            intellisenseComplete(intellisenseSelection, true)
        else
            insertCode("  ")
        return false;
    }
    if (charCode == 27) {
        clearIntellisense()
        return false
    }
    if (intellisenseSelection != null)
        switch (charCode) {
        case 33: moveIntellisenseSelection(-10); return false
        case 34: moveIntellisenseSelection(+10); return false
        case 38: moveIntellisenseSelection(-1); return false
        case 40: moveIntellisenseSelection(+1); return false
    }
    return true;
}
var startDragY
function startDrag() {
    var divider = document.getElementById("divider")
    var programTextBox = document.getElementById('ProgramTextBox')
    var rows = parseInt(programTextBox.getAttribute('rows'))
    var lineHeight = programTextBox.offsetHeight / rows
    var previousOnmouseover = divider.onmouseover
    var previousOnmouseout = divider.onmouseout
    divider.onmouseover = null
    divider.onmouseout = null
    document.body.onmousemove = function (e) {
        if (!e) e = window.event
        var delta = Math.floor((e.clientY - startDragY) / lineHeight)
        var newRows = rows + delta
        if (newRows > 1 && newRows != parseInt(programTextBox.getAttribute('rows'))) {
            programTextBox.setAttribute('rows', newRows)
            if (resize) resize()
            programTextBox.focus()
        }
    }
    document.body.onmouseup = function () {
        document.body.onmousemove = null
        document.body.onmouseup = null
        divider.onmouseover = previousOnmouseover
        divider.onmouseout = previousOnmouseout
    }
}
function initProgramTextBox() {
    var programTextBox = document.getElementById('ProgramTextBox')
    programTextBox.setAttribute("onkeypress", "return keypress(event)")
    programTextBox.setAttribute("onkeydown", "return keydown(event)")
    programTextBox.setAttribute("onkeyup", "keyup(event)")
    programTextBox.setAttribute("onclick", "if (getCodePosition() != intellisenseStart + 1) clearIntellisense()")
    var intellisense = document.getElementById("Intellisense")
    var intellisense2 = document.getElementById("Intellisense2")
    var intellisense3 = document.getElementById("Intellisense3")
    intellisense.setAttribute("onfocus", "document.getElementById('ProgramTextBox').focus()")
    intellisense2.setAttribute("onfocus", "document.getElementById('ProgramTextBox').focus()")
    intellisense3.setAttribute("onfocus", "document.getElementById('ProgramTextBox').focus()")

    var divider = document.getElementById("divider")
    divider.onmouseover = function (e) {
        if (!e) e = window.event
        startDragY = e.clientY
        document.body.style.cursor = 's-resize'
        divider.onmousedown = startDrag
    }
    divider.onmouseout = function () {
        document.body.style.cursor = 'default'
        divider.onmousedown = null
    }
}
initProgramTextBox()


