/*
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');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var obsidian__default = /*#__PURE__*/_interopDefaultLegacy(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());
    });
}

typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};

const DEFAULT_DAILY_NOTE_FORMAT = "YYYY-MM-DD";
const DEFAULT_WEEKLY_NOTE_FORMAT = "gggg-[W]ww";
const DEFAULT_MONTHLY_NOTE_FORMAT = "YYYY-MM";
const DEFAULT_QUARTERLY_NOTE_FORMAT = "YYYY-[Q]Q";
const DEFAULT_YEARLY_NOTE_FORMAT = "YYYY";

function shouldUsePeriodicNotesSettings(periodicity) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const periodicNotes = window.app.plugins.getPlugin("periodic-notes");
    return periodicNotes && periodicNotes.settings?.[periodicity]?.enabled;
}
/**
 * Read the user settings for the `daily-notes` plugin
 * to keep behavior of creating a new note in-sync.
 */
function getDailyNoteSettings() {
    try {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const { internalPlugins, plugins } = window.app;
        if (shouldUsePeriodicNotesSettings("daily")) {
            const { format, folder, template } = plugins.getPlugin("periodic-notes")?.settings?.daily || {};
            return {
                format: format || DEFAULT_DAILY_NOTE_FORMAT,
                folder: folder?.trim() || "",
                template: template?.trim() || "",
            };
        }
        const { folder, format, template } = internalPlugins.getPluginById("daily-notes")?.instance?.options || {};
        return {
            format: format || DEFAULT_DAILY_NOTE_FORMAT,
            folder: folder?.trim() || "",
            template: template?.trim() || "",
        };
    }
    catch (err) {
        console.info("No custom daily note settings found!", err);
    }
}
/**
 * Read the user settings for the `weekly-notes` plugin
 * to keep behavior of creating a new note in-sync.
 */
function getWeeklyNoteSettings() {
    try {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const pluginManager = window.app.plugins;
        const calendarSettings = pluginManager.getPlugin("calendar")?.options;
        const periodicNotesSettings = pluginManager.getPlugin("periodic-notes")?.settings?.weekly;
        if (shouldUsePeriodicNotesSettings("weekly")) {
            return {
                format: periodicNotesSettings.format || DEFAULT_WEEKLY_NOTE_FORMAT,
                folder: periodicNotesSettings.folder?.trim() || "",
                template: periodicNotesSettings.template?.trim() || "",
            };
        }
        const settings = calendarSettings || {};
        return {
            format: settings.weeklyNoteFormat || DEFAULT_WEEKLY_NOTE_FORMAT,
            folder: settings.weeklyNoteFolder?.trim() || "",
            template: settings.weeklyNoteTemplate?.trim() || "",
        };
    }
    catch (err) {
        console.info("No custom weekly note settings found!", err);
    }
}
/**
 * Read the user settings for the `periodic-notes` plugin
 * to keep behavior of creating a new note in-sync.
 */
function getMonthlyNoteSettings() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const pluginManager = window.app.plugins;
    try {
        const settings = (shouldUsePeriodicNotesSettings("monthly") &&
            pluginManager.getPlugin("periodic-notes")?.settings?.monthly) ||
            {};
        return {
            format: settings.format || DEFAULT_MONTHLY_NOTE_FORMAT,
            folder: settings.folder?.trim() || "",
            template: settings.template?.trim() || "",
        };
    }
    catch (err) {
        console.info("No custom monthly note settings found!", err);
    }
}
/**
 * Read the user settings for the `periodic-notes` plugin
 * to keep behavior of creating a new note in-sync.
 */
function getQuarterlyNoteSettings() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const pluginManager = window.app.plugins;
    try {
        const settings = (shouldUsePeriodicNotesSettings("quarterly") &&
            pluginManager.getPlugin("periodic-notes")?.settings?.quarterly) ||
            {};
        return {
            format: settings.format || DEFAULT_QUARTERLY_NOTE_FORMAT,
            folder: settings.folder?.trim() || "",
            template: settings.template?.trim() || "",
        };
    }
    catch (err) {
        console.info("No custom quarterly note settings found!", err);
    }
}
/**
 * Read the user settings for the `periodic-notes` plugin
 * to keep behavior of creating a new note in-sync.
 */
function getYearlyNoteSettings() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const pluginManager = window.app.plugins;
    try {
        const settings = (shouldUsePeriodicNotesSettings("yearly") &&
            pluginManager.getPlugin("periodic-notes")?.settings?.yearly) ||
            {};
        return {
            format: settings.format || DEFAULT_YEARLY_NOTE_FORMAT,
            folder: settings.folder?.trim() || "",
            template: settings.template?.trim() || "",
        };
    }
    catch (err) {
        console.info("No custom yearly note settings found!", err);
    }
}

// Credit: @creationix/path.js
function join(...partSegments) {
    // Split the inputs into a list of path commands.
    let parts = [];
    for (let i = 0, l = partSegments.length; i < l; i++) {
        parts = parts.concat(partSegments[i].split("/"));
    }
    // Interpret the path commands to get the new resolved path.
    const newParts = [];
    for (let i = 0, l = parts.length; i < l; i++) {
        const part = parts[i];
        // Remove leading and trailing slashes
        // Also remove "." segments
        if (!part || part === ".")
            continue;
        // Push new path segments.
        else
            newParts.push(part);
    }
    // Preserve the initial slash if there was one.
    if (parts[0] === "")
        newParts.unshift("");
    // Turn back into a single string path.
    return newParts.join("/");
}
async function ensureFolderExists(path) {
    const dirs = path.replace(/\\/g, "/").split("/");
    dirs.pop(); // remove basename
    if (dirs.length) {
        const dir = join(...dirs);
        if (!window.app.vault.getAbstractFileByPath(dir)) {
            await window.app.vault.createFolder(dir);
        }
    }
}
async function getNotePath(directory, filename) {
    if (!filename.endsWith(".md")) {
        filename += ".md";
    }
    const path = obsidian__default["default"].normalizePath(join(directory, filename));
    await ensureFolderExists(path);
    return path;
}
async function getTemplateInfo(template) {
    const { metadataCache, vault } = window.app;
    const templatePath = obsidian__default["default"].normalizePath(template);
    if (templatePath === "/") {
        return Promise.resolve(["", null]);
    }
    try {
        const templateFile = metadataCache.getFirstLinkpathDest(templatePath, "");
        const contents = await vault.cachedRead(templateFile);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const IFoldInfo = window.app.foldManager.load(templateFile);
        return [contents, IFoldInfo];
    }
    catch (err) {
        console.error(`Failed to read the daily note template '${templatePath}'`, err);
        new obsidian__default["default"].Notice("Failed to read the daily note template");
        return ["", null];
    }
}

/**
 * dateUID is a way of weekly identifying daily/weekly/monthly notes.
 * They are prefixed with the granularity to avoid ambiguity.
 */
function getDateUID(date, granularity = "day") {
    const ts = date.clone().startOf(granularity).format();
    return `${granularity}-${ts}`;
}
function removeEscapedCharacters(format) {
    return format.replace(/\[[^\]]*\]/g, ""); // remove everything within brackets
}
/**
 * XXX: When parsing dates that contain both week numbers and months,
 * Moment choses to ignore the week numbers. For the week dateUID, we
 * want the opposite behavior. Strip the MMM from the format to patch.
 */
function isFormatAmbiguous(format, granularity) {
    if (granularity === "week") {
        const cleanFormat = removeEscapedCharacters(format);
        return (/w{1,2}/i.test(cleanFormat) &&
            (/M{1,4}/.test(cleanFormat) || /D{1,4}/.test(cleanFormat)));
    }
    return false;
}
function getDateFromFile(file, granularity) {
    return getDateFromFilename(file.basename, granularity);
}
function getDateFromFilename(filename, granularity) {
    const getSettings = {
        day: getDailyNoteSettings,
        week: getWeeklyNoteSettings,
        month: getMonthlyNoteSettings,
        quarter: getQuarterlyNoteSettings,
        year: getYearlyNoteSettings,
    };
    const format = getSettings[granularity]().format.split("/").pop();
    const noteDate = window.moment(filename, format, true);
    if (!noteDate.isValid()) {
        return null;
    }
    if (isFormatAmbiguous(format, granularity)) {
        if (granularity === "week") {
            const cleanFormat = removeEscapedCharacters(format);
            if (/w{1,2}/i.test(cleanFormat)) {
                return window.moment(filename, 
                // If format contains week, remove day & month formatting
                format.replace(/M{1,4}/g, "").replace(/D{1,4}/g, ""), false);
            }
        }
    }
    return noteDate;
}

class DailyNotesFolderMissingError extends Error {
}
/**
 * This function mimics the behavior of the daily-notes plugin
 * so it will replace {{date}}, {{title}}, and {{time}} with the
 * formatted timestamp.
 *
 * Note: it has an added bonus that it's not 'today' specific.
 */
async function createDailyNote(date) {
    const app = window.app;
    const { vault } = app;
    const moment = window.moment;
    const { template, format, folder } = getDailyNoteSettings();
    const [templateContents, IFoldInfo] = await getTemplateInfo(template);
    const filename = date.format(format);
    const normalizedPath = await getNotePath(folder, filename);
    try {
        const createdFile = await vault.create(normalizedPath, templateContents
            .replace(/{{\s*date\s*}}/gi, filename)
            .replace(/{{\s*time\s*}}/gi, moment().format("HH:mm"))
            .replace(/{{\s*title\s*}}/gi, filename)
            .replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi, (_, _timeOrDate, calc, timeDelta, unit, momentFormat) => {
            const now = moment();
            const currentDate = date.clone().set({
                hour: now.get("hour"),
                minute: now.get("minute"),
                second: now.get("second"),
            });
            if (calc) {
                currentDate.add(parseInt(timeDelta, 10), unit);
            }
            if (momentFormat) {
                return currentDate.format(momentFormat.substring(1).trim());
            }
            return currentDate.format(format);
        })
            .replace(/{{\s*yesterday\s*}}/gi, date.clone().subtract(1, "day").format(format))
            .replace(/{{\s*tomorrow\s*}}/gi, date.clone().add(1, "d").format(format)));
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        app.foldManager.save(createdFile, IFoldInfo);
        return createdFile;
    }
    catch (err) {
        console.error(`Failed to create file: '${normalizedPath}'`, err);
        new obsidian__default["default"].Notice("Unable to create new file.");
    }
}
function getDailyNote(date, dailyNotes) {
    return dailyNotes[getDateUID(date, "day")] ?? null;
}
function getAllDailyNotes() {
    /**
     * Find all daily notes in the daily note folder
     */
    const { vault } = window.app;
    const { folder } = getDailyNoteSettings();
    const dailyNotesFolder = vault.getAbstractFileByPath(obsidian__default["default"].normalizePath(folder));
    if (!dailyNotesFolder) {
        throw new DailyNotesFolderMissingError("Failed to find daily notes folder");
    }
    const dailyNotes = {};
    obsidian__default["default"].Vault.recurseChildren(dailyNotesFolder, (note) => {
        if (note instanceof obsidian__default["default"].TFile) {
            const date = getDateFromFile(note, "day");
            if (date) {
                const dateString = getDateUID(date, "day");
                dailyNotes[dateString] = note;
            }
        }
    });
    return dailyNotes;
}

function appHasDailyNotesPluginLoaded() {
    const { app } = window;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const dailyNotesPlugin = app.internalPlugins.plugins["daily-notes"];
    if (dailyNotesPlugin && dailyNotesPlugin.enabled) {
        return true;
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const periodicNotes = app.plugins.getPlugin("periodic-notes");
    return periodicNotes && periodicNotes.settings?.daily?.enabled;
}
var appHasDailyNotesPluginLoaded_1 = appHasDailyNotesPluginLoaded;
var createDailyNote_1 = createDailyNote;
var getAllDailyNotes_1 = getAllDailyNotes;
var getDailyNote_1 = getDailyNote;
var getDailyNoteSettings_1 = getDailyNoteSettings;

const notificationUrl = 'data:audio/ogg;base64,[encoded data, 16236 characters]';
const whiteNoiseUrl = 'data:audio/mpeg;base64,[encoded data, 952944 characters]';

class WhiteNoise {
    constructor(plugin, whiteNoiseUrl) {
        this.plugin = plugin;
        this.whiteNoisePlayer = new Audio(whiteNoiseUrl);
        this.whiteNoisePlayer.loop = true;
    }
    stopWhiteNoise() {
        this.whiteNoisePlayer.pause();
        this.whiteNoisePlayer.currentTime = 0;
    }
    whiteNoise() {
        if (this.plugin.timer.mode === 0 /* Mode.Pomo */ && this.plugin.timer.paused === false) {
            this.whiteNoisePlayer.play();
        }
        else {
            this.stopWhiteNoise();
        }
    }
}

const DEFAULT_SETTINGS = {
    pomo: 25,
    shortBreak: 5,
    longBreak: 15,
    longBreakInterval: 4,
    autostartTimer: true,
    numAutoCycles: 0,
    ribbonIcon: true,
    emoji: true,
    notificationSound: true,
    useSystemNotification: false,
    backgroundNoiseFile: "",
    logging: false,
    logFile: "Pomodoro Log.md",
    logToDaily: false,
    logText: "[🍅] dddd, MMMM DD YYYY, h:mm A",
    logActiveNote: false,
    fancyStatusBar: false,
    whiteNoise: false,
};
class PomoSettingTab extends obsidian.PluginSettingTab {
    constructor(app, plugin) {
        super(app, plugin);
        this.plugin = plugin;
    }
    display() {
        let { containerEl } = this;
        containerEl.empty();
        containerEl.createEl('h2', { text: 'Timer' });
        /**************  Timer settings **************/
        new obsidian.Setting(containerEl)
            .setName("Pomodoro time (minutes)")
            .setDesc("Leave blank for default")
            .addText(text => text
            .setValue(this.plugin.settings.pomo.toString())
            .onChange(value => {
            this.plugin.settings.pomo = setNumericValue(value, DEFAULT_SETTINGS.pomo, this.plugin.settings.pomo);
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("Short break time (minutes)")
            .setDesc("Leave blank for default")
            .addText(text => text
            .setValue(this.plugin.settings.shortBreak.toString())
            .onChange(value => {
            this.plugin.settings.shortBreak = setNumericValue(value, DEFAULT_SETTINGS.shortBreak, this.plugin.settings.shortBreak);
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("Long break time (minutes)")
            .setDesc("Leave blank for default")
            .addText(text => text
            .setValue(this.plugin.settings.longBreak.toString())
            .onChange(value => {
            this.plugin.settings.longBreak = setNumericValue(value, DEFAULT_SETTINGS.longBreak, this.plugin.settings.longBreak);
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("Long break interval")
            .setDesc("Number of pomos before a long break; leave blank for default")
            .addText(text => text
            .setValue(this.plugin.settings.longBreakInterval.toString())
            .onChange(value => {
            this.plugin.settings.longBreakInterval = setNumericValue(value, DEFAULT_SETTINGS.longBreakInterval, this.plugin.settings.longBreakInterval);
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("Autostart timer")
            .setDesc("Start each pomodoro and break automatically. When off, click the sidebar icon on the left or use the toggle pause command to start the next timer")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.autostartTimer)
            .onChange(value => {
            this.plugin.settings.autostartTimer = value;
            this.plugin.saveSettings();
            this.display(); //force refresh
        }));
        if (this.plugin.settings.autostartTimer === false) {
            new obsidian.Setting(containerEl)
                .setName("Cycles before pause")
                .setDesc("Number of pomodoro + break cycles to run automatically before stopping. Default is 0 (stops after every pomodoro and every break)")
                .addText(text => text
                .setValue(this.plugin.settings.numAutoCycles.toString())
                .onChange(value => {
                this.plugin.settings.numAutoCycles = setNumericValue(value, DEFAULT_SETTINGS.numAutoCycles, this.plugin.settings.numAutoCycles);
                this.plugin.timer.cyclesSinceLastAutoStop = 0;
                this.plugin.saveSettings();
            }));
        }
        /************** Appearance ************************/
        containerEl.createEl("h2", { text: "Appearance" });
        new obsidian.Setting(containerEl)
            .setName("Sidebar icon")
            .setDesc("Toggle left sidebar icon. Restart Obsidian for the change to take effect")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.ribbonIcon)
            .onChange(value => {
            this.plugin.settings.ribbonIcon = value;
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("Timer emoji")
            .setDesc("Toggle 🏖️/🍅 emoji that indicate whether a timer is a pomodoro or a break.")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.emoji)
            .onChange(value => {
            this.plugin.settings.emoji = value;
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("System notification")
            .setDesc("Use system notifications at the end of each pomodoro and break")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.useSystemNotification)
            .onChange(value => {
            this.plugin.settings.useSystemNotification = value;
            this.plugin.saveSettings();
        }));
        /**************  Sound settings **************/
        containerEl.createEl("h2", { text: "Sound" });
        new obsidian.Setting(containerEl)
            .setName("Notification sound")
            .setDesc("Play notification sound at the end of each pomodoro and break")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.notificationSound)
            .onChange(value => {
            this.plugin.settings.notificationSound = value;
            this.plugin.saveSettings();
        }));
        new obsidian.Setting(containerEl)
            .setName("White noise")
            .setDesc("Play white noise while timer is active")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.whiteNoise)
            .onChange(value => {
            this.plugin.settings.whiteNoise = value;
            this.plugin.saveSettings();
            if (this.plugin.settings.whiteNoise === true) {
                this.plugin.timer.whiteNoisePlayer = new WhiteNoise(this.plugin, whiteNoiseUrl);
                this.plugin.timer.whiteNoisePlayer.whiteNoise();
            }
            else { //if false, turn it off immediately
                this.plugin.timer.whiteNoisePlayer.stopWhiteNoise();
            }
            this.display();
        }));
        /**************  Logging settings **************/
        containerEl.createEl("h2", { text: "Logging" });
        new obsidian.Setting(containerEl)
            .setName("Logging")
            .setDesc("Enable a log of completed pomodoros")
            .addToggle(toggle => toggle
            .setValue(this.plugin.settings.logging)
            .onChange(value => {
            this.plugin.settings.logging = value;
            if (value === true) {
                this.plugin.openLogFileOnClick();
            }
            else {
                this.plugin.statusBar.removeClass("statusbar-pomo-logging");
            }
            this.plugin.saveSettings();
            this.display(); //force refresh
        }));
        //various logging settings; only show if logging is enabled (currently does not autohide, only)
        if (this.plugin.settings.logging === true) {
            new obsidian.Setting(containerEl)
                .setName("Log file")
                .setDesc("If file doesn't already exist, it will be created")
                .addText(text => text
                .setValue(this.plugin.settings.logFile.toString())
                .onChange(value => {
                this.plugin.settings.logFile = value;
                this.plugin.saveSettings();
            }));
            new obsidian.Setting(containerEl)
                .setName("Log to daily note")
                .setDesc("Logs to the end of today's daily note")
                .addToggle(toggle => toggle
                .setValue(this.plugin.settings.logToDaily)
                .onChange(value => {
                if (appHasDailyNotesPluginLoaded_1() === true) {
                    this.plugin.settings.logToDaily = value;
                }
                else if (value === true) {
                    this.plugin.settings.logToDaily = false;
                    new obsidian.Notice("Please enable daily notes plugin");
                }
                this.plugin.saveSettings();
            }));
            new obsidian.Setting(containerEl)
                .setName("Timestamp Format")
                .setDesc("Specify format for the logtext using moment syntax")
                .addMomentFormat(text => text
                .setDefaultFormat(this.plugin.settings.logText)
                .setValue(this.plugin.settings.logText)
                .onChange(value => {
                this.plugin.settings.logText = value;
                this.plugin.saveSettings();
            }));
            new obsidian.Setting(containerEl)
                .setName("Log active note")
                .setDesc("In log, append link pointing to the note that was active when you started the pomodoro")
                .addToggle(toggle => toggle
                .setValue(this.plugin.settings.logActiveNote)
                .onChange(value => {
                this.plugin.settings.logActiveNote = value;
                this.plugin.saveSettings();
            }));
        }
    }
}
//sets the setting for the given to value if it's a valid, default if empty, otherwise sends user error notice
function setNumericValue(value, defaultSetting, currentSetting) {
    if (value === '') { //empty string -> reset to default
        return defaultSetting;
    }
    else if (!isNaN(Number(value)) && (Number(value) > 0)) { //if positive number, set setting
        return Number(value);
    }
    else { //invalid input
        new obsidian.Notice("Please specify a valid number.");
        return currentSetting;
    }
}

const electron = require("electron");
const MILLISECS_IN_MINUTE = 60 * 1000;
class Timer {
    constructor(plugin) {
        this.plugin = plugin;
        this.mode = 3 /* Mode.NoTimer */;
        this.paused = false;
        this.pomosSinceStart = 0;
        this.cyclesSinceLastAutoStop = 0;
        if (this.plugin.settings.whiteNoise === true) {
            this.whiteNoisePlayer = new WhiteNoise(plugin, whiteNoiseUrl);
        }
    }
    onRibbonIconClick() {
        if (this.mode === 3 /* Mode.NoTimer */) { //if starting from not having a timer running/paused
            this.startTimer(0 /* Mode.Pomo */);
        }
        else { //if timer exists, pause or unpause
            this.togglePause();
        }
    }
    /*Set status bar to remaining time or empty string if no timer is running*/
    //handling switching logic here, should spin out
    setStatusBarText() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.mode !== 3 /* Mode.NoTimer */) {
                let timer_type_symbol = "";
                if (this.plugin.settings.emoji === true) {
                    timer_type_symbol = "🏖️ ";
                    if (this.mode === 0 /* Mode.Pomo */) {
                        timer_type_symbol = "🍅 ";
                    }
                }
                if (this.paused === true) {
                    return timer_type_symbol + millisecsToString(this.pausedTime); //just show the paused time
                }
                else if (obsidian.moment().isSameOrAfter(this.endTime)) {
                    yield this.handleTimerEnd();
                }
                return timer_type_symbol + millisecsToString(this.getCountdown()); //return display value
            }
            else {
                return ""; //fixes TypeError: failed to execute 'appendChild' on 'Node https://github.com/kzhovn/statusbar-pomo-obsidian/issues/4
            }
        });
    }
    handleTimerEnd() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.mode === 0 /* Mode.Pomo */) { //completed another pomo
                this.pomosSinceStart += 1;
                if (this.plugin.settings.logging === true) {
                    yield this.logPomo();
                }
            }
            else if (this.mode === 1 /* Mode.ShortBreak */ || this.mode === 2 /* Mode.LongBreak */) {
                this.cyclesSinceLastAutoStop += 1;
            }
            //switch mode
            if (this.plugin.settings.notificationSound === true) { //play sound end of timer
                playNotification();
            }
            if (this.plugin.settings.useSystemNotification === true) { //show system notification end of timer
                showSystemNotification(this.mode, this.plugin.settings.emoji);
            }
            if (this.plugin.settings.autostartTimer === false && this.plugin.settings.numAutoCycles <= this.cyclesSinceLastAutoStop) { //if autostart disabled, pause and allow user to start manually
                this.setupTimer();
                this.autoPaused = true;
                this.paused = true;
                this.pausedTime = this.getTotalModeMillisecs();
                this.cyclesSinceLastAutoStop = 0;
            }
            else {
                this.startTimer();
            }
        });
    }
    quitTimer() {
        return __awaiter(this, void 0, void 0, function* () {
            this.mode = 3 /* Mode.NoTimer */;
            this.startTime = obsidian.moment(0);
            this.endTime = obsidian.moment(0);
            this.paused = false;
            this.pomosSinceStart = 0;
            if (this.plugin.settings.whiteNoise === true) {
                this.whiteNoisePlayer.stopWhiteNoise();
            }
            yield this.plugin.loadSettings(); //why am I loading settings on quit? to ensure that when I restart everything is correct? seems weird
        });
    }
    pauseTimer() {
        this.paused = true;
        this.pausedTime = this.getCountdown();
        if (this.plugin.settings.whiteNoise === true) {
            this.whiteNoisePlayer.stopWhiteNoise();
        }
    }
    togglePause() {
        if (this.paused === true) {
            this.restartTimer();
        }
        else if (this.mode !== 3 /* Mode.NoTimer */) { //if some timer running
            this.pauseTimer();
            new obsidian.Notice("Timer paused.");
        }
    }
    restartTimer() {
        if (this.plugin.settings.logActiveNote === true && this.autoPaused === true) {
            this.setLogFile();
            this.autoPaused = false;
        }
        this.setStartAndEndTime(this.pausedTime);
        this.modeRestartingNotification();
        this.paused = false;
        if (this.plugin.settings.whiteNoise === true) {
            this.whiteNoisePlayer.whiteNoise();
        }
    }
    startTimer(mode = null) {
        this.setupTimer(mode);
        this.paused = false; //do I need this?
        if (this.plugin.settings.logActiveNote === true) {
            this.setLogFile();
        }
        this.modeStartingNotification();
        if (this.plugin.settings.whiteNoise === true) {
            this.whiteNoisePlayer.whiteNoise();
        }
    }
    setupTimer(mode = null) {
        if (mode === null) { //no arg -> start next mode in cycle
            if (this.mode === 0 /* Mode.Pomo */) {
                if (this.pomosSinceStart % this.plugin.settings.longBreakInterval === 0) {
                    this.mode = 2 /* Mode.LongBreak */;
                }
                else {
                    this.mode = 1 /* Mode.ShortBreak */;
                }
            }
            else { //short break, long break, or no timer
                this.mode = 0 /* Mode.Pomo */;
            }
        }
        else { //starting a specific mode passed to func
            this.mode = mode;
        }
        this.setStartAndEndTime(this.getTotalModeMillisecs());
    }
    setStartAndEndTime(millisecsLeft) {
        this.startTime = obsidian.moment(); //start time to current time
        this.endTime = obsidian.moment().add(millisecsLeft, 'milliseconds');
    }
    /*Return milliseconds left until end of timer*/
    getCountdown() {
        let endTimeClone = this.endTime.clone(); //rewrite with freeze?
        return endTimeClone.diff(obsidian.moment());
    }
    getTotalModeMillisecs() {
        switch (this.mode) {
            case 0 /* Mode.Pomo */: {
                return this.plugin.settings.pomo * MILLISECS_IN_MINUTE;
            }
            case 1 /* Mode.ShortBreak */: {
                return this.plugin.settings.shortBreak * MILLISECS_IN_MINUTE;
            }
            case 2 /* Mode.LongBreak */: {
                return this.plugin.settings.longBreak * MILLISECS_IN_MINUTE;
            }
            case 3 /* Mode.NoTimer */: {
                throw new Error("Mode NoTimer does not have an associated time value");
            }
        }
    }
    /**************  Notifications  **************/
    /*Sends notification corresponding to whatever the mode is at the moment it's called*/
    modeStartingNotification() {
        let time = this.getTotalModeMillisecs();
        let unit;
        if (time >= MILLISECS_IN_MINUTE) { /*display in minutes*/
            time = Math.floor(time / MILLISECS_IN_MINUTE);
            unit = 'minute';
        }
        else { /*less than a minute, display in seconds*/
            time = Math.floor(time / 1000); //convert to secs
            unit = 'second';
        }
        switch (this.mode) {
            case (0 /* Mode.Pomo */): {
                new obsidian.Notice(`Starting ${time} ${unit} pomodoro.`);
                break;
            }
            case (1 /* Mode.ShortBreak */):
            case (2 /* Mode.LongBreak */): {
                new obsidian.Notice(`Starting ${time} ${unit} break.`);
                break;
            }
            case (3 /* Mode.NoTimer */): {
                new obsidian.Notice('Quitting pomodoro timer.');
                break;
            }
        }
    }
    modeRestartingNotification() {
        switch (this.mode) {
            case (0 /* Mode.Pomo */): {
                new obsidian.Notice(`Restarting pomodoro.`);
                break;
            }
            case (1 /* Mode.ShortBreak */):
            case (2 /* Mode.LongBreak */): {
                new obsidian.Notice(`Restarting break.`);
                break;
            }
        }
    }
    /**************  Logging  **************/
    logPomo() {
        return __awaiter(this, void 0, void 0, function* () {
            var logText = obsidian.moment().format(this.plugin.settings.logText);
            const logFilePlaceholder = "{{logFile}}";
            if (this.plugin.settings.logActiveNote === true) {
                let linkText = this.plugin.app.fileManager.generateMarkdownLink(this.activeNote, '');
                if (logText.includes(logFilePlaceholder)) {
                    logText = logText.replace(logFilePlaceholder, linkText);
                }
                else {
                    logText = logText + " " + linkText;
                }
                logText = logText.replace(String.raw `\n`, "\n");
            }
            if (this.plugin.settings.logToDaily === true) { //use today's note
                let file = (yield this.plugin.getDailyNoteFile()).path;
                yield this.appendFile(file, logText);
            }
            else { //use file given in settings
                let file = this.plugin.app.vault.getAbstractFileByPath(this.plugin.settings.logFile);
                if (!file || file instanceof obsidian.TFolder) { //if no file, create
                    console.log("Creating pomodoro log file");
                    yield this.plugin.app.vault.create(this.plugin.settings.logFile, "");
                }
                yield this.appendFile(this.plugin.settings.logFile, logText);
            }
        });
    }
    //from Note Refactor plugin by James Lynch, https://github.com/lynchjames/note-refactor-obsidian/blob/80c1a23a1352b5d22c70f1b1d915b4e0a1b2b33f/src/obsidian-file.ts#L69
    appendFile(filePath, logText) {
        return __awaiter(this, void 0, void 0, function* () {
            let existingContent = yield this.plugin.app.vault.adapter.read(filePath);
            if (existingContent.length > 0) {
                existingContent = existingContent + '\r';
            }
            yield this.plugin.app.vault.adapter.write(filePath, existingContent + logText);
        });
    }
    setLogFile() {
        const activeView = this.plugin.app.workspace.getActiveFile();
        if (activeView) {
            this.activeNote = activeView;
        }
    }
}
/*Returns [HH:]mm:ss left on the current timer*/
function millisecsToString(millisecs) {
    let formattedCountDown;
    if (millisecs >= 60 * 60 * 1000) { /* >= 1 hour*/
        formattedCountDown = obsidian.moment.utc(millisecs).format('HH:mm:ss');
    }
    else {
        formattedCountDown = obsidian.moment.utc(millisecs).format('mm:ss');
    }
    return formattedCountDown.toString();
}
function playNotification() {
    const audio = new Audio(notificationUrl);
    audio.play();
}
function showSystemNotification(mode, useEmoji) {
    let text = "";
    switch (mode) {
        case (0 /* Mode.Pomo */): {
            let emoji = useEmoji ? "🏖" : "";
            text = `End of the pomodoro, time to take a break ${emoji}`;
            break;
        }
        case (1 /* Mode.ShortBreak */):
        case (2 /* Mode.LongBreak */): {
            let emoji = useEmoji ? "🍅" : "";
            text = `End of the break, time for the next pomodoro ${emoji}`;
            break;
        }
        case (3 /* Mode.NoTimer */): {
            // no system notification needed
            return;
        }
    }
    let emoji = useEmoji ? "🍅" : "";
    let title = `Obsidian Pomodoro ${emoji}`;
    // Show system notification
    const Notification = electron.remote.Notification;
    const n = new Notification({
        title: title,
        body: text,
        silent: true
    });
    n.on("click", () => {
        n.close();
    });
    n.show();
}

class PomoTimerPlugin extends obsidian.Plugin {
    onload() {
        return __awaiter(this, void 0, void 0, function* () {
            console.log('Loading status bar pomodoro timer');
            yield this.loadSettings();
            this.addSettingTab(new PomoSettingTab(this.app, this));
            this.statusBar = this.addStatusBarItem();
            this.statusBar.addClass("statusbar-pomo");
            if (this.settings.logging === true) {
                this.openLogFileOnClick();
            }
            this.timer = new Timer(this);
            /*Adds icon to the left side bar which starts the pomo timer when clicked
              if no timer is currently running, and otherwise quits current timer*/
            if (this.settings.ribbonIcon === true) {
                this.addRibbonIcon('clock', 'Start pomodoro', () => __awaiter(this, void 0, void 0, function* () {
                    this.timer.onRibbonIconClick();
                }));
            }
            /*Update status bar timer ever half second
              Ideally should change so only updating when in timer mode
              - regular conditional doesn't remove after quit, need unload*/
            this.registerInterval(window.setInterval(() => __awaiter(this, void 0, void 0, function* () { return this.statusBar.setText(yield this.timer.setStatusBarText()); }), 500));
            this.addCommand({
                id: 'start-satusbar-pomo',
                name: 'Start pomodoro',
                icon: 'play',
                checkCallback: (checking) => {
                    let leaf = this.app.workspace.activeLeaf;
                    if (leaf) {
                        if (!checking) {
                            this.timer.startTimer(0 /* Mode.Pomo */);
                        }
                        return true;
                    }
                    return false;
                }
            });
            this.addCommand({
                id: 'pause-satusbar-pomo',
                name: 'Toggle timer pause',
                icon: 'pause',
                checkCallback: (checking) => {
                    let leaf = this.app.workspace.activeLeaf;
                    if (leaf && this.timer.mode !== 3 /* Mode.NoTimer */) {
                        if (!checking) {
                            this.timer.togglePause();
                        }
                        return true;
                    }
                    return false;
                }
            });
            this.addCommand({
                id: 'quit-satusbar-pomo',
                name: 'Quit timer',
                icon: 'quit',
                checkCallback: (checking) => {
                    let leaf = this.app.workspace.activeLeaf;
                    if (leaf && this.timer.mode !== 3 /* Mode.NoTimer */) {
                        if (!checking) {
                            this.timer.quitTimer();
                        }
                        return true;
                    }
                    return false;
                }
            });
        });
    }
    //on click, open log file; from Day Planner https://github.com/lynchjames/obsidian-day-planner/blob/c8d4d33af294bde4586a943463e8042c0f6a3a2d/src/status-bar.ts#L53
    openLogFileOnClick() {
        this.statusBar.addClass("statusbar-pomo-logging");
        this.statusBar.onClickEvent((ev) => __awaiter(this, void 0, void 0, function* () {
            if (this.settings.logging === true) { //this is hacky, ideally I'd just unwatch the onClickEvent as soon as I turned logging off
                try {
                    var file;
                    if (this.settings.logToDaily === true) {
                        file = (yield this.getDailyNoteFile()).path;
                    }
                    else {
                        file = this.settings.logFile;
                    }
                    this.app.workspace.openLinkText(file, '', false);
                }
                catch (error) {
                    console.log(error);
                }
            }
        }));
    }
    onunload() {
        this.timer.quitTimer();
        console.log('Unloading status bar pomodoro timer');
    }
    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);
        });
    }
    getDailyNoteFile() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                let file = getDailyNote_1(obsidian.moment(), getAllDailyNotes_1()); // as any, because getDailyNote is importing its own Moment and I'm using Obsidian's
                if (!file) {
                    file = yield createDailyNote_1(obsidian.moment());
                    console.log("Created daily note: " + file.path);
                }
                return file;
            }
            catch (error) { // If entire folder does not exist
                let dailyNoteFolder = getDailyNoteSettings_1().folder;
                console.log("Creating daily note folder: " + dailyNoteFolder);
                this.app.vault.createFolder(dailyNoteFolder);
                let file = yield createDailyNote_1(obsidian.moment());
                return file;
            }
        });
    }
}

module.exports = PomoTimerPlugin;


/* nosourcemap */