/**
 * @name MarkAllAsRead
 * @author Ahlawat
 * @authorId 1025214794766221384
 * @version 1.3.0
 * @invite SgKSKyh9gY
 * @description Get an option to mark everything as read by right clicking on the home button.
 * @website https://tharki-god.github.io/
 * @source https://github.com/Tharki-God/BetterDiscordPlugins
 * @updateUrl https://tharki-god.github.io/BetterDiscordPlugins/MarkAllAsRead.plugin.js
 */
/*@cc_on
@if (@_jscript)
var shell = WScript.CreateObject("WScript.Shell");
var fs = new ActiveXObject("Scripting.FileSystemObject");
var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins");
var pathSelf = WScript.ScriptFullName;
shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30);
if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) {
shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40);
} else if (!fs.FolderExists(pathPlugins)) {
shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10);
} else if (shell.Popup("Should I move myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) {
fs.MoveFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)));
shell.Exec("explorer " + pathPlugins);
shell.Popup("I'm installed!", 0, "Successfully installed", 0x40);
}
WScript.Quit();
@else@*/
module.exports = ((_) => {
  const config = {
    info: {
      name: "MarkAllAsRead",
      authors: [
        {
          name: "Ahlawat",
          discord_id: "1025214794766221384",
          github_username: "Tharki-God",
        },
      ],
      version: "1.3.0",
      description:
        "Get an option to mark everything as read by right clicking on the home button.",
      github: "https://github.com/Tharki-God/BetterDiscordPlugins",
      github_raw:
        "https://tharki-god.github.io/BetterDiscordPlugins/MarkAllAsRead.plugin.js",
    },
    changelog: [
      {
        title: "v0.0.1",
        items: ["Idea in mind"],
      },
      {
        title: "v0.0.5",
        items: ["Base Model"],
      },
      {
        title: "Initial Release v1.0.0",
        items: [
          "This is the initial release of the plugin :)",
          "Who sliding into your DMs ~~~///(^v^)\\\\~~~",
        ],
      },
      {
        title: "v1.0.5",
        items: ["Remove option from context menu if no ping"],
      },
      {
        title: "v1.0.7",
        items: ["Blacklist server/dm from being read in settings"],
      },
      {
        title: "v1.1.6",
        items: ["Corrected text."],
      },
    ],
    main: "MarkAllAsRead.plugin.js",
  };
  const RequiredLibs = [{
    window: "ZeresPluginLibrary",
    filename: "0PluginLibrary.plugin.js",
    external: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js",
    downloadUrl: "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js"
  },
  {
    window: "BunnyLib",
    filename: "1BunnyLib.plugin.js",
    external: "https://github.com/Tharki-God/BetterDiscordPlugins",
    downloadUrl: "https://tharki-god.github.io/BetterDiscordPlugins/1BunnyLib.plugin.js"
  },
  ];
  class handleMissingLibrarys {
    load() {
      for (const Lib of RequiredLibs.filter(lib => !window.hasOwnProperty(lib.window)))
        BdApi.showConfirmationModal(
          "Library Missing",
          `The library plugin (${Lib.window}) needed for ${config.info.name} is missing. Please click Download Now to install it.`,
          {
            confirmText: "Download Now",
            cancelText: "Cancel",
            onConfirm: () => this.downloadLib(Lib),
          }
        );
    }
    async downloadLib(Lib) {
      const fs = require("fs");
      const path = require("path");
      const { Plugins } = BdApi;
      const LibFetch = await fetch(
        Lib.downloadUrl
      );
      if (!LibFetch.ok) return this.errorDownloadLib(Lib);
      const LibContent = await LibFetch.text();
      try {
        await fs.writeFile(
          path.join(Plugins.folder, Lib.filename),
          LibContent,
          (err) => {
            if (err) return this.errorDownloadLib(Lib);
          }
        );
      } catch (err) {
        return this.errorDownloadLib(Lib);
      }
    }
    errorDownloadZLib(Lib) {
      const { shell } = require("electron");
      BdApi.showConfirmationModal(
        "Error Downloading",
        [
          `${Lib.window} download failed. Manually install plugin library from the link below.`,
        ],
        {
          confirmText: "Download",
          cancelText: "Cancel",
          onConfirm: () => {
            shell.openExternal(
              Lib.external
            );
          },
        }
      );
    }
    start() { }
    stop() { }
  }
  return RequiredLibs.some(m => !window.hasOwnProperty(m.window))
    ? handleMissingLibrarys
    : (([Plugin, ZLibrary]) => {
      const {
        Patcher,
        ContextMenu,
        Utilities,
        PluginUpdater,
        Logger,
        Toasts,
        Settings: { SettingPanel, SettingGroup, Switch },
        DiscordModules: {
          ChannelStore,
          UserStore,
          GuildStore,
          GuildChannelsStore,
          Dispatcher,
        },
      } = ZLibrary;
      const {
        HBCM,
        LibraryIcons,
        Settings: { IconSwitch },
        LibraryModules: { MentionUtils, IconUtils, AckUtils, MessageStore }
      } = BunnyLib.build(config);
      const defaultSettings = {
        blacklistedServers: {},
        blacklistedDMs: {},
        showToast: true,
      };
      return class MarkAllRead extends Plugin {
        constructor() {
          super();
          this.settings = Utilities.loadData(
            config.info.name,
            "settings",
            defaultSettings
          );
          this.initMenu = this.initMenu.bind(this);
        }
        checkForUpdates() {
          try {
            PluginUpdater.checkForUpdate(
              config.info.name,
              config.info.version,
              config.info.github_raw
            );
          } catch (err) {
            Logger.err("Plugin Updater could not be reached.", err);
          }
        }
        start() {
          this.checkForUpdates();
          this.initiate();
        }
        initiate() {
          this.initMenu();
          Dispatcher.subscribe("MESSAGE_ACK", this.initMenu);
          Patcher.after(MentionUtils, "Hl", (_, [args], res) => {
            const { type } = ChannelStore.getChannel(
              args.rawMessage.channel_id
            );
            if (res || type == 1) this.initMenu();
          });
        }
        initMenu() {
          if (this.timer) return;
          let Menu = this.makeMenu();
          if (
            !Menu &&
            Array.from(HBCM.items.keys()).some(
              (m) => m == config.info.name
            )
          )
            HBCM.remove(config.info.name);
          else if (Menu) HBCM.insert(config.info.name, Menu);
          this.timer = setTimeout(() => (this.timer = false), 3000);
        }
        getPingedDMs() {
          return ChannelStore.getSortedPrivateChannels()
            .map((c) => c.id)
            .filter(
              (id) =>
                (id &&
                  !this.settings["blacklistedDMs"][id] &&
                  MessageStore.getMentionCount(id) > 0) ||
                MessageStore.getUnreadCount(id) > 0
            );
        }
        getPingedGuilds() {
          const PingedChannels = [];
          const guildIds = Object.keys(GuildStore.getGuilds());
          for (const id of guildIds) {
            if (this.settings["blacklistedServers"][id]) continue;
            PingedChannels.push(
              ...GuildChannelsStore.getChannels(id)
                .SELECTABLE.map((c) => c.channel.id)
                .filter((id) => MessageStore.getMentionCount(id) > 0)
            );
          }
          return PingedChannels.filter((n) => n.length > 0);
        }
        makeMenu() {
          const PingedDMs = this.getPingedDMs();
          const PingedGuilds = this.getPingedGuilds();
          const AllMentions = PingedGuilds.concat(PingedDMs).filter(
            (n) => n.length > 0
          );
          if (!AllMentions.length) return;
          const children = this.buildChildrenReaders(PingedDMs, PingedGuilds);
          return {
            label: "Mark All as Read",
            id: "mark-all-read",
            icon: () => (children ? null : LibraryIcons.Message("20", "20")),
            action: () => this.markRead(AllMentions),
            children,
          };
        }
        buildChildrenReaders(PingedDMs, PingedGuilds) {
          if (!PingedDMs.length || !PingedGuilds.length) return;
          return ContextMenu.buildMenuChildren([
            {
              label: "Mark All Guilds as Read",
              id: "mark-all-guild-read",
              icon: () => LibraryIcons.Guilds("20", "20"),
              action: () => this.markRead(PingedGuilds, "Guild"),
            },
            {
              label: "Mark All DMs as Read",
              id: "mark-all-dm-read",
              icon: () => LibraryIcons.DMs("20", "20"),
              action: () => this.markRead(PingedDMs, "DM"),
            },
          ]);
        }
        async markRead(Mentions, Mode) {
          Mentions = Mentions.map((Unread) => ({
            channelId: Unread,
            messageId: MessageStore.lastMessageId(Unread),
          }));
          await AckUtils.y5(Mentions);
          await this.initMenu();
          if (this.settings["showToast"])
            switch (Mode) {
              case "DM":
                Toasts.show(`Marked All DMs as Read`, {
                  icon: "https://tharki-god.github.io/files-random-host/ic_fluent_people_community_24_filled.png",
                  timeout: 5000,
                  type: "info",
                });

                break;
              case "Guild":
                Toasts.show(`Marked All Guilds as Read`, {
                  icon: "https://tharki-god.github.io/files-random-host/ic_fluent_server_24_filled.png",
                  timeout: 5000,
                  type: "info",
                });
                break;
              default:
                Toasts.show(`Marked Everything as Read`, {
                  icon: "https://tharki-god.github.io/files-random-host/ic_fluent_mail_read_24_filled.png",
                  timeout: 5000,
                  type: "info",
                });
            }
        }
        onStop() {
          HBCM.remove(config.info.name);
          Patcher.unpatchAll();
          Dispatcher.unsubscribe("MESSAGE_ACK", this.initMenu);
        }
        getSettingsPanel() {
          const Guilds = Object.values(GuildStore.getGuilds());
          const DMs = ChannelStore.getSortedPrivateChannels();
          return SettingPanel.build(
            this.saveSettings.bind(this),
            new Switch(
              "Pop-up/Toast",
              "Get a toast confirmation when messages get marked as read.",
              this.settings["showToast"],
              (e) => {
                this.settings["showToast"] = e;
              }
            ),
            new SettingGroup("Server Blacklist", {
              collapsible: true,
              shown: false,
            }).append(
              ...Guilds.map((guild) => {
                return new IconSwitch(
                  guild.name,
                  guild.description,
                  this.settings["blacklistedServers"][guild.id] ?? false,
                  (e) => {
                    this.settings["blacklistedServers"][guild.id] = e;
                  },
                  {
                    icon:
                      IconUtils.getGuildIconURL(guild) ??
                      IconUtils.getDefaultAvatarURL(LibraryUtils.randomNo(0, 5)),
                  }
                );
              })
            ),
            new SettingGroup("DM Blacklist", {
              collapsible: true,
              shown: false,
            }).append(
              ...DMs.map((DM) => {
                const User = UserStore.getUser(DM.recipients[0]);
                return new IconSwitch(
                  User.tag,
                  User.pronouns,
                  this.settings["blacklistedDMs"][DM.id] ?? false,
                  (e) => {
                    this.settings["blacklistedDMs"][DM.id] = e;
                  },
                  {
                    icon:
                      IconUtils.getUserAvatarURL(User) ??
                      IconUtils.getDefaultAvatarURL(LibraryUtils.randomNo(0, 5)),
                  }
                );
              })
            )
          );
        }
        saveSettings() {
          Utilities.saveData(config.info.name, "settings", this.settings);
          this.initMenu();
        }
      };
    })(ZLibrary.buildPlugin(config));
})();
/*@end@*/