'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());
    });
}

class Settings {
    constructor() {
        this.fileDirections = {};
        this.defaultDirection = 'ltr';
        this.rememberPerFile = true;
        this.setNoteTitleDirection = true;
        this.setYamlDirection = false;
    }
    toJson() {
        return JSON.stringify(this);
    }
    fromJson(content) {
        var obj = JSON.parse(content);
        this.fileDirections = obj['fileDirections'];
        this.defaultDirection = obj['defaultDirection'];
        this.rememberPerFile = obj['rememberPerFile'];
        this.setNoteTitleDirection = obj['setNoteTitleDirection'];
    }
}
class RtlPlugin extends obsidian.Plugin {
    constructor() {
        super(...arguments);
        this.settings = new Settings();
        this.SETTINGS_PATH = '.obsidian/rtl.json';
        // This stores the value in CodeMirror's autoCloseBrackets option before overriding it, so it can be restored when
        // we're back to LTR
        this.autoCloseBracketsValue = false;
        this.initialized = false;
    }
    onload() {
        this.addCommand({
            id: 'switch-text-direction',
            name: 'Switch Text Direction (LTR<>RTL)',
            callback: () => { this.toggleDocumentDirection(); }
        });
        this.addSettingTab(new RtlSettingsTab(this.app, this));
        this.loadSettings();
        this.app.workspace.on('active-leaf-change', (leaf) => __awaiter(this, void 0, void 0, function* () {
            if (leaf.view instanceof obsidian.MarkdownView) {
                const file = leaf.view.file;
                yield this.onFileOpen(file);
            }
        }));
        this.app.workspace.on('file-open', (file) => __awaiter(this, void 0, void 0, function* () {
            yield this.onFileOpen(file);
        }));
        this.registerEvent(this.app.vault.on('delete', (file) => {
            if (file && file.path && file.path in this.settings.fileDirections) {
                delete this.settings.fileDirections[file.path];
                this.saveSettings();
            }
        }));
        this.registerEvent(this.app.vault.on('rename', (file, oldPath) => {
            if (file && file.path && oldPath in this.settings.fileDirections) {
                this.settings.fileDirections[file.path] = this.settings.fileDirections[oldPath];
                delete this.settings.fileDirections[oldPath];
                this.saveSettings();
            }
        }));
    }
    initialize() {
        return __awaiter(this, void 0, void 0, function* () {
            this.initialized = true;
        });
    }
    onunload() {
        console.log('unloading RTL plugin');
    }
    onFileOpen(file) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!this.initialized)
                yield this.initialize();
            if (file && file.path) {
                this.syncDefaultDirection();
                this.currentFile = file;
                this.adjustDirectionToCurrentFile();
            }
        });
    }
    adjustDirectionToCurrentFile() {
        if (this.currentFile && this.currentFile.path) {
            let requiredDirection = null;
            const frontMatterDirection = this.getFrontMatterDirection(this.currentFile);
            if (frontMatterDirection) {
                if (frontMatterDirection == 'rtl' || frontMatterDirection == 'ltr')
                    requiredDirection = frontMatterDirection;
                else
                    console.log('Front matter direction in file', this.currentFile.path, 'is unknown:', frontMatterDirection);
            }
            else if (this.settings.rememberPerFile && this.currentFile.path in this.settings.fileDirections) {
                // If the user wants to remember the direction per file, and we have a direction set for this file -- use it
                requiredDirection = this.settings.fileDirections[this.currentFile.path];
            }
            else {
                // Use the default direction
                requiredDirection = this.settings.defaultDirection;
            }
            this.setDocumentDirection(requiredDirection);
        }
    }
    saveSettings() {
        var settings = this.settings.toJson();
        this.app.vault.adapter.write(this.SETTINGS_PATH, settings);
    }
    loadSettings() {
        this.app.vault.adapter.read(this.SETTINGS_PATH).
            then((content) => this.settings.fromJson(content)).
            catch(error => { console.log("RTL settings file not found"); });
    }
    getCmEditor() {
        var _a;
        let view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
        if (view)
            return (_a = view.sourceMode) === null || _a === void 0 ? void 0 : _a.cmEditor;
        return null;
    }
    setDocumentDirection(newDirection) {
        let view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
        if (!view || !(view === null || view === void 0 ? void 0 : view.editor))
            return;
        const editorDivs = view.contentEl.getElementsByClassName('cm-editor');
        for (const editorDiv of editorDivs) {
            if (editorDiv instanceof HTMLDivElement)
                this.setDocumentDirectionForEditorDiv(editorDiv, newDirection);
        }
        const markdownPreviews = view.contentEl.getElementsByClassName('markdown-preview-view');
        for (const preview of markdownPreviews) {
            if (preview instanceof HTMLDivElement)
                this.setDocumentDirectionForReadingDiv(preview, newDirection);
        }
        // --- General global fixes ---
        // Fix list indentation problems in RTL
        this.replacePageStyleByString('List indent fix', `/* List indent fix */ .is-rtl .HyperMD-list-line { text-indent: 0px !important; }`, true);
        this.replacePageStyleByString('CodeMirror-rtl pre', `.CodeMirror-rtl pre { text-indent: 0px !important; }`, true);
        // Embedded backlinks should always be shown as LTR
        this.replacePageStyleByString('Embedded links always LTR', `/* Embedded links always LTR */ .embedded-backlinks { direction: ltr; }`, true);
        // Fold indicator fix (not perfect yet -- it can't be clicked)
        this.replacePageStyleByString('Fold symbol fix', `/* Fold symbol fix*/ .is-rtl .cm-fold-indicator { right: -15px !important; }`, true);
        if (this.settings.setNoteTitleDirection) {
            const container = view.containerEl.parentElement;
            let header = container.getElementsByClassName('view-header-title-container');
            header[0].style.direction = newDirection;
        }
        view.editor.refresh();
        // Set the *currently active* export direction. This is global and changes every time the user
        // switches a pane
        this.setExportDirection(newDirection);
    }
    setDocumentDirectionForEditorDiv(editorDiv, newDirection) {
        editorDiv.style.direction = newDirection;
        if (newDirection === 'rtl') {
            editorDiv.parentElement.classList.add('is-rtl');
        }
        else {
            editorDiv.parentElement.classList.remove('is-rtl');
        }
    }
    setDocumentDirectionForReadingDiv(readingDiv, newDirection) {
        readingDiv.style.direction = newDirection;
        // Although Obsidian doesn't care about is-rtl in Markdown preview, we use it below for some more formatting
        if (newDirection === 'rtl')
            readingDiv.classList.add('is-rtl');
        else
            readingDiv.classList.remove('is-rtl');
        if (this.settings.setYamlDirection)
            this.replacePageStyleByString('Patch YAML', `/* Patch YAML RTL */ .is-rtl .language-yaml code { text-align: right; }`, true);
    }
    setExportDirection(newDirection) {
        this.replacePageStyleByString('searched and replaced', `/* This is searched and replaced by the plugin */ @media print { body { direction: ${newDirection}; } }`, false);
    }
    // Returns true if a replacement was made
    replacePageStyleByString(searchString, newStyle, addIfNotFound) {
        let alreadyExists = false;
        let style = this.findPageStyle(searchString);
        if (style) {
            if (style.getText() === searchString)
                alreadyExists = true;
            else
                style.setText(newStyle);
        }
        else if (addIfNotFound) {
            let style = document.createElement('style');
            style.textContent = newStyle;
            document.head.appendChild(style);
        }
        return style && !alreadyExists;
    }
    findPageStyle(regex) {
        let styles = document.head.getElementsByTagName('style');
        for (let style of styles) {
            if (style.getText().match(regex))
                return style;
        }
        return null;
    }
    toggleDocumentDirection() {
        let newDirection = this.getDocumentDirection() === 'ltr' ? 'rtl' : 'ltr';
        this.setDocumentDirection(newDirection);
        if (this.settings.rememberPerFile && this.currentFile && this.currentFile.path) {
            this.settings.fileDirections[this.currentFile.path] = newDirection;
            this.saveSettings();
        }
    }
    getDocumentDirection() {
        let view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
        if (!view)
            return 'unknown';
        const rtlEditors = view.contentEl.getElementsByClassName('is-rtl');
        if (rtlEditors.length > 0)
            return 'rtl';
        else
            return 'ltr';
    }
    getFrontMatterDirection(file) {
        const fileCache = this.app.metadataCache.getFileCache(file);
        const frontMatter = fileCache === null || fileCache === void 0 ? void 0 : fileCache.frontmatter;
        if (frontMatter && (frontMatter === null || frontMatter === void 0 ? void 0 : frontMatter.direction)) {
            try {
                const direction = frontMatter.direction;
                return direction;
            }
            catch (error) { }
        }
    }
    syncDefaultDirection() {
        // Sync the plugin default direction with Obsidian's own setting
        const obsidianDirection = this.app.vault.getConfig('rightToLeft') ? 'rtl' : 'ltr';
        if (obsidianDirection != this.settings.defaultDirection) {
            this.settings.defaultDirection = obsidianDirection;
            this.saveSettings();
        }
    }
}
class RtlSettingsTab extends obsidian.PluginSettingTab {
    constructor(app, plugin) {
        super(app, plugin);
        this.plugin = plugin;
        this.settings = plugin.settings;
    }
    display() {
        let { containerEl } = this;
        containerEl.empty();
        containerEl.createEl('h2', { text: 'RTL Settings' });
        this.plugin.syncDefaultDirection();
        new obsidian.Setting(containerEl)
            .setName('Remember text direction per file')
            .setDesc('Store and remember the text direction used for each file individually.')
            .addToggle(toggle => toggle.setValue(this.settings.rememberPerFile)
            .onChange((value) => {
            this.settings.rememberPerFile = value;
            this.plugin.saveSettings();
            this.plugin.adjustDirectionToCurrentFile();
        }));
        new obsidian.Setting(containerEl)
            .setName('Default text direction')
            .setDesc('What should be the default text direction in Obsidian?')
            .addDropdown(dropdown => dropdown.addOption('ltr', 'LTR')
            .addOption('rtl', 'RTL')
            .setValue(this.settings.defaultDirection)
            .onChange((value) => {
            this.settings.defaultDirection = value;
            this.app.vault.setConfig('rightToLeft', value == 'rtl');
            this.plugin.saveSettings();
            this.plugin.adjustDirectionToCurrentFile();
        }));
        new obsidian.Setting(containerEl)
            .setName('Set note title direction')
            .setDesc('In RTL notes, also set the direction of the note title.')
            .addToggle(toggle => toggle.setValue(this.settings.setNoteTitleDirection)
            .onChange((value) => {
            this.settings.setNoteTitleDirection = value;
            this.plugin.saveSettings();
            this.plugin.adjustDirectionToCurrentFile();
        }));
        new obsidian.Setting(containerEl)
            .setName('Set YAML direction in Preview')
            .setDesc('For RTL notes, preview YAML blocks as RTL. (When turning off, restart of Obsidian is required.)')
            .addToggle(toggle => {
            var _a;
            return toggle.setValue((_a = this.settings.setYamlDirection) !== null && _a !== void 0 ? _a : false)
                .onChange((value) => {
                this.settings.setYamlDirection = value;
                this.plugin.saveSettings();
                this.plugin.adjustDirectionToCurrentFile();
            });
        });
    }
}

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