import { formatMessage, formatTitleWithDefault, openUrl, playSound, topicDisplayName, topicShortUrl } from "./utils";
import prefs from "./Prefs";
import subscriptionManager from "./SubscriptionManager";
import logo from "../img/ntfy.png";

/**
 * The notifier is responsible for displaying desktop notifications. Note that not all modern browsers
 * support this; most importantly, all iOS browsers do not support window.Notification.
 */
class Notifier {
  async notify(subscriptionId, notification, onClickFallback) {
    if (!this.supported()) {
      return;
    }
    const subscription = await subscriptionManager.get(subscriptionId);
    const shouldNotify = await this.shouldNotify(subscription, notification);
    if (!shouldNotify) {
      return;
    }
    const shortUrl = topicShortUrl(subscription.baseUrl, subscription.topic);
    const displayName = topicDisplayName(subscription);
    const message = formatMessage(notification);
    const title = formatTitleWithDefault(notification, displayName);

    // Show notification
    console.log(`[Notifier, ${shortUrl}] Displaying notification ${notification.id}: ${message}`);
    const n = new Notification(title, {
      body: message,
      icon: logo,
    });
    if (notification.click) {
      n.onclick = () => openUrl(notification.click);
    } else {
      n.onclick = () => onClickFallback(subscription);
    }

    // Play sound
    const sound = await prefs.sound();
    if (sound && sound !== "none") {
      try {
        await playSound(sound);
      } catch (e) {
        console.log(`[Notifier, ${shortUrl}] Error playing audio`, e);
      }
    }
  }

  granted() {
    return this.supported() && Notification.permission === "granted";
  }

  maybeRequestPermission(cb) {
    if (!this.supported()) {
      cb(false);
      return;
    }
    if (!this.granted()) {
      Notification.requestPermission().then((permission) => {
        const granted = permission === "granted";
        cb(granted);
      });
    }
  }

  async shouldNotify(subscription, notification) {
    if (subscription.mutedUntil === 1) {
      return false;
    }
    const priority = notification.priority ? notification.priority : 3;
    const minPriority = await prefs.minPriority();
    if (priority < minPriority) {
      return false;
    }
    return true;
  }

  supported() {
    return this.browserSupported() && this.contextSupported();
  }

  browserSupported() {
    return "Notification" in window;
  }

  /**
   * Returns true if this is a HTTPS site, or served over localhost. Otherwise the Notification API
   * is not supported, see https://developer.mozilla.org/en-US/docs/Web/API/notification
   */
  contextSupported() {
    return window.location.protocol === "https:" || window.location.hostname.match("^127.") || window.location.hostname === "localhost";
  }
}

const notifier = new Notifier();
export default notifier;
