let BIT_DISPLAYS = ["bank", "pc", "ma", "ac", "io", "running", "defer", "ov", "extend", "inst"];    //MSH: Added defer & inst
let FORWARD_ELEMS = ["pf", "sense"];

function init_word(type) {    //MSH: type = 0:ZERO, 1:TW, -1:RANDOM
    switch (type) {
    case -1:
        return Math.floor( Math.random() * 0o1000000 );
    case 0:
        return 0o000000;
    case 1:
        return window.testWord;
    }
}

class PDP1Console {

    constructor() {
        this._elems = {};
        this._inputs = {};
        for(let elem of document.querySelectorAll("input[data-console]")) {
            let list = this._elems[elem.dataset.console];
            if(!list) {
                list = [];
                this._elems[elem.dataset.console] = list;
            }
            if(!FORWARD_ELEMS.includes(elem.dataset.console)) {
                list.unshift(elem); // Reverse order. 0th element will be LSB
            } else {
                list.push(elem);
            }
        }
        for(let elem of document.querySelectorAll("[data-console-test-input]")) {
            let checkboxes = elem.querySelectorAll("input[type=checkbox]");
            let maxbit = checkboxes.length - 1;
            for(let i = 0; i < checkboxes.length; i++) {
                let checkbox = checkboxes[i];
                let bit = maxbit - i;
                checkbox.addEventListener("change", function(e) {
                    if(this.checked) {
                        window[elem.dataset.consoleTestInput] |= (1<<bit);
                    } else {
                        window[elem.dataset.consoleTestInput] &= ~(1<<bit);
                    }
                });
            }
        }
        for(let elem of document.querySelectorAll("[data-console-input]")) {
            let checkboxes = elem.querySelectorAll("input[type=checkbox");
            for(let i = 0; i < checkboxes.length; i++) {
                checkboxes[i].addEventListener("change", function() {
                    window.sense(i+1, this.checked);
                });
            }
        }
    }

    displayBits(elems, value) {
        for(let i = 0; i < elems.length; i++) {
            elems[i].checked = (value>>i)&1 === 1;
        }
    }

    displayPF() {
        for(let i = 0; i < 6; i++) {
            this._elems.pf[i].checked = flag(i+1);
        }
    }

    display() {
        for(let valToDisplay of BIT_DISPLAYS) {
            this.displayBits(this._elems[valToDisplay], window[valToDisplay]);
        }
        this.displayPF();
    }

    start() {
        // Note: If we are not currently STOPPED (i.e. 'running'), this may not do what you expect!
        if (window.running) console.log( "START PC =", os6(window.testAddress) );    //MSH: Log START
        window.ov      = 0;
        window.extend  = window.extendEnable;                                        //MSH: Add initial EXTEND
        window.bank    = window.testAddress >> 12;
        window.pc      = window.testAddress & 0o7777;
        window.running = 1;
    }

    stop() {
        window.running = 0;
    }

    continue() {
        window.running = 1;
    }

    examine() {
        if (window.running) {                                                                                         //MSH: Log EXAMINE ...
            console.log( "EXAMINE", os6(window.testAddress), "=", os6(window.memory[window.testAddress]) );    //MSH: ... if we are ...
        } else {                                                                                               //MSH: ... running
            window.ma = window.testAddress;                                                                    //MSH: Show MA
//          window.mb = window.memory[window.testAddress];                                                     //MSH: TODO
            window.ac = window.memory[window.testAddress];
        }
    }

    deposit() {
        if (window.running) {                                                                    //MSH: Log ...
            console.log( "DEPOSIT", os6(window.testAddress), "(",                         //MSH: ... DEPOSIT ...
                os6(window.memory[window.testAddress]), ") =", os6(window.testWord) );    //MSH: ... if we are ...
        } else {                                                                          //MSH: ... running
            window.ma = window.testAddress;                                               //MSH: Show MA
//          window.mb = window.memory[window.testAddress];                                //MSH: TODO
            window.ac = window.testWord;                                                  //MSH: Show AC=(MA)
        }
        window.memory[window.testAddress] = window.testWord;
    }

    init(type) {    //MSH: type = 0:ZERO, 1:TW, -1:RANDOM
        if (window.running) {
            console.log( "INIT ignored (CPU is currently running)" );
        } else {
            window.bank     = init_word( type ) >> 12 & 0o17;
            window.pc       = init_word( type ) & 0o007777;
            window.ma       = init_word( type ) & 0o177777;
        //  window.mb       = init_word( type );  //MSH: TODO
            window.ac       = init_word( type );
            window.io       = init_word( type );
            window.ov       = init_word( type ) & 1;
            window._flag[0] = init_word( type ) & 0o40;
            window._flag[1] = init_word( type ) & 0o20;
            window._flag[2] = init_word( type ) & 0o10;
            window._flag[3] = init_word( type ) & 0o04;
            window._flag[4] = init_word( type ) & 0o02;
            window._flag[5] = init_word( type ) & 0o01;
            window.defer    = 0;
            window.extend   = window.extendEnable;
            window.inst     = 0;

            // Fill memory

            switch (type) {
            case -1:
                console.log( "INIT memory to RANDOM" );
                for(let i = 0; i < memory.length; i++) {
                    memory[i] = Math.floor( Math.random() * 0o1000000 );
                }
                memory[0] &= 0o017777;  // Ensure the usual start addresses ...
                memory[4] &= 0o017777;  // ... both contain illegal instructions
                break;
            case 0:
                console.log( "INIT memory to 000000" );
                memory.fill( 0o000000 );
                break;
            case 1:
                console.log( "INIT memory to", os6( window.testWord ), "(TW)" );
                memory.fill( window.testWord );
                break;
            }
        }
    }

    reset_switches(state) {    //MSH: true or false
        if (!state) {
            window.testAddress = 0o000000;
        } else {
            window.testAddress = 0o177777;
        }
        document.getElementById("ta0").checked  = state;
        document.getElementById("ta1").checked  = state;
        document.getElementById("ta2").checked  = state;
        document.getElementById("ta3").checked  = state;
        document.getElementById("ta4").checked  = state;
        document.getElementById("ta5").checked  = state;
        document.getElementById("ta6").checked  = state;
        document.getElementById("ta7").checked  = state;
        document.getElementById("ta8").checked  = state;
        document.getElementById("ta9").checked  = state;
        document.getElementById("ta10").checked = state;
        document.getElementById("ta11").checked = state;
        document.getElementById("ta12").checked = state;
        document.getElementById("ta13").checked = state;
        document.getElementById("ta14").checked = state;
        document.getElementById("ta15").checked = state;

        if (!state) {
            window.testWord = 0o000000;
        } else {
            window.testWord = 0o777777;
        }
        document.getElementById("tw0").checked  = state;
        document.getElementById("tw1").checked  = state;
        document.getElementById("tw2").checked  = state;
        document.getElementById("tw3").checked  = state;
        document.getElementById("tw4").checked  = state;
        document.getElementById("tw5").checked  = state;
        document.getElementById("tw6").checked  = state;
        document.getElementById("tw7").checked  = state;
        document.getElementById("tw8").checked  = state;
        document.getElementById("tw9").checked  = state;
        document.getElementById("tw10").checked = state;
        document.getElementById("tw11").checked = state;
        document.getElementById("tw12").checked = state;
        document.getElementById("tw13").checked = state;
        document.getElementById("tw14").checked = state;
        document.getElementById("tw15").checked = state;
        document.getElementById("tw16").checked = state;
        document.getElementById("tw17").checked = state;

        if (!state) {
            window.extendEnable = state;
            document.getElementById("ex").checked  = state;

            window.singleInst = state;
            document.getElementById("si").checked  = state;

            window.stopJump = state;
            document.getElementById("saj").checked  = state;

            window.stopIOT = state;
            document.getElementById("sai").checked  = state;

            window.stopPDP1C = state;
            document.getElementById("sap").checked  = state;
        }

        window._sense = [state, state, state, state, state, state];
        document.getElementById("ss1").checked  = state;
        document.getElementById("ss2").checked  = state;
        document.getElementById("ss3").checked  = state;
        document.getElementById("ss4").checked  = state;
        document.getElementById("ss5").checked  = state;
        document.getElementById("ss6").checked  = state;

    //  window.MULDIV = state;
    //  document.getElementById("muldiv-checkbox").checked  = state;
    }
}
