if (!document) {
  throw Error("electron-tabs module must be called in renderer process");
}
// Inject styles
(function () {
  // const styles = `
  //   webview {
  //     position: absolute;
  //     visibility: hidden;
  //     width: 100%;
  //     height: 100%;
  //   }
  //   webview.visible {
  //     visibility: visible;
  //   }
  // `;
  // let styleTag = document.createElement("style");
  // styleTag.innerHTML = styles;
  // document.getElementsByTagName("head")[0].appendChild(styleTag);
})();
const Store = require("electron-store");
const store = new Store();
/**
 * This makes the browser EventTarget API work similar to EventEmitter
 */

class EventEmitter extends EventTarget {
  emit(type, ...args) {
    this.dispatchEvent(new CustomEvent(type, { detail: args }));
  }

  on(type, fn) {
    this.addEventListener(type, ({ detail }) => fn.apply(this, detail));
  }
}

class TabGroup extends EventEmitter {
  constructor(args = {}) {
    super();
    let options = (this.options = {
      tabContainerSelector: args.tabContainerSelector || ".etabs-tabs",
      buttonsContainerSelector:
        args.buttonsContainerSelector || ".etabs-buttons",
      viewContainerSelector: args.viewContainerSelector || ".etabs-views",
      tabClass: args.tabClass || "etabs-tab",
      viewClass: args.viewClass || "etabs-view",
      closeButtonText: args.closeButtonText || "&#215;",
      newTab: args.newTab,
      newTabButtonText: args.newTabButtonText || "&#65291;",
      visibilityThreshold: args.visibilityThreshold || 0,
      ready: args.ready,
    });
    this.tabContainer = document.querySelector(options.tabContainerSelector);
    this.viewContainer = document.querySelector(options.viewContainerSelector);
    this.tabs = [];
    this.newTabId = 0;
    // TabGroupPrivate.initNewTabButton.bind(this)();
    TabGroupPrivate.initVisibility.bind(this)();
    // ViewPrivate.initWebPhoto.bind(this)();
    // ViewPrivate.initSynchronous.bind(this)();
    if (typeof this.options.ready === "function") {
      this.options.ready(this);
    }
  }

  addTab(args = this.options.newTab) {
    if (typeof args === "function") {
      args = args(this);
    }
    /*
    let tab;
    tab = this.tabs.find((tab) =>
      tab.webviewAttributes.src === args.src || tab.webviewAttributes.src.split('?refer')[0] === args.src || tab.webviewAttributes.src === args.src.split('?refer')[0] || tab.webviewAttributes.src.split('?refer')[0] === args.src.split('?refer')[0]
    );
    if (tab) {
      tab.activate();
      return tab;
    }
    重复页面打开不再新开弹窗
    */
    let id = this.newTabId;
    this.newTabId++;
    let tab = new Tab(this, id, args);
    this.tabs.push(tab);
    // Don't call tab.activate() before a tab is referenced in this.tabs
    if (args.active === true) {
      tab.activate();
    }
    this.emit("tab-added", tab, this);
    return tab;
  }

  getTab(id) {
    for (let i in this.tabs) {
      if (this.tabs[i].id === id) {
        return this.tabs[i];
      }
    }
    return null;
  }

  getTabByPosition(position) {
    let fromRight = position < 0;
    for (let i in this.tabs) {
      if (this.tabs[i].getPosition(fromRight) === position) {
        return this.tabs[i];
      }
    }
    return null;
  }

  getTabByRelPosition(position) {
    position = this.getActiveTab().getPosition() + position;
    if (position <= 0) {
      return null;
    }
    return this.getTabByPosition(position);
  }

  getNextTab() {
    return this.getTabByRelPosition(1);
  }

  getPreviousTab() {
    return this.getTabByRelPosition(-1);
  }

  getTabs() {
    return this.tabs.slice();
  }

  eachTab(fn) {
    this.getTabs().forEach(fn);
    return this;
  }

  getActiveTab() {
    if (this.tabs.length === 0) return null;
    return this.tabs[0];
  }
}

const TabGroupPrivate = {
  initNewTabButton: function () {
    if (!this.options.newTab) return;
    let container = document.querySelector(
      this.options.buttonsContainerSelector
    );
    let button = container.appendChild(document.createElement("button"));
    button.classList.add(`${this.options.tabClass}-button-new`);
    button.innerHTML = this.options.newTabButtonText;
    button.addEventListener("click", this.addTab.bind(this, undefined), false);
  },

  initVisibility: function () {
    function toggleTabsVisibility(tab, tabGroup) {
      var visibilityThreshold = this.options.visibilityThreshold;
      var el = tabGroup.tabContainer.parentNode;
      if (this.tabs.length >= visibilityThreshold) {
        el.classList.add("visible");
      } else {
        el.classList.remove("visible");
      }
    }

    this.on("tab-added", toggleTabsVisibility);
    this.on("tab-removed", toggleTabsVisibility);
  },

  removeTab: function (tab, triggerEvent) {
    let id = tab.id;
    for (let i in this.tabs) {
      if (this.tabs[i].id === id) {
        this.tabs.splice(i, 1);
        break;
      }
    }
    if (triggerEvent) {
      this.emit("tab-removed", tab, this);
      let newsTabs = this.tabs.filter((item) => {
        return (
          item.webviewAttributes.src !== "https://www.qinyanai.com/internetSite" &&
          item.webviewAttributes.src !== "https://app.qinyanai.com/"
        );
      });
      saveTabs = [];
      newsTabs = newsTabs.map((item) => {

        let {src, target} = item.webviewAttributes;
        if(!item.webview.src) {
          if(!src && !!target) {
            src = target;
          }
        }

        saveTabs.push({
          title: item.title,
          src: item.webviewAttributes.src,
          webviewAttributes: item.webviewAttributes,
        });
      });
      store.set("saveTabs", saveTabs);
    }
    return this;
  },

  setActiveTab: function (tab) {
    TabGroupPrivate.removeTab.bind(this)(tab);
    this.tabs.unshift(tab);
    this.emit("tab-active", tab, this);
    return this;
  },

  activateRecentTab: function (tab) {
    if (this.tabs.length > 0) {
      this.tabs[0].activate();
    }
    return this;
  },
};

class Tab extends EventEmitter {
  constructor(tabGroup, id, args) {
    super();
    this.tabGroup = tabGroup;
    this.id = id;
    this.isHome = args.isHome;
    this.title = args.title;
    this.badge = args.badge;
    this.iconURL = args.iconURL;
    this.icon = args.icon;
    this.closable = args.closable === false ? false : true;
    this.webviewAttributes = args.webviewAttributes || {};
    this.webviewAttributes.src = args.src;
    this.tabElements = {};
    this.timer = null;
    this.progress = 0;
    TabPrivate.initTab.bind(this)();
    TabPrivate.initWebview.bind(this)();
    if (args.visible !== false) {
      this.show();
    }
    if (typeof args.ready === "function") {
      args.ready(this);
    }
  }

  setTitle(title) {
    if (this.isClosed) return;
    let span = this.tabElements.title;
    span.innerHTML = title;
    span.title = title;
    this.title = title;
    this.emit("title-changed", title, this);
    return this;
  }

  getTitle() {
    if (this.isClosed) return;
    return this.title;
  }

  setBadge(badge) {
    if (this.isClosed) return;
    let span = this.tabElements.badge;
    this.badge = badge;

    if (badge) {
      span.innerHTML = badge;
      span.classList.remove("hidden");
    } else {
      span.classList.add("hidden");
    }

    this.emit("badge-changed", badge, this);
  }

  getBadge() {
    if (this.isClosed) return;
    return this.badge;
  }

  setIcon(iconURL, icon) {
    if (this.isClosed) return;
    this.iconURL = iconURL;
    this.icon = icon;
    let span = this.tabElements.icon;
    if (iconURL) {
      span.innerHTML = `<img src="${iconURL}" />`;
      this.emit("icon-changed", iconURL, this);
    } else if (icon) {
      span.innerHTML = `<i class="${icon}"></i>`;
      this.emit("icon-changed", icon, this);
    }

    return this;
  }

  getIcon() {
    if (this.isClosed) return;
    if (this.iconURL) return this.iconURL;
    return this.icon;
  }

  setPosition(newPosition) {
    let tabContainer = this.tabGroup.tabContainer;
    let tabs = tabContainer.children;
    let oldPosition = this.getPosition() - 1;

    if (newPosition < 0) {
      newPosition += tabContainer.childElementCount;

      if (newPosition < 0) {
        newPosition = 0;
      }
    } else {
      if (newPosition > tabContainer.childElementCount) {
        newPosition = tabContainer.childElementCount;
      }

      // Make 1 be leftmost position
      newPosition--;
    }

    if (newPosition > oldPosition) {
      newPosition++;
    }

    tabContainer.insertBefore(tabs[oldPosition], tabs[newPosition]);

    return this;
  }

  getPosition(fromRight) {
    let position = 0;
    let tab = this.tab;
    while ((tab = tab.previousSibling) != null) position++;

    if (fromRight === true) {
      position -= this.tabGroup.tabContainer.childElementCount;
    }

    if (position >= 0) {
      position++;
    }

    return position;
  }
  oldWebviewDomReadyHandler = () => {
    $('.page-progress-bar .progress').css({width: "100%"});
    let timer = setTimeout(() => {
      $('.page-progress-bar').hide();
      clearTimeout(timer);
      timer = null;
    }, 350)
    this.stopTimer();
    this.webview.removeEventListener('dom-ready', this.oldWebviewDomReadyHandler)
  }

  stopTimer = () => {
    this.progress = 0;
    clearInterval(this.timer);
    this.timer = null;
  }

  addOldWebviewEvent = () => {
    this.timer = setInterval(() => {
      if(this.progress > 90) {
        this.stopTimer();
      } else {
        this.progress += 10;
        $('.page-progress-bar .progress').css({width: this.progress + '%'})
      }
    }, 300);
    this.webview.addEventListener('dom-ready', this.oldWebviewDomReadyHandler)
  }

  resetProgress = () => {
    $('.page-progress-bar').hide();
    $('.page-progress-bar .progress').css({width: '0%'})
    this.progress = 0;
    this.timer = null;
  }

  activate() {
    if (this.isClosed) return;
    this.resetProgress();
    const {src, target} = this.webviewAttributes;
    if(!this.webview.src) {
      if(!src && !!target) {
        $('.page-progress-bar').show();
        this.webview.src = target;
        this.addOldWebviewEvent()
      }
    }

    let activeTab = this.tabGroup.getActiveTab();
    if (activeTab) {
      activeTab.tab.classList.remove("active");
      activeTab.webview.classList.remove("visible");
      activeTab.emit("inactive", activeTab);
    }
    TabGroupPrivate.setActiveTab.bind(this.tabGroup)(this);
    this.tab.classList.add("active");
    this.webview.classList.add("visible");
    this.webview.focus();
    this.emit("active", this);
    return this;
  }

  show(flag) {
    if (this.isClosed) return;
    if (flag !== false) {
      this.tab.classList.add("visible");
      this.emit("visible", this);
    } else {
      this.tab.classList.remove("visible");
      this.emit("hidden", this);
    }
    return this;
  }

  hide() {
    return this.show(false);
  }

  flash(flag) {
    if (this.isClosed) return;
    if (flag !== false) {
      this.tab.classList.add("flash");
      this.emit("flash", this);
    } else {
      this.tab.classList.remove("flash");
      this.emit("unflash", this);
    }
    return this;
  }

  unflash() {
    return this.flash(false);
  }

  hasClass(classname) {
    return this.tab.classList.contains(classname);
  }

  close(force) {
    const abortController = new AbortController();
    const abort = () => abortController.abort();
    this.emit("closing", this, abort);

    const abortSignal = abortController.signal;
    if (this.isClosed || (!this.closable && !force) || abortSignal.aborted)
      return;

    this.isClosed = true;
    let tabGroup = this.tabGroup;
    tabGroup.tabContainer.removeChild(this.tab);
    tabGroup.viewContainer.removeChild(this.webview);
    let activeTab = this.tabGroup.getActiveTab();
    TabGroupPrivate.removeTab.bind(tabGroup)(this, true);

    this.emit("close", this);

    if (activeTab.id === this.id) {
      TabGroupPrivate.activateRecentTab.bind(tabGroup)();
    }
  }
}

const TabPrivate = {
  initTab: function () {
    let tabClass = this.tabGroup.options.tabClass;

    // Create tab element
    let tab = (this.tab = document.createElement("div"));
    tab.setAttribute("data-id", this.id);
    // if(!this.isHome) {
    //   tab.setAttribute('data-id', this.id)
    // } else {
    //   tab.classList.add('home-tab');
    // }
    tab.classList.add(tabClass);
    for (let el of ["icon", "title", "buttons", "badge"]) {
      let span = tab.appendChild(document.createElement("span"));
      span.classList.add(`${tabClass}-${el}`);
      this.tabElements[el] = span;
    }

    this.setTitle(this.title);
    this.setBadge(this.badge);
    this.setIcon(this.iconURL, this.icon);
    TabPrivate.initTabButtons.bind(this)();
    TabPrivate.initTabClickHandler.bind(this)();

    this.tabGroup.tabContainer.appendChild(this.tab);
  },

  initTabButtons: function () {
    let container = this.tabElements.buttons;
    let tabClass = this.tabGroup.options.tabClass;
    if (this.closable) {
      let button = container.appendChild(document.createElement("button"));
      button.classList.add(`${tabClass}-button-close`);
      button.innerHTML = this.tabGroup.options.closeButtonText;
      button.addEventListener("click", this.close.bind(this, false), false);
    }
  },

  initTabClickHandler: function () {
    // Mouse up
    const tabClickHandler = function (e) {
      if (this.isClosed) return;
      if (e.which === 2) {
        this.close();
      }
    };
    this.tab.addEventListener("mouseup", tabClickHandler.bind(this), false);
    // Mouse down
    const tabMouseDownHandler = function (e) {
      if (this.isClosed) return;
      if (e.which === 1) {
        if (e.target.matches("button")) return;
        this.activate();
      }
    };
    this.tab.addEventListener(
      "mousedown",
      tabMouseDownHandler.bind(this),
      false
    );
  },

  initWebview: function () {
    const webview = (this.webview = document.createElement("webview"));

    const tabWebviewDidFinishLoadHandler = function (e) {
      this.emit("webview-ready", this);
    };

    this.webview.addEventListener(
      "did-finish-load",
      tabWebviewDidFinishLoadHandler.bind(this),
      false
    );

    const tabWebviewDomReadyHandler = function (e) {
      // Remove this once https://github.com/electron/electron/issues/14474 is fixed
      webview.blur();
      webview.focus();
      if (!this.isHome) {
        this.setTitle(webview.getTitle());
      }

      this.emit("webview-dom-ready", this);
    };

    const tabWebviewUpdateTargetUrlHandler = function (e, title, explicitSet) {
      if (webview.getURL() === "https://app.qinyanai.com/") {
        this.setTitle("首页");
      } else {
        this.setTitle(webview.getTitle());
      }
    };

    this.webview.addEventListener(
      "dom-ready",
      tabWebviewDomReadyHandler.bind(this),
      false
    );
    this.webview.addEventListener(
      "page-title-updated",
      tabWebviewUpdateTargetUrlHandler.bind(this),
      false
    );
    this.webview.addEventListener(
      "did-navigate-in-page",
      tabWebviewUpdateTargetUrlHandler.bind(this),
      false
    );
    this.webview.classList.add(this.tabGroup.options.viewClass);
    if (this.webviewAttributes) {
      let attrs = this.webviewAttributes;
      for (let key in attrs) {
        const attr = attrs[key];
        if (attr === false) continue;
        this.webview.setAttribute(key, attr);
      }
    }

    this.tabGroup.viewContainer.appendChild(this.webview);
  },
};

module.exports = TabGroup;
