'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.
***************************************************************************** */
/* global Reflect, Promise */

var extendStatics = function(d, b) {
    extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
    return extendStatics(d, b);
};

function __extends(d, b) {
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

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

function __generator(thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
}

CodeMirror.defineOption('showInvisibles', false, (cm, val, prev) => {
  let Count = 0;
  const Maximum = cm.getOption('maxInvisibles') || 16;
  if (prev === CodeMirror.Init)
    prev = false;
  if (prev && !val) {
    cm.removeOverlay('invisibles');
    return;
  }
  if (!prev && val) {
    //add(Maximum);
    cm.addOverlay({
      name: 'invisibles',
      token: function nextToken(stream) {
        let spaces = 0;
        let peek = stream.peek() === ' ';
        if (peek) {
          while (peek && spaces < Maximum) {
            ++spaces;
            stream.next();
            peek = stream.peek() === ' ';
          }
          let ret = 'whitespace whitespace-' + spaces;
          /*
           * styles should be different
           * could not be two same styles
           * beside because of this check in runmode
           * function in `codemirror.js`:
           *
           * 6624: if (!flattenSpans || curStyle != style) {}
           */
          if (spaces === Maximum)
            ret += ' whitespace-rand-' + Count++;
          return ret;
        }
        while (!stream.eol() && !peek) {
          stream.next();
          peek = stream.peek() === ' ';
        }
        return 'cm-eol';
      },
    });
  }
});

var DEFAULT_SETTINGS = {
    enabled: true,
    showNewline: true,
    showTab: true,
    showSpace: true,
    showSingleSpace: true,
    showTrailingSpace: true,
    showStrictLineBreak: false
};
var CMShowWhitespacePlugin = /** @class */ (function (_super) {
    __extends(CMShowWhitespacePlugin, _super);
    function CMShowWhitespacePlugin() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.disable = function () {
            document.body.classList.remove('plugin-cm-show-whitespace');
            // @ts-ignore
            _this.app.workspace.iterateCodeMirrors(function (cm) { return cm.setOption("showInvisibles", false); });
            _this.saveSettings({ enabled: false });
        };
        _this.enable = function () {
            document.body.classList.add('plugin-cm-show-whitespace');
            // @ts-ignore
            _this.registerCodeMirror(function (cm) { return cm.setOption("showInvisibles", true); });
            _this.saveSettings({ enabled: true });
        };
        _this.updateHiddenChars = function () {
            var _a = _this.settings, showNewline = _a.showNewline, showSingleSpace = _a.showSingleSpace, showSpace = _a.showSpace, showTab = _a.showTab, showTrailingSpace = _a.showTrailingSpace, showStrictLineBreak = _a.showStrictLineBreak;
            var classList = document.body.classList;
            classList.toggle('plugin-cm-show-whitespace-hide-newline', !showNewline);
            classList.toggle('plugin-cm-show-whitespace-hide-tab', !showTab);
            classList.toggle('plugin-cm-show-whitespace-hide-space', !showSpace);
            classList.toggle('plugin-cm-show-whitespace-hide-single-space', !showSingleSpace);
            classList.toggle('plugin-cm-show-whitespace-hide-trailing-space', !showTrailingSpace);
            classList.toggle('plugin-cm-show-whitespace-show-strict-line-break', showStrictLineBreak);
        };
        return _this;
    }
    CMShowWhitespacePlugin.prototype.onload = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.loadSettings()];
                    case 1:
                        _a.sent();
                        if (this.settings.enabled) {
                            this.app.workspace.layoutReady ? this.enable() : this.app.workspace.on('layout-ready', this.enable);
                        }
                        // add the toggle on/off command
                        this.addCommand({
                            id: 'toggle-show-whitespace',
                            name: 'Toggle On/Off',
                            callback: function () {
                                // disable or enable as necessary
                                _this.settings.enabled ? _this.disable() : _this.enable();
                            }
                        });
                        this.addSettingTab(new CMShowWhitespacePluginSettingTab(this.app, this));
                        return [2 /*return*/];
                }
            });
        });
    };
    CMShowWhitespacePlugin.prototype.onunload = function () {
        this.disable();
    };
    CMShowWhitespacePlugin.prototype.loadSettings = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, _b, _c, _d;
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0:
                        _a = this;
                        _c = (_b = Object).assign;
                        _d = [DEFAULT_SETTINGS];
                        return [4 /*yield*/, this.loadData()];
                    case 1:
                        _a.settings = _c.apply(_b, _d.concat([_e.sent()]));
                        return [2 /*return*/];
                }
            });
        });
    };
    CMShowWhitespacePlugin.prototype.saveSettings = function (newSettings) {
        if (newSettings === void 0) { newSettings = {}; }
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        this.settings = Object.assign(this.settings, newSettings);
                        return [4 /*yield*/, this.saveData(this.settings)];
                    case 1:
                        _a.sent();
                        this.updateHiddenChars();
                        return [2 /*return*/];
                }
            });
        });
    };
    return CMShowWhitespacePlugin;
}(obsidian.Plugin));
var CMShowWhitespacePluginSettingTab = /** @class */ (function (_super) {
    __extends(CMShowWhitespacePluginSettingTab, _super);
    function CMShowWhitespacePluginSettingTab(app, plugin) {
        var _this = _super.call(this, app, plugin) || this;
        _this.plugin = plugin;
        return _this;
    }
    CMShowWhitespacePluginSettingTab.prototype.display = function () {
        var _this = this;
        var _a = this, containerEl = _a.containerEl, settings = _a.plugin.settings;
        containerEl.empty();
        containerEl.classList.add('plugin-cm-show-whitespace-settings');
        new obsidian.Setting(containerEl)
            .setName("Toggle Show Whitespace")
            .setDesc("Turns show whitespace on or off globally")
            .addToggle(function (toggle) {
            return toggle.setValue(_this.plugin.settings.enabled)
                .onChange(function (newValue) { newValue ? _this.plugin.enable() : _this.plugin.disable(); });
        });
        // ---
        new obsidian.Setting(containerEl).setHeading().setName('Spaces');
        // ---
        new obsidian.Setting(containerEl)
            .setName('Show space characters')
            .setDesc('Show or hide the space character. Note: This will also hide single space characters.')
            .addToggle(function (toggle) {
            return toggle.setValue(_this.plugin.settings.showSpace).onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.plugin.saveSettings({ showSpace: value, showSingleSpace: value })];
                        case 1:
                            _a.sent();
                            this.display();
                            return [2 /*return*/];
                    }
                });
            }); });
        });
        var singleSpaceSetting = new obsidian.Setting(containerEl)
            .setName('Show single space characters')
            .setDesc('Show or hide single space characters')
            .addToggle(function (toggle) {
            toggle.setValue(_this.plugin.settings.showSingleSpace).onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.plugin.saveSettings({ showSingleSpace: value })];
                        case 1:
                            _a.sent();
                            return [2 /*return*/];
                    }
                });
            }); });
        });
        if (!settings.showSpace) {
            // if general spaces are off it doesn't make sense to change the setting
            // to show or hide single spaces between words
            singleSpaceSetting.setClass('plugin-cm-show-whitespace-disabled');
        }
        new obsidian.Setting(containerEl)
            .setName('Show trailing space characters')
            .setDesc('Show or hide trailing space characters')
            .addToggle(function (toggle) {
            return toggle.setValue(_this.plugin.settings.showTrailingSpace).onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.plugin.saveSettings({ showTrailingSpace: value })];
                        case 1:
                            _a.sent();
                            return [2 /*return*/];
                    }
                });
            }); });
        });
        // ---
        new obsidian.Setting(containerEl).setHeading().setName('Other whitespace characters');
        // ---
        new obsidian.Setting(containerEl)
            .setName('Show newline characters')
            .setDesc('Show or hide the newline character')
            .addToggle(function (toggle) {
            return toggle.setValue(_this.plugin.settings.showNewline).onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.plugin.saveSettings({ showNewline: value })];
                        case 1:
                            _a.sent();
                            return [2 /*return*/];
                    }
                });
            }); });
        });
        new obsidian.Setting(containerEl)
            .setName('Show strict line break characters')
            .setDesc('Show or hide a different character for strict line breaks (two spaces followed by new line)')
            .addToggle(function (toggle) {
            return toggle.setValue(_this.plugin.settings.showStrictLineBreak).onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.plugin.saveSettings({ showStrictLineBreak: value })];
                        case 1:
                            _a.sent();
                            return [2 /*return*/];
                    }
                });
            }); });
        });
        new obsidian.Setting(containerEl)
            .setName('Show tab characters')
            .setDesc('Show or hide the tab character')
            .addToggle(function (toggle) {
            return toggle.setValue(_this.plugin.settings.showTab).onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.plugin.saveSettings({ showTab: value })];
                        case 1:
                            _a.sent();
                            return [2 /*return*/];
                    }
                });
            }); });
        });
    };
    return CMShowWhitespacePluginSettingTab;
}(obsidian.PluginSettingTab));

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