/**
 * Adds indentation using the `Tab` key, and auto-indents after a newline, as well as making it 
 * possible to indent/unindent multiple lines using Tab/Shift+Tab
 */
 codeInput.plugins.Indent = class extends codeInput.Plugin {
    constructor() {
        super();
    }

    /* Add keystroke events */
    afterElementsAdded(codeInput) {
        codeInput.check_tab = this.check_tab;
        codeInput.check_enter = this.check_enter;
        codeInput.querySelector("textarea").setAttribute("onkeydown", "this.parentElement.check_tab(event); this.parentElement.check_enter(event);");
    }

    /* Event handlers */
    check_tab(event) {
        if(event.key != "Tab") {
            return;
        }
        let input_element = this.querySelector("textarea");
        let code = input_element.value;
        event.preventDefault(); // stop normal
        
        if(!event.shiftKey && input_element.selectionStart == input_element.selectionEnd) {
            // Shift always means dedent - this places a tab here.
            let before_selection = code.slice(0, input_element.selectionStart); // text before tab
            let after_selection = code.slice(input_element.selectionEnd, input_element.value.length); // text after tab

            let cursor_pos = input_element.selectionEnd + 1; // where cursor moves after tab - moving forward by 1 char to after tab
            input_element.value = before_selection + "\t" + after_selection; // add tab char

            // move cursor
            input_element.selectionStart = cursor_pos;
            input_element.selectionEnd = cursor_pos;

        } else {
            let lines = input_element.value.split("\n");
            let letter_i = 0;

            let selection_start = input_element.selectionStart; // where cursor moves after tab - moving forward by 1 indent
            let selection_end = input_element.selectionEnd; // where cursor moves after tab - moving forward by 1 indent

            let number_indents = 0;
            let first_line_indents = 0;

            for (let i = 0; i < lines.length; i++) {
                letter_i += lines[i].length+1; // newline counted
                
                log(lines[i], ": start", input_element.selectionStart, letter_i, "&& end", input_element.selectionEnd , letter_i - lines[i].length)
                if(input_element.selectionStart <= letter_i && input_element.selectionEnd >= letter_i - lines[i].length) {
                    // Starts before or at last char and ends after or at first char
                    if(event.shiftKey) {
                        if(lines[i][0] == "\t") {
                            // Remove first tab
                            lines[i] = lines[i].slice(1);
                            if(number_indents == 0) first_line_indents--;
                            number_indents--;
                        }
                    } else {
                        lines[i] = "\t" + lines[i];
                        if(number_indents == 0) first_line_indents++;
                        number_indents++;
                    }
                    
                }
            }
            input_element.value = lines.join("\n");

            // move cursor
            input_element.selectionStart = selection_start + first_line_indents;
            input_element.selectionEnd = selection_end + number_indents;
        }

        this.update(input_element.value);
    }

    check_enter(event) {

        if(event.key!=="Enter"){return}

        event.preventDefault()// enter was pressed, we will eithe run the query or process the enter separately
        
        if(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey){
            //if it is alt-enter, ctrl-enter, shift-enter, or win-enter, run the query
            run_query(event.target)
            return;
        } 
        //code to manipulate textarea and prism div as if enter were pressed

        let input_element = this.querySelector("textarea");
        let lines = input_element.value.split("\n");
        let letter_i = 0;
        let current_line = lines.length - 1;
        let new_line = "";
        let number_indents = 0;

        // find the index of the line our cursor is currently on
        for (let i = 0; i < lines.length; i++) {
            letter_i += lines[i].length + 1;
            if(input_element.selectionEnd <= letter_i) {
                current_line = i;
                break;
            }
        }

        // count the number of indents the current line starts with (up to our cursor position in the line)
        let cursor_pos_in_line = lines[current_line].length - (letter_i - input_element.selectionEnd) + 1;
        for (let i = 0; i < cursor_pos_in_line; i++) {
            if (lines[current_line][i] == "\t") {
                number_indents++;
            } else {
                break;
            }
        }

        // determine the text before and after the cursor and chop the current line at the new line break
        let text_after_cursor = "";
        if (cursor_pos_in_line != lines[current_line].length) {
            text_after_cursor = lines[current_line].substring(cursor_pos_in_line);
            lines[current_line] = lines[current_line].substring(0, cursor_pos_in_line);
        }

        // insert our indents and any text from the previous line that might have been after the line break
        for (let i = 0; i < number_indents; i++) {
            new_line += "\t";
        }
        new_line += text_after_cursor;

        // save the current cursor position
        let selection_start = input_element.selectionStart;
        let selection_end = input_element.selectionEnd;

        // splice our new line into the list of existing lines and join them all back up
        lines.splice(current_line + 1, 0, new_line);
        input_element.value = lines.join("\n");

        // move cursor to new position
        input_element.selectionStart = selection_start + number_indents + 1;  // count the indent level and the newline character
        input_element.selectionEnd = selection_end + number_indents + 1;

        this.update(input_element.value);
    }
}