var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
define(["require", "exports", "bootbox", "jquery", "./interactivity", "./search-replace"], function (require, exports, bootbox, jquery_1, interactivity_1, search_replace_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    bootbox = __importStar(bootbox);
    jquery_1 = __importDefault(jquery_1);
    exports.Direction = search_replace_1.Direction;
    const dialogTemplate = `
<form>
 <div class='form-group'>
  <label>Search for:</label>
  <input type='text' name='search' class='form-control'>
 </div>
 <div class='form-group'>
  <label>Replace with:</label>
  <input type='text' name='replace' class='form-control'>
 </div>
 <div class='radio'>
  <span>Direction:</span>
  <div>
   <label class='radio-inline'>
    <input type='radio' name='direction' value='forward'> Forward
   </label>
  </div>
  <div>
   <label class='radio-inline'>
    <input type='radio' name='direction' value='backwards'> Backwards
   </label>
  <div>
 </div>
 <div class='radio'>
  <span>Context:</span>
  <div>
   <label class='radio-inline'>
    <input type='radio' name='context' value='text' checked>
    Only element text
   </label>
  </div>
  <div>
   <label class='radio-inline'>
    <input type='radio' name='context' value='attributes'>
    Only attributes values
   </label>
  </div>
 </div>
</form>`;
    /**
     * Brings up a search and replace dialog box to allow the user to search through
     * a document. See the section on "Dialog Search" in the editor's embedded help
     * for details of how it works for users.
     */
    class DialogSearchReplace {
        /**
         * @param editor The editor for which we are searching.
         *
         * @param scroller The scroller holding the document being searched.
         *
         * @param direction The direction of the search.
         */
        constructor(editor, scroller, direction) {
            this.search = new search_replace_1.SearchReplace(editor, scroller);
            const body = jquery_1.default(dialogTemplate)[0];
            const dialog = bootbox.dialog({
                title: "Search/Replace",
                message: body,
                onEscape: true,
                backdrop: false,
                size: "small",
                buttons: {
                    find: {
                        label: "Find",
                        className: "btn-primary",
                        callback: this.onFind.bind(this),
                    },
                    replaceFind: {
                        label: "Replace and Find",
                        className: "btn-default replace-and-find",
                        callback: this.onReplaceAndFind.bind(this),
                    },
                    replaceAll: {
                        label: "Replace All",
                        className: "btn-default replace-all",
                        callback: this.onReplaceAll.bind(this),
                    },
                    close: {
                        label: "Close",
                    },
                },
            });
            interactivity_1.makeResizable(dialog);
            interactivity_1.makeDraggable(dialog);
            const directionItems = body.elements
                .namedItem("direction");
            this.forwardRadioButton = directionItems[0];
            this.backwardRadioButton = directionItems[1];
            const contextItems = body.elements
                .namedItem("context");
            this.textRadioButton = contextItems[0];
            this.attributeRadioButton = contextItems[1];
            let toCheck;
            switch (direction) {
                case search_replace_1.Direction.FORWARD:
                    toCheck = this.forwardRadioButton;
                    break;
                case search_replace_1.Direction.BACKWARDS:
                    toCheck = this.backwardRadioButton;
                    break;
                default:
                    const d = direction;
                    throw new Error(`unknown direction: ${d}`);
            }
            toCheck.checked = true;
            dialog.on("hidden.bs.modal", () => {
                this.search.clearHighlight();
                // Return the focus to the editor.
                editor.caretManager.focusInputField();
            });
            const searchField = this.searchField =
                body.elements.namedItem("search");
            const $searchField = jquery_1.default(searchField);
            $searchField.on("input", this.onSearchInput.bind(this));
            const replaceField = this.replaceField =
                body.elements.namedItem("replace");
            const $replaceField = jquery_1.default(replaceField);
            $replaceField.on("input", this.onReplaceInput.bind(this));
            this.replaceButton =
                dialog[0].querySelector(".replace-and-find");
            this.replaceAll =
                dialog[0].querySelector(".replace-all");
            this.updateButtons();
        }
        /**
         * @returns The search option to pass to the search engine, given the user
         * choices.
         */
        getSearchOptions() {
            let direction;
            if (this.forwardRadioButton.checked) {
                direction = search_replace_1.Direction.FORWARD;
            }
            else if (this.backwardRadioButton.checked) {
                direction = search_replace_1.Direction.BACKWARDS;
            }
            else {
                throw new Error("cannot determine direction");
            }
            let context;
            if (this.textRadioButton.checked) {
                context = search_replace_1.Context.TEXT;
            }
            else if (this.attributeRadioButton.checked) {
                context = search_replace_1.Context.ATTRIBUTE_VALUES;
            }
            else {
                throw new Error("cannot determine context");
            }
            return {
                direction,
                context,
            };
        }
        /**
         * Processes clicks on the "Find" button: searches the document and updates
         * the buttons.
         */
        onFind() {
            this.next();
            this.updateButtons();
            return false;
        }
        /**
         * Updates the disabled status of the buttons depending on how the input
         * elements are set.
         */
        updateButtons() {
            const fieldFilled = this.replaceField.value !== "";
            this.replaceButton.disabled = !(fieldFilled && this.search.canReplace);
            this.replaceAll.disabled = !fieldFilled;
        }
        /**
         * Processes clicks on the "Replace and Find" button: replaces the current hit
         * and find the next one.
         */
        onReplaceAndFind() {
            this.replace();
            this.onFind();
            return false;
        }
        /**
         * Processes clicks on the "Replace All" button: replaces all replaceable
         * hits.
         */
        onReplaceAll() {
            if (this.search.current === undefined) {
                this.onFind();
            }
            while (this.search.current !== null) {
                if (this.search.canReplace) {
                    this.replace();
                }
                this.next();
            }
            this.updateButtons();
            return false;
        }
        /**
         * Replaces the current hit.
         */
        replace() {
            this.search.replace(this.replaceField.value);
        }
        /**
         * Moves to the next hit in the direction specified by the user.
         */
        next() {
            this.search.next(this.getSearchOptions());
        }
        /**
         * Processes an ``input`` event on the search field. May change the currently
         * highlighted hit.
         */
        onSearchInput() {
            const value = this.searchField.value;
            if (value !== this.previousSearchValue) {
                this.previousSearchValue = value;
                this.search.updatePattern(value, this.getSearchOptions());
                this.updateButtons();
            }
        }
        /**
         * Processes an ``input`` event on the replace field. Updates the buttons.
         */
        onReplaceInput() {
            this.updateButtons();
        }
    }
    exports.DialogSearchReplace = DialogSearchReplace;
});
//# sourceMappingURL=dialog-search-replace.js.map