/*
 * Application Insights JavaScript SDK - Debug Plugin, 3.4.0-nightlybeta3.2504-20
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */


import { arrForEach, arrIndexOf, getIEVersion, isArray, isError, isFunction, isObject, isString, isSymbol, objKeys } from "@microsoft/applicationinsights-core-js";
import { strShimPrototype } from "@microsoft/applicationinsights-shims";
import { objHasOwnProperty } from "@nevware21/ts-utils";
import { _DYN_APPEND_CHILD, _DYN_CLASS_NAME, _DYN_CREATE_ELEMENT, _DYN_FOCUS, _DYN_IDENTIFIER, _DYN_INNER_TEXT, _DYN_LENGTH, _DYN_NAME, _DYN_ONCLICK, _DYN_ONTOUCHEND, _DYN_PARENT_ELEMENT, _DYN_PREVENT_DEFAULT, _DYN_PUSH, _DYN_REMOVE_CHILD, _DYN_REPLACE, _DYN_SET_ATTRIBUTE, _DYN_STOP_PROPAGATION, _DYN_SUBSTRING, _DYN_TO_STRING } from "../__DynamicConstants";
var strConstructor = "constructor";
var strGetOwnPropertyNames = "getOwnPropertyNames";
export var MAX_DEPTH = 16;
export function makeRegex(value) {
    if (value && value[_DYN_LENGTH /* @min:%2elength */] > 0) {
        // Escape any slashes first!
        value = value[_DYN_REPLACE /* @min:%2ereplace */](/\\/g, "\\\\");
        // eslint-disable-next-line security/detect-non-literal-regexp
        value = value[_DYN_REPLACE /* @min:%2ereplace */](/([\+\?\|\{\}\[\]\(\)\^\$\#\.\=\!\:\/])/g, "\\$1");
        value = value.replace(/\*/g, ".*");
        return new RegExp("(" + value + ")");
    }
    return null;
}
export function toggleClassName(el, className) {
    var idx = el[_DYN_CLASS_NAME /* @min:%2eclassName */].indexOf(className);
    if (idx === -1) {
        el[_DYN_CLASS_NAME /* @min:%2eclassName */] += className;
    }
    else {
        el[_DYN_CLASS_NAME /* @min:%2eclassName */] = el[_DYN_CLASS_NAME /* @min:%2eclassName */][_DYN_SUBSTRING /* @min:%2esubstring */](0, idx) + el[_DYN_CLASS_NAME /* @min:%2eclassName */][_DYN_SUBSTRING /* @min:%2esubstring */](idx + className[_DYN_LENGTH /* @min:%2elength */]);
    }
}
export function traverseAndReplace(target, maxDepth, currentDepth, thingsReferenced, excludedKeys, includeFunctions) {
    var out = {};
    if (!thingsReferenced) {
        thingsReferenced = [];
    }
    if (isObject(target)) {
        for (var _i = 0, _a = getTargetKeys(target, excludedKeys, includeFunctions); _i < _a.length; _i++) {
            var key = _a[_i];
            var targetValue = target[key];
            if (isSymbol(targetValue)) {
                targetValue = targetValue[_DYN_TO_STRING /* @min:%2etoString */]();
            }
            if (targetValue !== null && arrIndexOf(thingsReferenced, targetValue) !== -1) {
                out[key] = "<circular (".concat(key, " - \"").concat(getTargetName(targetValue), "\")>");
            }
            else if (targetValue !== null && isObject(targetValue)) {
                if (currentDepth >= maxDepth) {
                    out[key] = "<max allowed depth reached>";
                }
                else {
                    thingsReferenced[_DYN_PUSH /* @min:%2epush */](target);
                    out[key] = traverseAndReplace(targetValue, maxDepth, currentDepth + 1, thingsReferenced, excludedKeys, includeFunctions);
                    thingsReferenced.pop();
                }
            }
            else {
                out[key] = targetValue;
            }
        }
    }
    return out;
}
function _sanitizeText(value) {
    if (value) {
        value = value[_DYN_REPLACE /* @min:%2ereplace */](/&/g, "&amp;");
        value = value[_DYN_REPLACE /* @min:%2ereplace */](/>/g, "&gt;");
        value = value[_DYN_REPLACE /* @min:%2ereplace */](/</g, "&lt;");
    }
    return value;
}
function _setInnerText(elm, theText, textFilter) {
    var innerText = theText;
    var matchPos = -1;
    var matchLen = 0;
    var rg = makeRegex(textFilter);
    if (rg) {
        var matchTxt = rg.exec(innerText);
        if (matchTxt && matchTxt[1]) {
            matchPos = theText.indexOf(matchTxt[1]);
            matchLen = matchTxt[1][_DYN_LENGTH /* @min:%2elength */];
        }
    }
    if (matchPos !== -1) {
        var innerHtml = _sanitizeText(theText[_DYN_SUBSTRING /* @min:%2esubstring */](0, matchPos)) +
            "<span class=\"matched-text-filter\">" +
            _sanitizeText(theText[_DYN_SUBSTRING /* @min:%2esubstring */](matchPos, matchPos + matchLen)) +
            "</span>" +
            theText[_DYN_SUBSTRING /* @min:%2esubstring */](matchPos + matchLen);
        elm.innerHTML = innerHtml;
        return true;
    }
    elm[_DYN_INNER_TEXT /* @min:%2einnerText */] = theText;
    return false;
}
var lastSelectedElement;
var selectedObject;
export function copySelectedTree() {
    var toCopy = selectedObject;
    if (!toCopy) {
        return;
    }
    var textArea = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("textarea");
    textArea[_DYN_INNER_TEXT /* @min:%2einnerText */] = JSON.stringify(toCopy);
    textArea.style.opacity = "0";
    document.body[_DYN_APPEND_CHILD /* @min:%2eappendChild */](textArea);
    textArea.select();
    document.execCommand("copy");
    textArea[_DYN_PARENT_ELEMENT /* @min:%2eparentElement */][_DYN_REMOVE_CHILD /* @min:%2eremoveChild */](textArea);
}
export function focusHandler(evt, target, level, excludeKeys, includeFunctions) {
    if (lastSelectedElement) {
        toggleClassName(lastSelectedElement, " last-selected-element");
    }
    lastSelectedElement = evt.target;
    for (var i = 0; i < 10; i++) {
        if (lastSelectedElement.tagName === "DIV") {
            break;
        }
        lastSelectedElement = lastSelectedElement[_DYN_PARENT_ELEMENT /* @min:%2eparentElement */];
    }
    lastSelectedElement[_DYN_CLASS_NAME /* @min:%2eclassName */] += " last-selected-element";
    selectedObject = traverseAndReplace(target, MAX_DEPTH, level, null, excludeKeys, includeFunctions);
}
function _navHandler(evt, openHandler, currentState) {
    var el = evt.target;
    switch (evt.which) {
        // Enter
        case 13:
            (openHandler) ? openHandler(evt) : void 0;
            break;
        // ArrowUp
        case 38:
            evt[_DYN_PREVENT_DEFAULT /* @min:%2epreventDefault */]();
            var prev = el.previousElementSibling;
            if (prev && prev.tagName !== "BUTTON") {
                prev[_DYN_FOCUS /* @min:%2efocus */]();
            }
            break;
        // ArrowDown
        case 40:
            evt[_DYN_PREVENT_DEFAULT /* @min:%2epreventDefault */]();
            var next = el.nextElementSibling;
            if (next) {
                next[_DYN_FOCUS /* @min:%2efocus */]();
            }
            break;
        // ArrowRight
        case 39:
            if (openHandler) {
                openHandler(evt, true);
                if (currentState) {
                    el.firstElementChild.nextSibling[_DYN_FOCUS /* @min:%2efocus */]();
                }
            }
            break;
        // ArrowLeft
        case 37:
            if (openHandler) {
                openHandler(evt, false);
            }
            if (!currentState) {
                el[_DYN_PARENT_ELEMENT /* @min:%2eparentElement */][_DYN_FOCUS /* @min:%2efocus */]();
            }
            break;
        // c
        case 67:
            if (evt.ctrlKey) {
                copySelectedTree();
                evt.target[_DYN_FOCUS /* @min:%2efocus */]();
            }
            break;
    }
}
export function getTargetName(target) {
    if (target) {
        if (isString(target[_DYN_IDENTIFIER /* @min:%2eidentifier */])) {
            return target[_DYN_IDENTIFIER /* @min:%2eidentifier */];
        }
        if (isString(target[_DYN_NAME /* @min:%2ename */])) {
            return target[_DYN_NAME /* @min:%2ename */];
        }
        if (objHasOwnProperty(target, strShimPrototype)) {
            // Look like a prototype
            return target[_DYN_NAME /* @min:%2ename */] || "";
        }
        return ((target[strConstructor]) || {})[_DYN_NAME /* @min:%2ename */] || "";
    }
    return "";
}
function _toString(value) {
    if (isString(value)) {
        return value;
    }
    if (isSymbol(value)) {
        return value[_DYN_TO_STRING /* @min:%2etoString */]();
    }
    if (isFunction(value["toString"])) {
        return value["toString"]() || "";
    }
    return "";
}
export function getTargetKeys(target, excludedKeys, includeFunctions) {
    var keys = objKeys(target);
    if (!isArray(target)) {
        try {
            if (Object[strGetOwnPropertyNames]) {
                // We need to use this for built in objects such as Error which don't return their values via objKeys because they are not enumerable for example
                var propKeys = Object[strGetOwnPropertyNames](target);
                if (propKeys) {
                    arrForEach(propKeys, function (key) {
                        var theKey = _toString(key);
                        if (theKey && arrIndexOf(keys, theKey) === -1) {
                            keys[_DYN_PUSH /* @min:%2epush */](key);
                        }
                    });
                }
            }
        }
        catch (ex) {
            // getOwnPropertyNames can fail in ES5, if the argument to this method is not an object (a primitive),
            // then it will cause a TypeError. In ES2015, a non-object argument will be coerced to an object.
        }
    }
    var theKeys = [];
    arrForEach(keys, function (key) {
        if (!includeFunctions && isFunction(target[key])) {
            return;
        }
        var theKey = _toString(key);
        if (theKey && arrIndexOf(excludedKeys, theKey) === -1) {
            theKeys[_DYN_PUSH /* @min:%2epush */](theKey);
        }
    });
    return theKeys;
}
export function formatLogElements(target, tmLabel, key, level, textFilter, excludeKeys, thingsReferenced, includeFunctions) {
    var openState = false;
    if (!level) {
        level = 0;
    }
    if (!thingsReferenced) {
        thingsReferenced = [];
    }
    var isObj = isObject(target) || isError(target);
    var isErr = target["baseType"] === "ExceptionData" || isError(target);
    var children = [];
    function _openNode(currentLine) {
        openState = true;
        arrForEach(children, function (child) {
            rootDiv[_DYN_APPEND_CHILD /* @min:%2eappendChild */](child);
        });
        currentLine[_DYN_CLASS_NAME /* @min:%2eclassName */] = "obj-key expandable open";
    }
    function _collapseNode(currentLine) {
        // rootDiv.innerHTML = '';
        arrForEach(children, function (child) {
            rootDiv[_DYN_REMOVE_CHILD /* @min:%2eremoveChild */](child);
        });
        // rootDiv.appendChild(currentLine);
        openState = false;
        currentLine[_DYN_CLASS_NAME /* @min:%2eclassName */] = "obj-key expandable closed";
    }
    var matched = false;
    var childOpened = false;
    var keys = getTargetKeys(target, excludeKeys, includeFunctions);
    if (keys[_DYN_LENGTH /* @min:%2elength */] === 0) {
        keys[_DYN_PUSH /* @min:%2epush */]("<empty>");
    }
    if (level >= MAX_DEPTH) {
        keys.unshift("<maxdepth>");
    }
    for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
        var key_1 = keys_1[_i];
        if (arrIndexOf(excludeKeys, key_1) !== -1) {
            continue;
        }
        var targetValue = target[key_1];
        if (isSymbol(targetValue)) {
            targetValue = targetValue[_DYN_TO_STRING /* @min:%2etoString */]();
        }
        if (key_1 === "<maxdepth>") {
            var builder = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("div");
            builder[_DYN_CLASS_NAME /* @min:%2eclassName */] = "empty";
            builder[_DYN_INNER_TEXT /* @min:%2einnerText */] = "<max allowed depth reached>";
            children[_DYN_PUSH /* @min:%2epush */](builder);
            break;
        }
        else if (key_1 === "<empty>") {
            var builder = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("div");
            builder[_DYN_CLASS_NAME /* @min:%2eclassName */] = "empty";
            builder[_DYN_INNER_TEXT /* @min:%2einnerText */] = "<empty>";
            children[_DYN_PUSH /* @min:%2epush */](builder);
        }
        else if (targetValue !== null && arrIndexOf(thingsReferenced, targetValue) !== -1) {
            var builder = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("div");
            builder[_DYN_CLASS_NAME /* @min:%2eclassName */] = "empty";
            builder[_DYN_INNER_TEXT /* @min:%2einnerText */] = "<circular (".concat(key_1, ") - \"").concat(getTargetName(targetValue), "\">");
            children[_DYN_PUSH /* @min:%2epush */](builder);
        }
        else if (targetValue !== null && (isObject(targetValue) || isError(targetValue))) {
            thingsReferenced[_DYN_PUSH /* @min:%2epush */](target);
            var formatted = formatLogElements(targetValue, null, key_1, level + 1, textFilter, excludeKeys, thingsReferenced, includeFunctions);
            thingsReferenced.pop();
            if (formatted.matched) {
                childOpened = true;
            }
            if (formatted.isErr) {
                isErr = true;
            }
            children[_DYN_PUSH /* @min:%2epush */](formatted.root);
        }
        else {
            var builder = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("div");
            builder[_DYN_SET_ATTRIBUTE /* @min:%2esetAttribute */]("tabindex", "0");
            builder[_DYN_ONCLICK /* @min:%2eonclick */] = function (evt) {
                evt[_DYN_STOP_PROPAGATION /* @min:%2estopPropagation */]();
            };
            builder[_DYN_ONTOUCHEND /* @min:%2eontouchend */] = function (evt) {
                evt[_DYN_STOP_PROPAGATION /* @min:%2estopPropagation */]();
            };
            builder.onkeydown = function (evt) {
                evt[_DYN_STOP_PROPAGATION /* @min:%2estopPropagation */]();
                _navHandler(evt);
            };
            builder.onfocus = function (evt) {
                focusHandler(evt, target, level, excludeKeys, includeFunctions);
            };
            var outerSpan = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("span");
            var keySpan = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("span");
            keySpan[_DYN_CLASS_NAME /* @min:%2eclassName */] = "key";
            if (_setInnerText(keySpan, "".concat(key_1, ": "), textFilter)) {
                childOpened = true;
            }
            outerSpan[_DYN_APPEND_CHILD /* @min:%2eappendChild */](keySpan);
            var valueSpan = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("span");
            if (isFunction(targetValue)) {
                var fnStr = targetValue[_DYN_TO_STRING /* @min:%2etoString */]();
                var fnHead = fnStr.match(/^([^{]+)/)[1];
                valueSpan.textContent = "".concat(fnHead, "{...}");
            }
            else {
                if (_setInnerText(valueSpan, "".concat(targetValue), textFilter)) {
                    childOpened = true;
                }
            }
            valueSpan[_DYN_CLASS_NAME /* @min:%2eclassName */] = "".concat(typeof targetValue);
            outerSpan[_DYN_APPEND_CHILD /* @min:%2eappendChild */](valueSpan);
            builder[_DYN_APPEND_CHILD /* @min:%2eappendChild */](outerSpan);
            children[_DYN_PUSH /* @min:%2epush */](builder);
        }
    }
    var rootDiv = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("div");
    var innerText = "";
    var currentLine = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("span");
    if (isObj || children[_DYN_LENGTH /* @min:%2elength */]) {
        innerText = "".concat(key ? key : "obj", ": ");
        if (isArray(target)) {
            innerText += "[".concat(getTargetKeys(target, excludeKeys, includeFunctions).length, "]");
        }
        else {
            var targetName = getTargetName(target);
            if (targetName) {
                innerText += " <\"".concat(targetName, "\"> ");
            }
            innerText += "{".concat(getTargetKeys(target, excludeKeys, includeFunctions).length, "}");
        }
        matched = _setInnerText(currentLine, innerText, textFilter);
        if (tmLabel) {
            var tmWrapper = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("span");
            var tmDetails = document[_DYN_CREATE_ELEMENT /* @min:%2ecreateElement */]("span");
            tmDetails[_DYN_CLASS_NAME /* @min:%2eclassName */] = "obj-time";
            tmDetails[_DYN_INNER_TEXT /* @min:%2einnerText */] = tmLabel;
            tmWrapper[_DYN_APPEND_CHILD /* @min:%2eappendChild */](tmDetails);
            tmWrapper[_DYN_APPEND_CHILD /* @min:%2eappendChild */](currentLine);
            currentLine = tmWrapper;
        }
        currentLine[_DYN_CLASS_NAME /* @min:%2eclassName */] = "obj-key expandable closed";
    }
    else {
        innerText = "".concat(key ? key : "obj", ": ").concat(target.toString());
        matched = _setInnerText(currentLine, innerText, textFilter);
        currentLine[_DYN_CLASS_NAME /* @min:%2eclassName */] = "obj-key";
    }
    rootDiv[_DYN_APPEND_CHILD /* @min:%2eappendChild */](currentLine);
    rootDiv[_DYN_SET_ATTRIBUTE /* @min:%2esetAttribute */]("tabindex", "0");
    if (childOpened) {
        // A child node matched so auto-expand
        _openNode(currentLine);
    }
    if (isObj) {
        if (isErr) {
            rootDiv[_DYN_CLASS_NAME /* @min:%2eclassName */] = "exception";
        }
        var openHandler_1 = function (evt, forceState) {
            evt[_DYN_STOP_PROPAGATION /* @min:%2estopPropagation */]();
            if (getIEVersion()) {
                focusHandler(evt, target, level, excludeKeys, includeFunctions);
            }
            if (forceState !== undefined && openState === forceState) {
                return;
            }
            if (lastSelectedElement === rootDiv) {
                if (openState) {
                    _collapseNode(currentLine);
                }
                else {
                    _openNode(currentLine);
                }
            }
        };
        rootDiv.onkeydown = function (evt) {
            _navHandler(evt, openHandler_1, openState);
        };
        rootDiv[_DYN_ONCLICK /* @min:%2eonclick */] = function (evt) {
            openHandler_1(evt);
        };
        rootDiv[_DYN_ONTOUCHEND /* @min:%2eontouchend */] = function (evt) {
            openHandler_1(evt);
        };
        rootDiv.onfocus = function (evt) {
            focusHandler(evt, target, level, excludeKeys, includeFunctions);
        };
    }
    return {
        root: rootDiv,
        isErr: isErr,
        matched: matched || childOpened
    };
}
//# sourceMappingURL=helpers.js.map