/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/

'use strict';

var obsidian = require('obsidian');

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

const idOnlyRegex = /([0-9]+|[a-z]+)/g;
const checkSettingsMessage = "Try checking the settings if this seems wrong.";
const lettersIDComponentSuccessors = {
    a: "b",
    b: "c",
    c: "d",
    d: "e",
    e: "f",
    f: "g",
    g: "h",
    h: "i",
    i: "j",
    j: "k",
    k: "l",
    l: "m",
    m: "n",
    n: "o",
    o: "p",
    p: "q",
    q: "r",
    r: "s",
    s: "t",
    t: "u",
    u: "v",
    v: "w",
    w: "x",
    x: "y",
    y: "z",
    z: "aa",
};
const DEFAULT_SETTINGS = {
    matchRule: "strict",
    addTitle: false,
    separator: "⁝ ",
};
class LuhmanSettingTab extends obsidian.PluginSettingTab {
    constructor(app, plugin) {
        super(app, plugin);
        this.plugin = plugin;
    }
    display() {
        const { containerEl } = this;
        const { matchRule, separator, addTitle } = this.plugin.settings;
        containerEl.empty();
        containerEl.createEl("p", {
            text: "The ID is a block of letters and numbers at the beginning of the filename",
        });
        new obsidian.Setting(containerEl)
            .setName("ID matching rule")
            .setDesc("Strict means filenames consist of only an ID. " +
            "Separator means the ID must be followed by the separator. " +
            "Fuzzy treats the first non-alphanumeric character as the end of the ID.")
            .addDropdown((setting) => setting
            .addOption("strict", "Strict")
            .addOption("separator", "Separator")
            .addOption("fuzzy", "Fuzzy")
            .setValue(matchRule)
            .onChange((value) => __awaiter(this, void 0, void 0, function* () {
            this.plugin.settings.matchRule = value;
            yield this.plugin.saveSettings();
            this.display();
        })));
        if (matchRule !== "strict") {
            new obsidian.Setting(containerEl)
                .setName("Add titles automatically")
                .setDesc("Add the separator and the title of the note when creating filenames")
                .setDisabled(matchRule !== "strict")
                .addToggle((setting) => setting.setValue(addTitle).onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.addTitle = value;
                yield this.plugin.saveSettings();
                this.display();
            })));
        }
        const useSeparator = matchRule !== "strict" && (addTitle || matchRule === "separator");
        if (useSeparator) {
            new obsidian.Setting(containerEl)
                .setName("ID Separator")
                .setDesc("Used between id and title, include whitespace padding if needed")
                .setDisabled(useSeparator)
                .addText((text) => text
                .setPlaceholder("Enter your separator")
                .setValue(separator)
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.separator = value;
                yield this.plugin.saveSettings();
            })));
        }
    }
}
class NewZettel extends obsidian.Plugin {
    constructor() {
        super(...arguments);
        this.settings = DEFAULT_SETTINGS;
    }
    loadSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
        });
    }
    saveSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.saveData(this.settings);
        });
    }
    incrementStringIDComponent(id) {
        const comps = id.split("");
        const last = comps.pop();
        return comps.concat([lettersIDComponentSuccessors[last]]).join("");
    }
    incrementNumberIDComponent(id) {
        return (parseInt(id) + 1).toString();
    }
    isNumber(string) {
        return /^\d+$/.test(string);
    }
    incrementIDComponent(id) {
        if (this.isNumber(id)) {
            return this.incrementNumberIDComponent(id);
        }
        else {
            return this.incrementStringIDComponent(id);
        }
    }
    incrementID(id) {
        const parts = id.match(idOnlyRegex);
        const lastPart = parts.pop();
        return parts.concat([this.incrementIDComponent(lastPart)]).join("");
    }
    parentID(id) {
        const parts = id.match(idOnlyRegex);
        if (parts) {
            parts.pop();
            return parts.join("");
        }
        else {
            return "";
        }
    }
    nextComponentOf(id) {
        const parts = id.match(idOnlyRegex);
        const lastPart = parts.pop();
        if (this.isNumber(lastPart)) {
            return "a";
        }
        else {
            return "1";
        }
    }
    firstChildOf(parentID) {
        return parentID + this.nextComponentOf(parentID);
    }
    fileToId(filename) {
        const ruleRegexes = {
            strict: /^((?:[0-9]+|[a-z]+)+)$/,
            separator: new RegExp(`^((?:[0-9]+|[a-z]+)+)${this.settings.separator}.*`),
            fuzzy: /^((?:[0-9]+|[a-z]+)+).*/,
        };
        const match = filename.match(ruleRegexes[this.settings.matchRule]);
        if (match) {
            return match[1];
        }
        return "";
    }
    idExists(id) {
        const fileMatcher = (file) => this.fileToId(file.basename) === id;
        return this.app.vault.getMarkdownFiles().filter(fileMatcher).length != 0;
    }
    firstAvailableID(startingID) {
        let nextID = startingID;
        while (this.idExists(nextID)) {
            nextID = this.incrementID(nextID);
        }
        return nextID;
    }
    makeNoteForNextSiblingOf(sibling) {
        const nextID = this.firstAvailableID(this.incrementID(this.fileToId(sibling.basename)));
        return nextID;
    }
    makeNoteForNextChildOf(parent) {
        const childID = this.firstAvailableID(this.firstChildOf(this.fileToId(parent.basename)));
        return childID;
    }
    makeNote(path, title, content, placeCursorAtStartOfContent, openZettel = false) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const app = this.app;
            let titleContent = null;
            if (title && title.length > 0) {
                titleContent = "# " + title + "\n\n";
            }
            else {
                titleContent = "";
            }
            const fullContent = titleContent + content;
            const file = yield this.app.vault.create(path, fullContent);
            const active = app.workspace.getLeaf();
            if (active == null) {
                return;
            }
            if (openZettel == false)
                return;
            yield active.openFile(file);
            const editor = (_a = app.workspace.getActiveViewOfType(obsidian.MarkdownView)) === null || _a === void 0 ? void 0 : _a.editor;
            if (editor == null) {
                return;
            }
            if (placeCursorAtStartOfContent) {
                const position = { line: 2, ch: 0 };
                editor.setCursor(position);
            }
            else {
                editor.exec("goEnd");
            }
        });
    }
    isZettelFile(name) {
        const mdRegex = /.*\.md$/;
        return mdRegex.exec(name) != null && this.fileToId(name) !== "";
    }
    makeNoteFunction(idGenerator, openNewFile = true) {
        var _a;
        const file = this.app.workspace.getActiveFile();
        if (file == null) {
            return;
        }
        if (this.isZettelFile(file.name)) {
            this.fileToId(file.basename);
            const fileLink = "[[" + file.basename + "]]";
            const editor = (_a = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView)) === null || _a === void 0 ? void 0 : _a.editor;
            if (editor == null) {
                return;
            }
            const selection = editor.getSelection();
            const nextID = idGenerator.bind(this, file)();
            const nextPath = (title) => (file === null || file === void 0 ? void 0 : file.path)
                ? this.app.fileManager.getNewFileParent(file.path).path +
                    "/" +
                    nextID +
                    (this.settings.addTitle ? this.settings.separator + title : "") +
                    ".md"
                : "";
            const newLink = (title) => `[[${nextID}${(this.settings.addTitle ? this.settings.separator + title : "")}]]`;
            // const newLink = "[[" + nextID + "]]";
            if (selection) {
                // This current solution eats line returns spaces but thats 
                // fine as it is turning the selection into a title so it makes sense
                const selectionTrimStart = selection.trimStart();
                const selectionTrimEnd = selectionTrimStart.trimEnd();
                const spaceBefore = selection.length - selectionTrimStart.length;
                const spaceAfter = selectionTrimStart.length - selectionTrimEnd.length;
                const title = selectionTrimEnd
                    .split(/\s+/)
                    .map((w) => w[0].toUpperCase() + w.slice(1))
                    .join(" ");
                const selectionPos = editor.listSelections()[0];
                /* By default the anchor is what ever position the selection started
                   how ever replaceRange does not accept it both ways and
                   gets weird if we just pass in the anchor then the head
                   so here we create a vertual anchor and head position to pass in */
                const anchorCorrect = selectionPos.anchor.line == selectionPos.head.line ? // If the anchor and head are on the same line
                    selectionPos.anchor.ch <= selectionPos.head.ch : // Then if anchor is before the head
                    selectionPos.anchor.line < selectionPos.head.line; // else they are not on the same line and just check if anchor is before head
                // if anchorCorrect use as is, else switch
                const virtualAnchor = anchorCorrect ? selectionPos.anchor : selectionPos.head;
                const virtualHead = anchorCorrect ? selectionPos.head : selectionPos.anchor;
                editor.replaceRange(' '.repeat(spaceBefore) + newLink(title) + ' '.repeat(spaceAfter), virtualAnchor, virtualHead);
                this.makeNote(nextPath(title), title, fileLink, true, openNewFile);
            }
            else {
                new NewZettelModal(this.app, (title, options) => {
                    this.insertTextIntoCurrentNote(newLink(title));
                    this.makeNote(nextPath(title), title, fileLink, true, options.openNewZettel);
                }, {
                    openNewZettel: openNewFile
                }).open();
            }
        }
        else {
            new obsidian.Notice(`Couldn't find ID in "${file.basename}". ${checkSettingsMessage}`);
        }
    }
    renameZettel(id, toId) {
        return __awaiter(this, void 0, void 0, function* () {
            this.settings.separator;
            const zettel = this.app.vault
                .getMarkdownFiles()
                .filter((file) => this.fileToId(file.basename) === id)
                .first();
            if (zettel) {
                const id = this.fileToId(zettel.basename);
                const rest = zettel.basename.split(id)[1];
                this.app.fileManager.renameFile(zettel, zettel.parent.path + toId + rest + "." + zettel.extension);
            }
            else {
                new obsidian.Notice(`Couldn't find file for ID ${id}. ${checkSettingsMessage}`);
            }
        });
    }
    moveChildrenDown(id) {
        return __awaiter(this, void 0, void 0, function* () {
            const children = this.getDirectChildZettels(id);
            for (const child of children) {
                yield this.moveZettelDown(this.fileToId(child.basename));
            }
        });
    }
    moveZettelDown(id) {
        return __awaiter(this, void 0, void 0, function* () {
            this.moveChildrenDown(id);
            yield this.renameZettel(id, this.firstAvailableID(id));
        });
    }
    outdentZettel(id) {
        return __awaiter(this, void 0, void 0, function* () {
            const newID = this.incrementID(this.parentID(id));
            if (this.idExists(newID)) {
                yield this.moveZettelDown(newID);
            }
            for (const child of this.getDirectChildZettels(id)) {
                const newChildID = this.firstAvailableID(this.firstChildOf(newID));
                yield this.renameZettel(this.fileToId(child.basename), newChildID);
            }
            yield this.renameZettel(id, newID);
        });
    }
    onload() {
        return __awaiter(this, void 0, void 0, function* () {
            console.log("loading New Zettel");
            this.loadSettings();
            this.addSettingTab(new LuhmanSettingTab(this.app, this));
            // this.app.workspace.onLayoutReady(this.initialize);
            this.addCommand({
                id: "new-sibling-note",
                name: "New Sibling Zettel Note",
                callback: () => {
                    this.makeNoteFunction(this.makeNoteForNextSiblingOf);
                },
            });
            this.addCommand({
                id: "new-child-note",
                name: "New Child Zettel Note",
                callback: () => {
                    this.makeNoteFunction(this.makeNoteForNextChildOf);
                },
            });
            this.addCommand({
                id: "new-sibling-note-dont-open",
                name: "New Sibling Zettel Note (Don't Open)",
                callback: () => {
                    this.makeNoteFunction(this.makeNoteForNextSiblingOf, false);
                },
            });
            this.addCommand({
                id: "new-child-note-dont-open",
                name: "New Child Zettel Note (Don't Open)",
                callback: () => {
                    this.makeNoteFunction(this.makeNoteForNextChildOf, false);
                },
            });
            this.addCommand({
                id: "insert-zettel-link",
                name: "Insert Zettel Link",
                callback: () => __awaiter(this, void 0, void 0, function* () {
                    // let completion = (te)
                    const titles = yield this.getAllNoteTitles();
                    new ZettelSuggester(this.app, titles, this.currentlySelectedText(), (file) => {
                        this.insertTextIntoCurrentNote("[[" + file.basename + "]]");
                    }).open();
                }),
            });
            this.addCommand({
                id: "open-zettel",
                name: "Open Zettel",
                callback: () => __awaiter(this, void 0, void 0, function* () {
                    const titles = yield this.getAllNoteTitles();
                    new ZettelSuggester(this.app, titles, this.currentlySelectedText(), (file) => {
                        this.app.workspace.getLeaf().openFile(file);
                    }).open();
                }),
            });
            this.addCommand({
                id: "open-parent-zettel",
                name: "Open Parent Zettel",
                callback: () => {
                    const file = this.currentFile();
                    if (file) {
                        const id = this.fileToId(file.basename);
                        const parentId = this.parentID(id);
                        if (parentId === "") {
                            new obsidian.Notice(`No parent found for "${file.basename}". ${checkSettingsMessage}`);
                            return;
                        }
                        this.openZettel(parentId);
                    }
                    else {
                        new obsidian.Notice("No file open");
                    }
                },
            });
            this.addCommand({
                id: "outdent-zettel",
                name: "Outdent Zettel",
                callback: () => {
                    const file = this.currentFile();
                    if (file) {
                        this.outdentZettel(this.fileToId(file.basename));
                    }
                },
            });
        });
    }
    onunload() {
        console.log("unloading New Zettel");
        // this.initialize(true);
    }
    currentFile() {
        var _a;
        return (_a = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView)) === null || _a === void 0 ? void 0 : _a.file;
    }
    openZettel(id) {
        const file = this.app.vault
            .getMarkdownFiles()
            .filter((file) => this.fileToId(file.basename) == id)
            .first();
        if (file) {
            this.app.workspace.getLeaf().openFile(file);
        }
    }
    currentlySelectedText() {
        var _a;
        return (_a = this.app.workspace
            .getActiveViewOfType(obsidian.MarkdownView)) === null || _a === void 0 ? void 0 : _a.editor.getSelection();
    }
    insertTextIntoCurrentNote(text) {
        const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
        if (view) {
            const editor = view.editor;
            let position;
            let prefix = "";
            if (editor.getSelection()) {
                const selectionPos = editor.listSelections()[0];
                const positionCH = Math.max(selectionPos.head.ch, selectionPos.anchor.ch);
                position = { line: selectionPos.anchor.line, ch: positionCH + 1 };
                prefix = " ";
            }
            else {
                position = editor.getCursor();
            }
            editor.replaceRange(prefix + text, position, position);
        }
    }
    getZettels() {
        const fileToId = (file) => this.fileToId(file.basename);
        return this.app.vault.getMarkdownFiles().filter((file) => {
            const ignore = !file.path.match(/^(_layouts|templates|scripts)/);
            return ignore && fileToId(file) !== "";
        });
    }
    getDirectChildZettels(ofParent) {
        return this.getZettels().filter((file) => {
            return this.parentID(this.fileToId(file.basename)) == ofParent;
        });
    }
    getAllNoteTitles() {
        return __awaiter(this, void 0, void 0, function* () {
            const regex = /# (.+)\s*/;
            const titles = new Map();
            for (const file of this.getZettels()) {
                const text = yield this.app.vault.cachedRead(file);
                const match = text.match(regex);
                if (match) {
                    titles.set(match[1], file);
                }
            }
            return titles;
        });
    }
}
const MakeZettelModelOptionDefault = () => ({
    openNewZettel: true
});
class NewZettelModal extends obsidian.Modal {
    constructor(app, completion, options = MakeZettelModelOptionDefault()) {
        super(app);
        this.completion = completion;
        /***********************************
         ** Model Title                   **
         ***********************************/
        const { contentEl } = this;
        contentEl.parentElement.addClass("zettel-modal");
        this.titleEl.setText("New zettel title...");
        /***********************************
         ** Name and GO area              **
         ***********************************/
        // Setup the container
        const main_container = contentEl.createEl("div", {
            cls: "zettel-modal-container",
        });
        // Add the textBox
        this.textBox = contentEl.createEl("input", {
            type: "text",
            cls: "zettel-modal-textbox",
        });
        this.textBox.id = "zettel-modal-textbox";
        this.textBox.addEventListener("keydown", (event) => {
            if (event.key == "Enter") {
                event.preventDefault();
                this.goTapped();
            }
        });
        main_container.append(this.textBox);
        // Add the go button
        const button = contentEl.createEl("input", {
            type: "button",
            value: "GO",
            cls: "zettel-modal-button",
        });
        button.addEventListener("click", (e) => this.goTapped());
        main_container.append(button);
        contentEl.append(main_container);
        /***********************************
         ** New Zettel Options            **
         ***********************************/
        // Setup the container
        const options_container = contentEl.appendChild(contentEl.createEl("div", {
            cls: ["zettel-modal-container", "zettel-options-container"],
        }));
        // Create label inside the container
        const label = options_container.appendChild(contentEl.createEl("label", {
            cls: ["label", "zettel-label"]
        }));
        // Create label
        const openNewZettelCheckboxLabel = label.appendChild(contentEl.createEl("div", { cls: ["labelText"] }));
        openNewZettelCheckboxLabel.innerText = "Open New Zettel on Creation";
        // Create checkbox inside the container
        this.openNewZettelCheckbox = label.appendChild(contentEl.createEl("input", {
            type: "checkbox",
            cls: ["zettel-modal-checkbox"],
            value: options.openNewZettel.toString()
        }));
        this.openNewZettelCheckbox.id = "zettel-modal-option-openZettel";
        this.openNewZettelCheckbox.checked = options.openNewZettel;
    }
    onOpen() {
        window.setTimeout(() => {
            this.textBox.focus();
        }, 0);
    }
    goTapped() {
        const title = this.textBox.value;
        const openNewZettel = this.openNewZettelCheckbox.checked;
        this.completion(title, {
            openNewZettel
        });
        this.close();
    }
}
class ZettelSuggester extends obsidian.FuzzySuggestModal {
    constructor(app, titles, search, completion) {
        super(app);
        this.initialQuery = search !== null && search !== void 0 ? search : "";
        this.titles = titles;
        this.completion = completion;
        this.emptyStateText = "No zettels found";
        this.setPlaceholder("Search for a zettel...");
        console.log(this.initialQuery);
    }
    onOpen() {
        super.onOpen();
        this.inputEl.value = this.initialQuery;
        const event = new Event("input");
        this.inputEl.dispatchEvent(event);
    }
    getItems() {
        return Array.from(this.titles.keys()).sort();
    }
    getItemText(item) {
        return item;
    }
    renderSuggestion(value, el) {
        el.setText(value.item);
        const matches = value.match.matches;
        if (matches == null || matches.length == 0) {
            return;
        }
        const start = matches[0][0];
        const end = matches[0][1];
        const range = new Range();
        const text = el.firstChild;
        if (text == null) {
            return;
        }
        range.setStart(text, start);
        range.setEnd(text, end);
        range.surroundContents(document.createElement("b"));
    }
    onChooseItem(item, evt) {
        this.completion(this.titles.get(item));
    }
}

module.exports = NewZettel;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 26404 characters]
