// Dicom saved settings
var dicom_settings_db = new Dexie("dicom_settings");
dicom_settings_db.version(1).stores({
    mouse_bindings: "button,mode,tool",
});


cornerstoneBase64ImageLoader.external.cornerstone = cornerstone;
cornerstoneWebImageLoader.external.cornerstone = cornerstone;
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;

cornerstoneTools.init({
    keyboardEnabled: true
});

let tool_state = {};

export function loadCornerstone(main_element, db, images, annotations_to_load, load_as_stack = false) {
    // canvas-panel holds the enabled elements and all tools / menus
    const canvas_panel = $("<div class='canvas-panel'></div>");
    main_element.append(canvas_panel);
    main_element[0].dataset.collapsed = "none";


    const cornerstone_element = $("<div class='cornerstone-element'></div>");
    const element = cornerstone_element.get(0);
    canvas_panel.append(cornerstone_element);
    canvas_panel.append($(`<div id='dicom-summary-panel'>
            <span id="dicom-summary-close" class="close-button"><a href="#">close</a></span>
<div class="container-fluid">
    <h1>DICOM Summary</h1>

    <div class="panel panel-default ">
        <div class="panel-heading">
            <h3 class="panel-title">Patient Information</h3>
        </div>
        <div class="panel-body">
            <div>
                <div>
                    Patient Name: <span data-dicom="x00100010"></span>
                </div>
                <div>
                    Patient ID: <span data-dicom="x00100020"></span>
                </div>
            </div>
            <div>
                <div>
                    Patient Birth Date: <span data-dicom="x00100030"></span>
                </div>
                <div>
                    Patient Sex: <span data-dicom="x00100040"></span>
                </div>
            </div>
        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Study Information</h3>
        </div>
        <div class="panel-body">
            <div>
                <div>
                    Study Description: <span data-dicom="x00081030"></span>
                </div>
                <div>
                    Protocol Name: <span data-dicom="x00181030"></span>
                </div>
            </div>
            <div>
                <div>
                    Accession #: <span data-dicom="x00080050"></span>
                </div>
                <div>
                    Study Id: <span data-dicom="x00200010"></span>
                </div>
            </div>
            <div>
                <div>
                    Study Date: <span data-dicom="x00080020"></span>
                </div>
                <div>
                    Study Time: <span data-dicom="x00080030"></span>
                </div>
            </div>

        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Series Information</h3>
        </div>
        <div class="panel-body">
            <div>
                <div>
                    Series Description: <span data-dicom="x0008103e"></span>
                </div>
                <div>
                    Series #: <span data-dicom="x00200011"></span>
                </div>
            </div>
            <div>
                <div>
                    Modality: <span data-dicom="x00080060"></span>
                </div>
                <div>
                    Body Part: <span data-dicom="x00180015"></span>
                </div>
            </div>
            <div>
                <div>
                    Series Date: <span data-dicom="x00080021"></span>
                </div>
                <div>
                    Series Time: <span data-dicom="x00080031"></span>
                </div>
            </div>

        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Instance Information</h3>
        </div>
        <div class="panel-body">
            <div>
                <div>
                    Instance #: <span data-dicom="x00200013"></span>
                </div>
                <div>
                    Acquisition #: <span data-dicom="x00200012"></span>
                </div>
            </div>
            <div>
                <div>
                    Acquisition Date: <span data-dicom="x00080022"></span>
                </div>
                <div>
                    Acquisition Time: <span data-dicom="x00080032"></span>
                </div>
            </div>
            <div>
                <div>
                    Content Date: <span data-dicom="x00080023"></span>
                </div>
                <div>
                    Content Time: <span data-dicom="x00080033"></span>
                </div>
            </div>



        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Image Information</h3>
        </div>
        <div class="panel-body">
            <div>
                <div>
                    Rows: <span data-dicomUint="x00280010"></span>
                </div>
                <div>
                    Columns: <span data-dicomUint="x00280011"></span>
                </div>
            </div>

            <div>
                <div>
                    Photometric Interpretation: <span data-dicom="x00280004"></span>
                </div>
                <div>
                    Image Type: <span data-dicom="x00080008"></span>
                </div>

            </div>

            <div>
                <div>
                    Bits Allocated: <span data-dicomUint="x00280100"></span>
                </div>
                <div>
                    Bits Stored: <span data-dicomUint="x00280101"></span>
                </div>
            </div>

            <div>
                <div>
                    HighBit: <span data-dicomUint="x00280102"></span>
                </div>
                <div>
                    Pixel Representation (0=us): <span data-dicomUint="x00280103"></span>
                </div>
            </div>

            <div>
                <div>
                    Rescale Slope: <span data-dicom="x00281053"></span>
                </div>
                <div>
                    Rescale Intercept: <span data-dicom="x00281052"></span>
                </div>
            </div>
            <div>
                <div>
                    Image Position Patient: <span data-dicom="x00200032"></span>
                </div>
                <div>
                    Image Orientation Patient: <span data-dicom="x00200037"></span>
                </div>
            </div>
            <div>
                <div>
                    Pixel Spacing: <span data-dicom="x00280030"></span>
                </div>
                <div>
                    Samples Per Pixel: <span data-dicomUint="x00280002"></span>
                </div>
            </div>

        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Equipment Information</h3>
        </div>
        <div class="panel-body">
            <div>
                <div>
                    Manufacturer: <span data-dicom="x00080070"></span>
                </div>
                <div>
                    Model: <span data-dicom="x00081090"></span>
                </div>
            </div>
            <div>
                <div>
                    Station Name: <span data-dicom="x00081010"></span>
                </div>
                <div>
                    AE Title: <span data-dicom="x00020016"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Institution Name: <span data-dicom="x00080080"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Software Version: <span data-dicom="x00181020"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Implementation Version Name: <span data-dicom="x00020013"></span>
                </div>
            </div>
        </div>
    </div>

    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">UIDS</h3>
        </div>
        <div class="panel-body">
            <div>
                <div class="col-xs-12">
                    Study UID: <span data-dicom="x0020000d"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Series UID: <span data-dicom="x0020000e"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Instance UID: <span data-dicom="x00080018"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    SOP Class UID: <span data-dicom="x00080016"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Transfer Syntax UID: <span data-dicom="x00020010"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    Frame of Reference UID: <span data-dicom="x00200052"></span>
                </div>
            </div>
            <div>
                <div class="col-xs-12">
                    WADO URL:
                    <div style="overflow:auto">
                        <span>http://localhost:3333/wado?requestType=WADO&studyUID=</span><span
                            data-dicom="x0020000d"></span><span>&seriesUID=</span><span
                            data-dicom="x0020000e"></span><span>&objectUID=</span><span
                            data-dicom="x00080018"></span><span>&contentType=application%2Fdicom&transferSyntax=1.2.840.10008.1.2.1</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
    </div>`));


    canvas_panel.append($(`<div id='dicom-log-panel'>
            <span id="dicom-log-close" class="close-button"><a href="#">close</a></span>
    </div>`));

    // Add generic settings menus to canvas-panel
    $(".canvas-panel").append(
            $(`<div id='dicom-settings-panel'>
            <span id="dicom-settings-close" class="close-button"><a href="#">close</a></span>
            <span class="view-log-button"><a href="#">view log</a></span>
            <h3>Image viewer settings:</h3>

            Primary
            <div id="primary-mouse-binding">
            <label for="left-mouse-dicom">Left mouse button:</label>
            <select
            id="left-mouse-dicom"
            class="mouse-binding-select"
            data-button="1"
            data-mode="0"
            >
            </select>
            <label for="middle-mouse-dicom">Middle mouse button:</label>
            <select
            id="middle-mouse-dicom"
            class="mouse-binding-select"
            data-button="4"
            data-mode="0"
            >
            </select>
            <label for="right-mouse-dicom">Right mouse button:</label>
            <select
            id="right-mouse-dicom"
            class="mouse-binding-select"
            data-button="2"
            data-mode="0"
            >
            </select>
            <label for="left-right-mouse-dicom">Left+Right mouse buttons:</label>
            <select
            id="left-right-mouse-dicom"
            class="mouse-binding-select"
            data-button="3"
            data-mode="0"
            >
            </select>
            </div>
            <br />
            Secondary (Ctrl)
            <div id="secondary-mouse-binding">
            <label for="left-mouse-dicom-secondary">Left mouse button:</label>
            <select
            id="left-mouse-dicom-secondary"
            class="mouse-binding-select"
            data-button="1"
            data-mode="1"
            >
            </select>
            <label for="middle-mouse-dicom-secondary">Middle mouse button:</label>
            <select
            id="middle-mouse-dicom-secondary"
            class="mouse-binding-select"
            data-button="4"
            data-mode="1"
            >
            </select>
            <label for="right-mouse-dicom-secondary">Right mouse button:</label>
            <select
            id="right-mouse-dicom-secondary"
            class="mouse-binding-select"
            data-button="2"
            data-mode="1"
            >
            </select>
            <label for="left-right-mouse-dicom-secondary">Left+Right mouse buttons:</label>
            <select
            id="left-right-mouse-dicom-secondary"
            class="mouse-binding-select"
            data-button="3"
            data-mode="1"
            >
            </select>
            </div>

        </div>`)
        )
        .append($("<span id='dicom-toggle-mode-button' class='dicom-button' title='toggle stack/thumbnail view'>↻</span>"))
        .append($("<span id='dicom-fullscreen-button' class='dicom-button' title='toggle stack/thumbnail view'>⛶</span>"))
        .append($("<span id='dicom-settings-button' class='dicom-button' title='open settings'>&#9881;</span>"))
        .append($("<span id='dicom-collapse-button' class='dicom-button' title='collapse viewer'>⇄</span>"))
        .append($("<span id='dicom-info-button' class='dicom-button' title='view image info'>🛈</span>"))
        .append(
            $(`<div id='dicom-window-panel'>
           <button id='window-btn-abdomen'>Abdomen</button> 
           <button id='window-btn-liver'>Liver</button> 
           <button id='window-btn-mediastinum'>Mediastinum</button> 
           <button id='window-btn-lung'>Lungs</button> 
           <button id='window-btn-brain'>Brain</button> 
           <button id='window-btn-stroke'>Stroke</button> 
           <button id='window-btn-bone'>Bone</button> 
            </div>`)
        );

    cornerstone_element.append(
        $(
            "<div id='dicom-overlay'>Image <span id='current_image_number'></span> of <span id='total_image_number'></span><br />wc: <span id='wc'></span> ww: <span id='ww'></span></div>"
        )
    );
    // Add buttons

    let window_presets = {
        "window-btn-abdomen": [400, 50],
        "window-btn-liver": [150, 30],
        "window-btn-mediastinum": [350, 50],
        "window-btn-lung": [1500, -600],
        "window-btn-brain": [80, 40],
        "window-btn-stroke": [40, 40],
        "window-btn-bone": [1800, 400]
    }

    $("#dicom-window-panel button").each((n, el) => {
        $(el).click((e) => {
            let button_id = e.target.id;
            let [ww, wc] = window_presets[button_id];

            let viewport = cornerstone.getViewport(element);
            viewport.voi.windowWidth = parseFloat(ww);
            viewport.voi.windowCenter = parseFloat(wc);
            cornerstone.setViewport(element, viewport);

            e.preventDefault();
            e.stopPropagation();

        })
    })

    $("#dicom-settings-close").click(e => {
        $("#dicom-settings-panel").hide();
        e.preventDefault();
    });
    $("#dicom-summary-close").click(e => {
        $("#dicom-summary-panel").hide();
        e.preventDefault();
    });
    $("#dicom-log-close").click(e => {
        $("#dicom-log-panel").hide();
        e.preventDefault();
    });
    $(".view-log-button").click(e => {
        $("#dicom-settings-panel").hide();
        $("#dicom-log-panel").show();
        e.preventDefault();
    });
    $("#dicom-settings-button").click(e => {
        $("#dicom-settings-panel").toggle();
    });
    $("#dicom-info-button").click(e => {
        try {
            // todo improve
            dumpDataSet(cornerstone.getEnabledElement(element).image.data);
        } catch {
            console.log("unable to extract dicom data")

        }
        $("#dicom-summary-panel").toggle();
    });
    $("#dicom-fullscreen-button").click(e => {
        if (!document.fullscreenElement) {
            $(".canvas-panel").get(0).requestFullscreen().catch(err => {
                alert(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
            });
        } else {
            document.exitFullscreen();
        }
    });
    $("#dicom-toggle-mode-button").click(e => {
        //$("#dicom-settings-panel").toggle();
        let stack = !load_as_stack;
        $(main_element).empty();
        loadCornerstone(main_element, db, images, annotations_to_load, stack)
    });

    $("#dicom-collapse-button").click(e => {
        //$("#dicom-settings-panel").toggle();
        //let stack = !load_as_stack;
        if (main_element[0].dataset.collapsed == "none") {
            main_element[0].dataset.collapsed = main_element.width();
            main_element.width("50px");
            $("#dicom-window-panel").hide();
            $(e.target).addClass("dicom-button-highlight");
        } else {
            main_element.width(main_element[0].dataset.collapsed);
            main_element[0].dataset.collapsed = "none"
            $("#dicom-window-panel").show();
            $(e.target).removeClass("dicom-button-highlight");
        }
        resizeHandler(element);
        //loadCornerstone(main_element, db, images, annotations_to_load, stack)
    });

    //let images = data["images"];

    // Make sure we have an array
    if (!Array.isArray(images)) {
        images = [images];
    }


    //let annotations = [];
    //if (annotations_to_load) { 
    //annotations = annotations_to_load[figure_to_load.split("-")[1]];
    //if (!Array.isArray(annotations)) {
    //annotations = [annotations];
    //}
    //}
    let annotations = annotations_to_load;
    if (!Array.isArray(annotations)) {
        annotations = [annotations];
    }


    function loadAnnotation(imageId, annotation) {
        const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;

        if (annotation == undefined || annotation.length < 1 || annotation == [undefined]) {
            return
        }

        let tool_state_no_id = JSON.parse(annotation);

        tool_state[imageId] = tool_state_no_id;

        toolStateManager.restoreToolState(tool_state);
    }

    async function load(images, annotations) {
        let imageIds = [];
        for (let i = 0; i < images.length; i++) {
            let data_url = images[i];
            const annotation = annotations[i];
            // check stack type
            if (data_url.startsWith("data:image")) {
                let imageId = "base64://" + data_url.split(",")[1];

                loadAnnotation(imageId, annotation);

                imageIds.push(imageId);
            } else if (data_url.startsWith("base64://") || data_url.startsWith("wadouri:")) {
                loadAnnotation(data_url, annotation);

                imageIds.push(data_url);

                // Treat application/octet-stream as if they are dicoms
            } else if (data_url.startsWith("data:application/dicom") || data_url.startsWith("data:application/octet-stream")) {
                //stack = stack.split(";")[1];

                let dfile = await urltoFile(data_url, "dicom", "application/dicom");

                const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
                    dfile
                );

                loadAnnotation(imageId, annotation);

                imageIds.push(imageId);
                //cornerstone.loadImage(imageId).then(function(image) {
                //    tempFunction(image);
                //});
            } else {
                let url;
                // This doesn't seem to have any benefit
                //if (data_url.startsWith("http")) {
                //    url = data_url;
                //} else {
                //    url = window.location.href.replace(/\/\#\/?$/, '') + "/" + data_url
                //}
                url = data_url;

                if (url.endsWith("dcm")) {
                    url = "wadouri:" + url;
                }

                // if there is no extension treat it as a dicom
                if (/(?:\/|^)[^.\/]+$/.test(url)) {
                    url = "wadouri:" + url;
                }

                loadAnnotation(url, annotation);

                imageIds.push(url);


            }
        }
        const stack = {
            currentImageIdIndex: 0,
            imageIds
        };
        //cornerstone.loadAndCacheImage(imageIds[0]).then(function(image) {
        cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {

                //console.log("LOAD and cache, then", image);
                loadCornerstoneMainImage(element, image, stack, db, load_as_stack);
                checkAnonStatus(image.data)

                let load_annotation_image = true;
                if (load_annotation_image) {
                    getNextAnnotationImage(element)
                }
            })
            .catch((err, err2) => {
                console.log(err);
                $("#dicom-log-panel").append("<br/>").append(err.stack);

            });
    }

    function loadCornerstoneThumb(image, id) {
        let img = $("<div></div>").get(0);
        img.id = "thumb-image-" + id;
        img.class = "thumbnail";
        img.title =
            "Click on the thumbnail to view and manipulate the image.";
        img.draggable = "false";
        img.style = "height: 100px; width: 100px";
        $("#thumb-" + id).append(img);

        const element = document.getElementById("thumb-image-" + id);
        cornerstone.enable(element);
        cornerstone.displayImage(element, image);
        cornerstone.resize(element);
    }

    if (images.length > 1 && load_as_stack == false) {
        $(".canvas-panel").append("<div id='image-thumbs'></div>");
        for (let id = 0; id < images.length; id++) {
            let n = id + 1;
            let thumb = $(
                "<div class='thumb' id='thumb-" +
                id +
                "' data-id=" +
                id +
                "><span>" +
                n +
                "</span></div>"
            );
            $("#image-thumbs").append(thumb);
            $("#thumb-" + id).click((evt) => {
                selectThumbClick(evt, element)
            }).mousedown(stopEvent);

            let image_url = images[id];

            let img;


            if (image_url.startsWith("data")) {
                // based (image) data url, just load the image directly
                if (image_url.startsWith("data:image/")) {
                    img = $("<img />", {
                        src: image_url,
                        id: "thumb-image-" + id,
                        class: "thumbnail",
                        title: "Click on the thumbnail to view and manipulate the image.",
                        draggable: "false",
                        style: "height: 100px;"
                    });

                    $("#thumb-" + id).append(img);

                    // otherwise try to load it as a dicom
                } else {
                    // convert the data url to a file
                    urltoFile(image_url, "dicom", "application/dicom").then(function (
                        dfile
                    ) {
                        // load the file using cornerstoneWADO file loader
                        const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
                            dfile
                        );
                        cornerstone.loadAndCacheImage(imageId).then(function (image) {
                            loadCornerstoneThumb(image, id);
                        });
                    });
                }
            } else {
                if (image_url.startsWith("wadouri") || image_url.startsWith("base64")) {
                    cornerstone.loadAndCacheImage(image_url).then(function (image) {
                        loadCornerstoneThumb(image, id);
                    });
                } else if ((!image_url.endsWith("dicom") && !image_url.endsWith("dcm"))) {
                    img = $("<img />", {
                        src: image_url,
                        id: "thumb-image-" + id,
                        class: "thumbnail",
                        title: "Click on the thumbnail to view and manipulate the image.",
                        draggable: "false",
                        style: "height: 100px;"
                    });

                    $("#thumb-" + id).append(img);

                    // otherwise try to load it as a dicom
                } else {

                    let url = "wadouri:" + image_url;
                    cornerstone.loadAndCacheImage(url).then(function (image) {
                        loadCornerstoneThumb(image, id);
                    });
                }
            }
        }
    }

    load(images, annotations);

    main_element.keydown((evt) => {
        keyDownHandler(evt, element)
    });
    main_element.keyup((evt) => {
        keyUpHandler(evt, element)
    });


}

function keyUpHandler(e, element) {
    if (e.key == "Control") {
        registerPrimaryDicomInterface(element);
        window.control_pressed = false;
    }
}

function keyDownHandler(e, element) {
    //// Ignore our custom keybindings if we are currently in a field that
    //// accepts some kind of input
    //if ($("*:focus:not(disabled)").is("textarea, input")) {
    //  // unless a modifier key is pressed (not shift)
    //  if (e.altKey ? true : false || e.ctrlKey ? true : false) {} else {
    //    return;
    //  }
    //}

    if (e.key == "Control") {
        if (window.control_pressed != true) {
            window.control_pressed = true;
            registerAltDicomInterface(e, element);
        }
    }

    var charCode = typeof e.which == "number" ? e.which : e.keyCode;

    function numberKeyPressed(e, x) {
        if (e.altKey ? true : false) {
            loadStackIndex(x, element);
            e.preventDefault();
        } else {}
    }

    switch (charCode) {
        case 13: // Return
            getNextAnnotationImage(element);
            if (e.shiftKey ? true : false) {
                //$(".next-button:last").click();
            } else {
                //$(".check-button:last").click();
            }
            break;
        case 32: // Space
            if (e.shiftKey ? true : false) {
                //$(".previous-button:last").click();
            } else {
                //$(".next-button:last").click();
            }
            e.preventDefault(); // Needed to stop the default action (scroll)
            break;
        case 38: // Up
            manualScrollDicom(1, element);
            e.preventDefault();
            break;
        case 40: // down
            manualScrollDicom(-1, element);
            e.preventDefault();
            break;
        case 46: // .
            //toggleFlagged();
            break;

            // Numbers 1-9 select the corresponding answer (if it exists)
            // TODO: fix for multi question questions
        case 49: // 1
            numberKeyPressed(e, 0);
            break;
        case 50: // 2
            numberKeyPressed(e, 1);
            break;
        case 51: // 3
            numberKeyPressed(e, 2);
            break;
        case 52: // 4
            numberKeyPressed(e, 3);
            break;
        case 53: // 5
            numberKeyPressed(e, 4);
            break;
        case 54: // 6
            numberKeyPressed(e, 5);
            break;
        case 55: // 7
            numberKeyPressed(e, 6);
            break;
        case 56: // 8
            numberKeyPressed(e, 7);
            break;
        case 57: // 9
            numberKeyPressed(e, 8);
            break;
        case 72: // H
            previousQuestion();
            break;
        case 76: // L
            //nextQuestion();
            break;

        case 102: // f
            //$("#filter-toggle").click();
            break;
        case 103: // g
            //$("#options").slideDown("slow");
            //$("#goto-question-input").focus();
            //e.preventDefault();
            break;

            // Vim like scrolling (incredibly important)
        case 106: // j
            //window.scrollBy(0, 25);
            break;
        case 107: // k
            //window.scrollBy(0, -25);
            break;
    }
}


function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
    // It is probably silly to do this each time we load a question
    const PanTool = cornerstoneTools.PanTool;
    const ZoomTool = cornerstoneTools.ZoomTool;
    const ZoomMouseWheelTool = cornerstoneTools.ZoomMouseWheelTool;
    const StackScrollMouseWheelTool = cornerstoneTools.StackScrollMouseWheelTool;
    const WwwcTool = cornerstoneTools.WwwcTool;
    const WwwcRegionTool = cornerstoneTools.WwwcRegionTool;
    const RotateTool = cornerstoneTools.RotateTool;
    const StackScrollTool = cornerstoneTools.StackScrollTool;
    const MagnifyTool = cornerstoneTools.MagnifyTool;
    const ArrowAnnotateTool = cornerstoneTools.ArrowAnnotateTool;
    const RectangleRoiTool = cornerstoneTools.RectangleRoiTool;
    const LengthTool = cornerstoneTools.LengthTool;
    const AngleTool = cornerstoneTools.AngleTool;
    const CobbAngleTool = cornerstoneTools.CobbAngleTool;
    const EraserTool = cornerstoneTools.EraserTool;

    cornerstone.enable(element);
    element.tabIndex = 0;

    cornerstone.displayImage(element, image);

    //cornerstoneTools.keyboardInput.enable(element);

    cornerstoneTools.addStackStateManager(element, ["stack"]);
    cornerstoneTools.addToolState(element, "stack", stack);

    cornerstoneTools.addToolForElement(element, PanTool);
    cornerstoneTools.addToolForElement(element, ZoomTool);
    cornerstoneTools.addToolForElement(element, ZoomMouseWheelTool);
    cornerstoneTools.addToolForElement(element, StackScrollMouseWheelTool);
    cornerstoneTools.addToolForElement(element, WwwcTool);
    cornerstoneTools.addToolForElement(element, WwwcRegionTool);
    cornerstoneTools.addToolForElement(element, RotateTool);
    cornerstoneTools.addToolForElement(element, StackScrollTool);
    cornerstoneTools.addToolForElement(element, MagnifyTool);
    cornerstoneTools.addToolForElement(element, LengthTool);
    cornerstoneTools.addToolForElement(element, AngleTool);
    cornerstoneTools.addToolForElement(element, CobbAngleTool);
    cornerstoneTools.addToolForElement(element, EraserTool);
    //cornerstoneTools.addTool(ArrowAnnotateTool);
    //cornerstoneTools.addTool(RectangleRoiTool);

    cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, {
        configuration: {
            getTextCallback: () => {},
            changeTextCallback: () => {},
            allowEmptyLabel: true,
            renderDashed: false,
            drawHandles: false,
            drawHandlesOnHover: true,
        },
    });
    cornerstoneTools.addToolForElement(element, RectangleRoiTool, {
        configuration: {
            showHounsfieldUnits: false,
            showMinMax: false,
            allowEmptyLabel: true,
            renderDashed: false,
            drawHandles: false,
            drawHandlesOnHover: true,
        },
    });

    cornerstoneTools.setToolEnabledForElement(element, "ArrowAnnotate");


    let available_tools = [
        "Pan",
        "Zoom",
        "Wwwc",
        "WwwcRegion",
        "Rotate",
        "StackScroll",
        "Magnify",
        "Length",
        "ArrowAnnotate",
        "RectangleRoi",
        "Angle",
        "CobbAngle",
        "Eraser",
    ];
    $(".mouse-binding-select option").remove();

    available_tools.forEach(function (tool) {
        let option = "<option value=" + tool + ">" + tool + "</option>";
        $(".mouse-binding-select").append(option);
        //$("#left-mouse-dicom").append(option);
        //$("#middle-mouse-dicom").append(option);
        //$("#right-mouse-dicom").append(option);
    });
    $(".mouse-binding-select").on("change", function (evt) {
        changeMouseBinding(evt, db, element);
    });

    // Set default tools
    $("#primary-mouse-binding .mouse-binding-select[data-button=1]").val("Pan");
    $("#primary-mouse-binding .mouse-binding-select[data-button=2]").val("Wwwc");
    $("#primary-mouse-binding .mouse-binding-select[data-button=3]").val("Zoom");
    $("#primary-mouse-binding .mouse-binding-select[data-button=4]").val("Zoom");
    //cornerstoneTools.setToolActive("Pan", { mouseButtonMask: 1 });

    if (load_as_stack) {
        cornerstoneTools.setToolActiveForElement(element, "StackScrollMouseWheel", {
            //mouseButtonMask: [4]
        });
    } else {
        cornerstoneTools.setToolActiveForElement(element, "ZoomMouseWheel", {
            //mouseButtonMask: [4]
        });
    }
    //cornerstoneTools.setToolActive("Zoom", { mouseButtonMask: 4 });
    //cornerstoneTools.setToolActive("Wwwc", { mouseButtonMask: 2 });
    $("#secondary-mouse-binding .mouse-binding-select[data-button=1]").val(
        "Magnify"
    );
    $("#secondary-mouse-binding .mouse-binding-select[data-button=2]").val(
        "Rotate"
    );
    $("#secondary-mouse-binding .mouse-binding-select[data-button=3]").val(
        "StackScroll"
    );
    $("#secondary-mouse-binding .mouse-binding-select[data-button=4]").val(
        "WwwcRegion"
    );

    loadPrimaryDicomInterface(db, element);
    loadAltDicomInterface(db);

    element.addEventListener("cornerstoneimagerendered", onImageRendered);
    element.addEventListener("cornerstonenewimage", onNewImage);
    //element.addEventListener("cornerstonetoolskeydown", keyDownHandler);

    //setDicomCanvasNonFullscreen(element);
    cornerstone.reset(element);
    //element.scrollIntoView(false);
    //element.scrollTo(0);

    $(element).dblclick(function () {
        cornerstone.reset(this);
    });

    element.removeEventListener("wheel", element.wheelEventHandler);

    // Add tool selector
    //$(".canvas-panel").append(
    //  '<select class="control-overlay"><option value="pan">pan</option><option value="zoom">zoom</option><option value="rotate">rotate</option><option value="scroll" hidden="" disabled="">scroll (1/1)</option><option value="window">window ()</option><option value="abdomen" hidden="" disabled="">window = abdomen</option><option value="pulmonary" hidden="" disabled="">window = pulmonary</option><option value="brain" hidden="" disabled="">window = brain</option><option value="bone" hidden="" disabled="">window = bone</option><option value="reset">reset</option></select>'
    //);

    //$(".control-overlay")
    //  .get(0)
    //  .addEventListener("change", changeControlSelection);

    resizeHandler(element);

    window.addEventListener("resize", () => {
        resizeHandler(element)
    });
    element.addEventListener(
        "contextmenu",
        function (e) {
            // do something here...
            e.preventDefault();
        },
        false
    );


    $(element).on("mouseup", function (event) {
        console.log(event)
        if (event.which == 4) {
            getNextAnnotationImage(element)
        }
        $(".magnifyTool").hide();
    });
}

function resizeHandler(element) {
    let h = window.innerHeight - $("#header").height() - 16;
    $(element).height(h);
    cornerstone.resize(element, true);
}

async function loadPrimaryDicomInterface(db, element) {
    const bindings = await dicom_settings_db.mouse_bindings.where({
        mode: "0"
    }).toArray().catch((err) => {
        console.log(err);
    });
    bindings.forEach(function (b) {
        let sel = $("#primary-mouse-binding select[data-button=" + b.button + "]").get(
            0
        );
        sel.value = b.tool;
        //sel.dispatchEvent(new Event("change"));
    });
    registerPrimaryDicomInterface(element);
}

async function loadAltDicomInterface(db) {
    const bindings = await dicom_settings_db.mouse_bindings.where({
        mode: "1"
    }).toArray().catch((err) => {
        console.log(err);
    });
    bindings.forEach(function (b) {
        let sel = $(
            "#secondary-mouse-binding select[data-button=" + b.button + "]"
        ).get(0);
        sel.value = b.tool;
    });
}

function onNewImage(e) {
    let dataSet = e.detail.image.data;
    checkAnonStatus(dataSet)
}

function checkAnonStatus(dataSet) {
    let accession_number = dataSet.string('x00080050').toLowerCase();
    let patient_id = dataSet.string('x00100020').toLowerCase();

    let not_anon = false;

    let site_codes = ["ref", "rk9", "ra9", "rh8", "rbz", "rba"]

    for (let i = 0; i < site_codes.length; i++) {
        if (
            accession_number.startsWith(site_codes[i]) ||
            patient_id.startsWith(site_codes[i])) {
            not_anon = true;
        }
    }

    if (not_anon) {
        toastr.warning(`File does not appear to be annonymised<br/>Accession: ${accession_number} <br/>Patient ID: ${patient_id}<br/>`, 'Anonymisation warning', {
            "closeButton": false,
            "debug": false,
            "newestOnTop": false,
            "progressBar": false,
            "positionClass": "toast-top-full-width",
            "preventDuplicates": false,
            "onclick": null,
            "showDuration": "0",
            "hideDuration": "0",
            "timeOut": 0,
            "extendedTimeOut": 0,
            "showEasing": "swing",
            "hideEasing": "linear",
            "showMethod": "fadeIn",
            "hideMethod": "fadeOut",
        });
    }
}

// Called when the dicom image is loaded / rendered
function onImageRendered(e) {
    const eventData = e.detail;

    // Update ww/wl
    $("#wc").text(Math.round(eventData.viewport.voi.windowCenter));
    $("#ww").text(Math.round(eventData.viewport.voi.windowWidth));

    // update stack data
    let stack = eventData.enabledElement.toolStateManager.toolState.stack.data[0];

    $("#total_image_number").text(stack.imageIds.length);
    $("#current_image_number").text(parseInt(stack.currentImageIdIndex) + 1);

    if (stack.imageIds.length > 1) {
        $(".thumb").removeClass("thumb-active");
        $("#thumb-" + stack.currentImageIdIndex).addClass("thumb-active");
    }
}

function stopEvent(evt) {
    //console.log("stop", evt)
    evt.preventDefault();
    evt.stopPropagation();
}

function selectThumbClick(evt, element) {
    let new_index = evt.currentTarget.dataset.id;
    loadStackIndex(new_index, element);
    evt.preventDefault();
}


export function registerPrimaryDicomInterface(element) {
    console.log("reg primary")
    // Set mousetools based upon the selected options
    let selections = $("#primary-mouse-binding select");
    selections.each((i, option) => {
        cornerstoneTools.setToolActiveForElement(element, option.value, {
            mouseButtonMask: parseInt(option.dataset.button)
        });
    });
}

export function registerAltDicomInterface(e, element) {
    // Called when control is pressed

    // Set mousetools based upon the selected options
    //let element = document.getElementsByClassName("cornerstone-element")[0];
    console.log("reg alt", element)
    let selections = $("#secondary-mouse-binding select");
    selections.each((i, option) => {
        cornerstoneTools.setToolActiveForElement(element, option.value, {
            mouseButtonMask: parseInt(option.dataset.button)
        });
    });
}

function changeMouseBinding(evt, db, element) {
    let select = evt.currentTarget;
    let button = select.dataset.button;
    let mode = select.dataset.mode;
    let tool = select.value;

    // Directly activate primary tools (secondary will be activated when modifier
    // key is pressed
    if (mode == "0") {
        cornerstoneTools.setToolActiveForElement(element, tool, {
            mouseButtonMask: parseInt(button)
        });
    }

    dicom_settings_db.mouse_bindings.put({
        button: button,
        mode: mode,
        tool: tool
    });
    //db.mouse_bindings.put({button: button, mode: mode, tool: tool}).then(loadPrimaryDicomInterface());
}

export function loadStackIndex(new_index, dicom_element) {
    console.log("select new stack index", new_index);
    // There must be a better way to do this...
    if (dicom_element == null) {
        return;
    }
    let c = cornerstone.getEnabledElement(dicom_element);
    //   let current_index =
    //     c.toolStateManager.toolState.stack.data[0].currentImageIdIndex;
    c.toolStateManager.toolState.stack.data[0].currentImageIdIndex = new_index;
    let id = c.toolStateManager.toolState.stack.data[0].imageIds[new_index];
    ////console.log("select thumb id", id);
    //console.log("select thumb el", dicom_element);
    cornerstone.loadImage(id).then(b => {
        //console.log("b", b);
        cornerstone.displayImage(dicom_element, b);
    });
    //c = cornerstone.getEnabledElement(dicom_element)
}

function urltoFile(url, filename, mimeType) {
    return fetch(url)
        .then(function (res) {
            return res.arrayBuffer();
        })
        .then(function (buf) {
            return new File([buf], filename, {
                type: mimeType
            });
        });
}

function dumpDataSet(dataSet) {
    $('span[data-dicom]').each(function (index, value) {
        var attr = $(value).attr('data-dicom');
        var element = dataSet.elements[attr];
        var text = "";
        if (element !== undefined) {
            var str = dataSet.string(attr);
            if (str !== undefined) {
                text = str;
            }
        }
        $(value).text(text);
    });

    $('span[data-dicomUint]').each(function (index, value) {
        var attr = $(value).attr('data-dicomUint');
        var element = dataSet.elements[attr];
        var text = "";
        if (element !== undefined) {
            if (element.length === 2) {
                text += dataSet.uint16(attr);
            } else if (element.length === 4) {
                text += dataSet.uint32(attr);
            }
        }

        $(value).text(text);
    });

}

export function getNextAnnotationImage(element) {
    const enabled_element = cornerstone.getEnabledElement(element)
    const image_ids = enabled_element.toolStateManager.toolState.stack.data[0].imageIds;
    const current_image = enabled_element.toolStateManager.toolState.stack.data[0].currentImageIdIndex;
    const annotated_images = Object.getOwnPropertyNames(cornerstoneTools.globalImageIdSpecificToolStateManager.saveToolState());

    if (annotated_images.length > 0) {
        let offset = current_image;
        for (let i = 0; i < image_ids.length; i++) {
            let pointer = (i + offset) % image_ids.length;
            if (annotated_images.includes(image_ids[pointer])) {
                loadStackIndex(pointer, element);

            }
        }
    }
}

function manualScrollDicom(n, dicom_element) {
  // There must be a better way to do this...
  //dicom_element = document.getElementById("dicom-image");
  let c = cornerstone.getEnabledElement(dicom_element);

  let max = c.toolStateManager.toolState.stack.data[0].imageIds.length;

  if (max < 2) {
    return;
  }

  let current_index =
    c.toolStateManager.toolState.stack.data[0].currentImageIdIndex;

  let new_index = current_index + n
  
  let corrected_index = Math.min(Math.max(new_index, 0), max)

  // TODO: if loop
  //if (new_index >= max) {
  //  corrected_index = new_index - max;
  //} else if (new_index < 0) {
  //  corrected_index = new_index + max;
  //}

  c.toolStateManager.toolState.stack.data[0].currentImageIdIndex = corrected_index;
  let id = c.toolStateManager.toolState.stack.data[0].imageIds[corrected_index];
  cornerstone.loadImage(id).then((b) => {
    cornerstone.displayImage(dicom_element, b);
  });
  // c = cornerstone.getEnabledElement(dicom_element)
}