const Lang = imports.lang;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const St = imports.gi.St;
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extension-do-not-disturb');
const _ = Gettext.gettext;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Lib = Me.imports.lib;


/**
 * A class which handles the UI of the do not disturb toggle.
 */
class DoNotDisturbToggle {
  /**
   * Represents a do not disturb toggle in the calendar/notification popup.
   * @constructor
   */
  constructor() {
    this._connections = [];
  }

  /**
   * Shows the do not disturb toggle in the calendar/notification popup.
   */
  show() {
    this._clearButton = Main.panel.statusArea.dateMenu._messageList._clearButton;

    this._calendarBox = this._clearButton.get_parent();

    this._clearBox = new St.BoxLayout({
      vertical: false,
      x_expand: true,
      y_expand: false
    });


    this._disturbToggle = new PopupMenu.PopupSwitchMenuItem(_("Do not disturb"));

    this._disturbToggle.actor.add_style_class_name('do-not-disturb');
    this._disturbToggle.actor.set_x_expand(true);
    this._disturbToggle.actor.track_hover = false;

    this._disturbToggle.actor.set_x_align(Clutter.ActorAlign.START);
    this._disturbToggle.actor.remove_child(this._disturbToggle.label);
    this._disturbToggle.actor.add_child(this._disturbToggle.label);
    this._disturbToggle.label.set_y_align(Clutter.ActorAlign.CENTER);
    this._disturbToggle.actor.remove_child(this._disturbToggle._ornamentLabel);

    this._clearBox.add_actor(this._disturbToggle.actor);

    this._clearButton.reparent(this._clearBox);
    this._clearButton.add_style_class_name('clear-button');

    this._calendarBox.add_actor(this._clearBox);
  }

  /**
   * Destroys all UI elements of the toggle and returns the clear button to its proper location.
   */
  destroy() {
    if (this._disturbToggle) {
      this._connections.forEach((id) => {
        this._disturbToggle.disconnect(id);
      });
      this._connections = [];
      this._disturbToggle.destroy();
      this._disturbToggle = 0;
    }

    if (this._clearButton) {
      this._clearButton.reparent(this._calendarBox);
      this._clearButton.remove_style_class_name('clear-button');
    }

    if (this._clearBox) {
      this._clearBox.destroy();
      this._clearBox = 0;
    }
  }

  /**
   * Sets the activation state of the toggle.
   *
   * @param {boolean} state - The state of the toggle: true for on, false for off.
   */
  setToggleState(state) {
    if (this._disturbToggle) {
      this._disturbToggle.setToggleState(state);
    }
  }

  /**
   * Get the activation state of the toggle.
   *
   * @returns {boolean} - True if the toggle is on, false otherwise.
   */
  getToggleState() {
    if (this._disturbToggle) {
      return this._disturbToggle._switch.state;
    }
    return false;
  }

  /**
   * Calls a function when the toggle state changes.
   *
   * @param {() => ()} fn - The function to call when the toggle state changes.
   */
  onToggleStateChanged(fn) {
    if (this._disturbToggle) {
      var id = this._disturbToggle.connect("toggled", (item, event) => fn());
      this._connections.push(id);
    }
  }
}

/**
 * A class which handles the UI of the do not disturb status icon.
 */
class DoNotDisturbIcon {
  /**
   * Represents a do not disturb icon in the system status area of the panel.
   * @constructor
   */
  constructor(settingsManager, notificationCounter) {
    this._settings = settingsManager;
    this.notificationCounter = notificationCounter;
    this._indicatorArea = Main.panel._centerBox; //statusArea.aggregateMenu._indicators;

    let icon = "notification-disabled-symbolic";
    let fallback = "user-busy-symbolic";

    this._enabledIcon = new St.Icon({
      icon_name: icon,
      fallback_icon_name: fallback,
      style_class: 'popup-menu-icon do-not-disturb-icon'
    });

    this._countLbl = new St.Label();
    this.updateCount(0);
    this._countLbl.add_style_class_name("notification-count");

    this._iconBox = new St.BoxLayout();
    this._iconBox.add_actor(this._enabledIcon);
    this._iconBox.add_actor(this._countLbl);
    this.showDot = this._settings.showDot;
    this.showCount = this._settings.showCount;
    this.showIcon = this._settings.shouldShowIcon();
    this.shown = false;
    this.count = this.notificationCounter.notificationCount;
    this.updateCount(this.count);

    this._settings.onShowIconChanged(() => {
      this.showIcon = this._settings.shouldShowIcon();
      if (this.shown){
        this.hide();
        this.show();
      }
    });
    this._settings.onShowCountChanged(() => {
      this.showCount = this._settings.showCount;
      this.updateCount(this.count);
    });
    this._settings.onShowDotChanged(() => {
      this.showDot = this._settings.showDot;
      this.updateCount(this.count);
    });
    this.notificationListenerID = this.notificationCounter.addNotificationCountListener((count) => {
      this.updateCount(count);
    });
  }

  updateCount(newCount){
    this.count = newCount;
    if (newCount == 0){
      this._countLbl.add_style_class_name("hide-dot");
    } else {
      if (this.showCount){
        this._countLbl.set_text("" + newCount);
        this._countLbl.remove_style_class_name("hide-dot");
      } else if(this.showDot){
        this._countLbl.set_text("\u25CF");
        this._countLbl.remove_style_class_name("hide-dot");
      } else {
        this._countLbl.add_style_class_name("hide-dot");
      }

    }
  }

  /**
   * Shows the status icon.
   */
  show() {
    if (this.showIcon){
      this._indicatorArea.add_child(this._iconBox);
      Main.panel.statusArea.dateMenu._indicator.actor.add_style_class_name("hide-dot");
    }
    this.shown = true;
  }

  /**
   * Hides the status icon.
   */
  hide() {
    Main.panel.statusArea.dateMenu._indicator.actor.remove_style_class_name("hide-dot");
    if (this._iconBox.get_parent()) {
      this._indicatorArea.remove_child(this._iconBox);
    }
    this.shown = false;
  }

  /**
   * Destroys the status icon and removes it from the system status area.
   */
  destroy() {
    if (this._enabledIcon) {
      if (this._iconBox.get_parent()) {
        this._indicatorArea.remove_child(this._iconBox);
      }
      this._countLbl.destroy();
      this._countLbl = 0;
      this._enabledIcon.destroy();
      this._enabledIcon = 0;
      this._iconBox.destroy();
      this._iconBox = 0;
    }
    this._settings.disconnectAll();
    this.notificationCounter.removeNotificationCountListener(this.notificationListenerID);
  }
}

Lib.initTranslations(Me);