/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* import-globals-from preferences.js */

var { GenericConvIMPrototype, GenericMessagePrototype } =
  ChromeUtils.importESModule("resource:///modules/jsProtoHelper.sys.mjs");
var { getThemeByName, getThemeVariants } = ChromeUtils.importESModule(
  "resource:///modules/imThemes.sys.mjs"
);

var { IMServices } = ChromeUtils.importESModule(
  "resource:///modules/IMServices.sys.mjs"
);

function Conversation(aName) {
  this._name = aName;
  this._observers = [];
  let now = new Date();
  this._date =
    new Date(now.getFullYear(), now.getMonth(), now.getDate(), 10, 42, 22) *
    1000;
}
Conversation.prototype = {
  __proto__: GenericConvIMPrototype,
  account: {
    protocol: { name: "Fake Protocol" },
    alias: "",
    name: "Fake Account",
    get statusInfo() {
      return IMServices.core.globalUserStatus;
    },
  },
};

function Message(aWho, aMessage, aObject, aConversation) {
  this._init(aWho, aMessage, aObject, aConversation);
}
Message.prototype = {
  __proto__: GenericMessagePrototype,
  get displayMessage() {
    return this.originalMessage;
  },
};

// Message style tooltips use this.
function getBrowser() {
  return document.getElementById("previewbrowser");
}

var previewObserver = {
  _loaded: false,
  load() {
    let makeDate = function (aDateString) {
      let array = aDateString.split(":");
      let now = new Date();
      return (
        new Date(
          now.getFullYear(),
          now.getMonth(),
          now.getDate(),
          array[0],
          array[1],
          array[2]
        ) / 1000
      );
    };
    let bundle = document.getElementById("themesBundle");
    let msg = {};
    [
      "nick1",
      "buddy1",
      "nick2",
      "buddy2",
      "message1",
      "message2",
      "message3",
    ].forEach(function (aText) {
      msg[aText] = bundle.getString(aText);
    });
    let conv = new Conversation(msg.nick2);
    conv.messages = [
      new Message(
        msg.buddy1,
        msg.message1,
        {
          outgoing: true,
          _alias: msg.nick1,
          time: makeDate("10:42:22"),
        },
        conv
      ),
      new Message(
        msg.buddy1,
        msg.message2,
        {
          outgoing: true,
          _alias: msg.nick1,
          time: makeDate("10:42:25"),
        },
        conv
      ),
      new Message(
        msg.buddy2,
        msg.message3,
        {
          incoming: true,
          _alias: msg.nick2,
          time: makeDate("10:43:01"),
        },
        conv
      ),
    ];
    previewObserver.conv = conv;

    let themeName = document.getElementById("messagestyle-themename");
    previewObserver.browser = document.getElementById("previewbrowser");

    // If the preferences tab is opened straight to the message styles,
    // loading the preview fails. Pushing this to back of the event queue
    // prevents that failure.
    setTimeout(() => {
      previewObserver.displayTheme(themeName.value);
      this._loaded = true;
    });
  },

  currentThemeChanged() {
    if (!this._loaded) {
      return;
    }

    let currentTheme = document.getElementById("messagestyle-themename").value;
    if (!currentTheme) {
      return;
    }

    this.displayTheme(currentTheme);
  },

  _ignoreVariantChange: false,
  currentVariantChanged() {
    if (!this._loaded || this._ignoreVariantChange) {
      return;
    }

    let variant = document.getElementById("themevariant").value;
    if (!variant) {
      return;
    }

    this.theme.variant = variant;
    this.reloadPreview();
  },

  displayTheme(aTheme) {
    try {
      this.theme = getThemeByName(aTheme);
    } catch (e) {
      let previewBoxBrowser = document
        .getElementById("previewBox")
        .querySelector("browser");
      if (previewBoxBrowser) {
        previewBoxBrowser.hidden = true;
      }
      document.getElementById("noPreviewScreen").hidden = false;
      return;
    }

    let menulist = document.getElementById("themevariant");
    if (menulist.menupopup) {
      menulist.menupopup.remove();
    }
    let popup = menulist.appendChild(document.createXULElement("menupopup"));
    let variants = getThemeVariants(this.theme);

    let defaultVariant = "";
    if (
      "DefaultVariant" in this.theme.metadata &&
      variants.includes(this.theme.metadata.DefaultVariant)
    ) {
      defaultVariant = this.theme.metadata.DefaultVariant.replace(/_/g, " ");
    }

    let defaultText = defaultVariant;
    if (!defaultText && "DisplayNameForNoVariant" in this.theme.metadata) {
      defaultText = this.theme.metadata.DisplayNameForNoVariant;
    }
    // if the name in the metadata is 'Default', use the localized version
    if (!defaultText || defaultText.toLowerCase() == "default") {
      defaultText = document
        .getElementById("themesBundle")
        .getString("default");
    }

    let menuitem = document.createXULElement("menuitem");
    menuitem.setAttribute("label", defaultText);
    menuitem.setAttribute("value", "default");
    popup.appendChild(menuitem);
    popup.appendChild(document.createXULElement("menuseparator"));

    variants.sort().forEach(function (aVariantName) {
      let displayName = aVariantName.replace(/_/g, " ");
      if (displayName != defaultVariant) {
        let menuitem = document.createXULElement("menuitem");
        menuitem.setAttribute("label", displayName);
        menuitem.setAttribute("value", aVariantName);
        popup.appendChild(menuitem);
      }
    });
    this._ignoreVariantChange = true;
    if (!this._loaded) {
      menulist.value = this.theme.variant = menulist.value;
    } else {
      menulist.value = this.theme.variant; // (reset to "default")
      Preferences.userChangedValue(menulist);
    }
    this._ignoreVariantChange = false;

    // disable the variant menulist if there's no variant, or only one
    // which is the default
    menulist.disabled =
      variants.length == 0 || (variants.length == 1 && defaultVariant);

    this.reloadPreview();
    document.getElementById("noPreviewScreen").hidden = true;
  },

  reloadPreview() {
    this.browser.init(this.conv);
    this.browser._theme = this.theme;
    Services.obs.addObserver(this, "conversation-loaded");
  },

  observe(aSubject, aTopic, aData) {
    if (aTopic != "conversation-loaded" || aSubject != this.browser) {
      return;
    }

    // We want to avoid the convbrowser trying to scroll to the last
    // added message, as that causes the entire pref pane to jump up
    // (bug 1179943). Therefore, we override the method convbrowser
    // uses to determine if it should scroll, as well as its
    // mirror in the contentWindow (that messagestyle JS can call).
    this.browser.convScrollEnabled = () => false;
    this.browser.contentWindow.convScrollEnabled = () => false;

    // Display all queued messages. Use a timeout so that message text
    // modifiers can be added with observers for this notification.
    setTimeout(function () {
      for (let message of previewObserver.conv.messages) {
        aSubject.appendMessage(message, false);
      }
    }, 0);

    Services.obs.removeObserver(this, "conversation-loaded");
  },
};
