// ==UserScript==
// @name Enhance the copy manga site
// @version 26
// @author Arylo Yeung <arylo.open@gmail.com>
// @license MIT
// @match https://copymanga.com/comic/*/chapter/*
// @match https://copymanga.org/comic/*/chapter/*
// @match https://copymanga.net/comic/*/chapter/*
// @match https://copymanga.info/comic/*/chapter/*
// @match https://copymanga.site/comic/*/chapter/*
// @match https://copymanga.tv/comic/*/chapter/*
// @match https://mangacopy.com/comic/*/chapter/*
// @match https://*.copymanga.com/comic/*/chapter/*
// @match https://*.copymanga.org/comic/*/chapter/*
// @match https://*.copymanga.net/comic/*/chapter/*
// @match https://*.copymanga.info/comic/*/chapter/*
// @match https://*.copymanga.site/comic/*/chapter/*
// @match https://*.copymanga.tv/comic/*/chapter/*
// @match https://*.mangacopy.com/comic/*/chapter/*
// @require https://unpkg.com/vue@2.7.14/dist/vue.min.js
// @homepage https://github.com/Arylo/scripts#readme
// @supportURL https://github.com/Arylo/scripts/issues
// @downloadURL https://raw.githubusercontent.com/Arylo/scripts/monkey/copymanga-enhance.user.js
// @updateURL https://raw.githubusercontent.com/Arylo/scripts/monkey/copymanga-enhance.meta.js
// @run-at document-end
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
"use strict";
(() => {
  // src/monkey/polyfill/GM.ts
  var thisGlobal = window;
  if (typeof thisGlobal.GM === "undefined") {
    thisGlobal.GM = {};
  }
  function getGMWindow() {
    return thisGlobal;
  }

  // src/monkey/polyfill/GM_addStyle.ts
  var w = getGMWindow();
  if (typeof w.GM_addStyle === "undefined") {
    w.GM_addStyle = function GM_addStyle2(cssContent) {
      const head = document.getElementsByTagName("head")[0];
      if (head) {
        const styleElement = document.createElement("style");
        styleElement.setAttribute("type", "text/css");
        styleElement.textContent = cssContent;
        head.appendChild(styleElement);
        return styleElement;
      }
      return null;
    };
  }
  if (typeof w.GM.addStyle === "undefined") {
    w.GM.addStyle = GM_addStyle;
  }

  // src/monkey/copymanga-enhance/style.css
  var style_default = ":root{--header-label-color: rgba(255, 255, 255, .95);--header-height: 30px;--image-max-height: calc(100vh - var(--header-height));--action-btn-label-color: rgba(255, 255, 255, .95);--action-btn-bg-color: rgba(0, 0, 0, .2);--action-btn-height: 100px;--action-btn-width: 100px;--action-btn-border-radius: 100px;--action-btn-only-height: 30vh;--action-btn-only-width: 95px}#app{overflow:hidden;height:100vh}#app .header{height:var(--header-height);width:100vw;display:flex;justify-content:center;align-items:center}#app .header:hover~.hint{display:none}#app .header span{color:var(--header-label-color)}#app .header .btn{min-width:80px}#app .header .btn.no-action{visibility:hidden}#app .images{display:flex;flex-wrap:wrap;justify-content:center;overflow:auto;height:var(--image-max-height)}#app .images.rtl{flex-direction:row-reverse}#app .images div{height:var(--image-max-height)}#app .images.ttb div{height:auto;width:90vw}#app .images .white-page{visibility:hidden}#app .hint-container{position:absolute;height:var(--hint-action-zone-height, var(--image-max-height));top:var(--hint-action-zone-top, var(--header-height));display:flex;width:30vw;align-items:center;cursor:pointer;overflow:hidden}#app .hint-container.left{left:0;justify-content:flex-start}#app .hint-container.right{right:0;justify-content:flex-end}#app .hint-container.windows.right{right:16px}#app .hint-container.top{--hint-action-zone-top: var(--header-height);--hint-action-zone-height: calc(var(--image-max-height) * .4);align-items:flex-start}#app .hint-container.bottom{--hint-action-zone-top: calc(var(--header-height) + var(--image-max-height) * .4);--hint-action-zone-height: calc(var(--image-max-height) * .6);align-items:flex-end}#app .hint-container>div{display:none;padding:20px;border-radius:var(--action-btn-border-radius);height:var(--action-btn-height);width:var(--action-btn-width);color:var(--action-btn-label-color);background-color:var(--action-btn-bg-color);box-shadow:var(--action-btn-shadow-x, 0) var(--action-btn-shadow-y, 0) 18px var(--action-btn-bg-color)}#app .hint-container:hover>div{display:flex}#app .hint-container.left>div{--action-btn-shadow-x: 10px;justify-content:flex-start;border-top-left-radius:0;border-bottom-left-radius:0}#app .hint-container.right>div{--action-btn-shadow-x: -10px;justify-content:flex-end;border-top-right-radius:0;border-bottom-right-radius:0}#app .hint-container.top>div{--action-btn-shadow-y: 10px;align-items:flex-start;border-top-left-radius:0;border-top-right-radius:0}#app .hint-container.bottom>div{--action-btn-shadow-y: -10px;align-items:flex-end;border-bottom-left-radius:0;border-bottom-right-radius:0}#app .hint-container:not(.top):not(.bottom)>div{align-items:center;height:var(--action-btn-only-height);width:var(--action-btn-only-width)}\n";

  // src/monkey/copymanga-enhance/template.html
  var template_default = `<div id="app"> <div class="header"> <a :href="prevUrl" :class="{'no-action': !prevUrl}" class="btn"><span>\u4E0A\u4E00\u8BDD</span></a> <a :href="menuUrl" class="title"><span>{{ title }}</span></a> <a :href="nextUrl" :class="{'no-action': !nextUrl}" class="btn"><span>\u4E0B\u4E00\u8BDD</span></a> <select v-model="mode" @change="selectMode"> <option :value="ComicDirection.LTR">\u6B63\u5E38\u6A21\u5F0F</option> <option :value="ComicDirection.RTL">\u65E5\u6F2B\u6A21\u5F0F</option> <option :value="ComicDirection.TTB">\u6761\u6F2B\u6A21\u5F0F</option> </select> <template v-if="canWhitePage"> <a v-if="!hasWhitePage" class="btn" @click="() => toggleWhitePage()"><span>\u589E\u52A0\u7A7A\u767D\u9875</span></a> <a v-else class="btn" @click="() => toggleWhitePage()"><span>\u79FB\u9664\u7A7A\u767D\u9875</span></a> </template> <template v-else> <span style="margin-left: 15px;color: white;">{{currentImageCount}} / {{ totalImageCount }}</span> </template> </div> <div class="images" tabindex="0" :class="mode"> <template v-for="(image, index) of images"> <div v-if="hasWhitePage && whitePageIndex === index"> <img :src="image" class="white-page"> </div> <div> <img class="comic" :src="image" :index="index" @load="(e) => imageLoaded(e, index)"> </div> </template> </div> <div class="hint-container" :class="zone.names" v-for="zone of ActionZones" @click="() => onActionZoneClick(zone)" @wheel.stop="onActionZoneWheel"> <div v-if="zone.names.includes(ClickAction.PREV_PAGE)">\u4E0A\u4E00\u9875</div> <div v-if="zone.names.includes(ClickAction.NEXT_PAGE)">\u4E0B\u4E00\u9875</div> </div> </div>`;

  // src/monkey/copymanga-enhance/scripts/common.ts
  var genScrollTo = (el) => (top, isSmooth = false) => el.scrollTo({
    top,
    left: 0,
    behavior: isSmooth ? "smooth" : "auto"
  });
  var comic = globalThis.location?.pathname.split("/")[2];
  var chapter = globalThis.location?.pathname.split("/")[4];
  var findIndex = (list, predicate, opts) => {
    const { startIndex = 0 } = opts || {};
    const targetList = list.slice(startIndex);
    const nextIndex = targetList.findIndex(predicate);
    if (nextIndex === -1) return nextIndex;
    return nextIndex + startIndex;
  };
  var group = (list, groupFn) => {
    return list.reduce((acc, item, index) => {
      if (index === 0) {
        acc.push([item]);
        return acc;
      }
      const lastList = acc[acc.length - 1];
      const lastKey = groupFn(lastList[0]);
      const curKey = groupFn(item);
      if (lastKey === curKey) {
        lastList.push(item);
      } else {
        acc.push([item]);
      }
      return acc;
    }, []);
  };

  // src/monkey/copymanga-enhance/scripts/constant.ts
  var ComicDirection = /* @__PURE__ */ ((ComicDirection2) => {
    ComicDirection2["LTR"] = "ltr";
    ComicDirection2["RTL"] = "rtl";
    ComicDirection2["TTB"] = "ttb";
    return ComicDirection2;
  })(ComicDirection || {});
  var ClickAction = /* @__PURE__ */ ((ClickAction2) => {
    ClickAction2["PREV_PAGE"] = "prev_page";
    ClickAction2["NEXT_PAGE"] = "next_page";
    return ClickAction2;
  })(ClickAction || {});
  var ActionZones = [{
    names: ["left", "prev_page" /* PREV_PAGE */]
  }, {
    names: ["top", "right", "prev_page" /* PREV_PAGE */]
  }, {
    names: ["bottom", "right", "next_page" /* NEXT_PAGE */]
  }];

  // src/monkey/copymanga-enhance/scripts/new-vue-mixin/action.ts
  var ActionMixin = () => ({
    computed: {
      ClickAction: () => ClickAction,
      ActionZones: () => ActionZones.map(
        (zone) => ({
          names: zone.names.concat($.isWindow(window) ? ["windows"] : []).filter(Boolean)
        })
      )
    },
    methods: {
      onJumpPage(nextAction) {
        const that = this;
        const element = document.body;
        const containerElement = document.getElementsByClassName("images")[0];
        const containerScrollTo = genScrollTo(containerElement);
        const headerHeight = document.getElementsByClassName("header")[0].clientHeight;
        if (["ltr" /* LTR */, "rtl" /* RTL */].includes(that.mode)) {
          const offsetTops = [...document.getElementsByClassName("comic")].map((el) => el.offsetTop - headerHeight);
          const currentTop = containerElement.scrollTop;
          for (let i = 0; i < offsetTops.length - 1; i++) {
            if (nextAction === "prev_page" /* PREV_PAGE */) {
              if (offsetTops[i] < currentTop && offsetTops[i + 1] >= currentTop) {
                containerScrollTo(offsetTops[i], true);
                break;
              }
            }
            if (nextAction === "next_page" /* NEXT_PAGE */) {
              if (offsetTops[i] <= currentTop && offsetTops[i + 1] > currentTop) {
                containerScrollTo(offsetTops[i + 1], true);
                break;
              }
            }
          }
        } else if (that.mode === "ttb" /* TTB */) {
          let nextTop = nextAction === "prev_page" /* PREV_PAGE */ ? containerElement.scrollTop - element.clientHeight : containerElement.scrollTop + element.clientHeight;
          nextTop += headerHeight;
          nextTop = Math.max(0, nextTop);
          containerScrollTo(nextTop, true);
        }
      },
      onActionZoneClick(zone) {
        const that = this;
        const { names } = zone;
        const nextAction = [
          names.includes("prev_page" /* PREV_PAGE */) ? "prev_page" /* PREV_PAGE */ : void 0,
          names.includes("next_page" /* NEXT_PAGE */) ? "next_page" /* NEXT_PAGE */ : void 0
        ].filter(Boolean)[0];
        that.onJumpPage(nextAction);
      },
      onActionZoneWheel(event) {
        const containerElement = document.getElementsByClassName("images")[0];
        const containerScrollTo = genScrollTo(containerElement);
        containerScrollTo(containerElement.scrollTop - event.wheelDeltaY * 2, true);
      }
    },
    mounted() {
      const that = this;
      window.addEventListener("keyup", ({ code }) => {
        switch (code.toLowerCase()) {
          case "ArrowLeft".toLowerCase():
            that.prevUrl && (window.location.href = that.prevUrl);
            break;
          case "ArrowRight".toLowerCase():
            that.nextUrl && (window.location.href = that.nextUrl);
            break;
          case "ArrowUp".toLowerCase():
            that.onJumpPage("prev_page" /* PREV_PAGE */);
            break;
          case "Space".toLowerCase():
          case "ArrowDown".toLowerCase():
            that.onJumpPage("next_page" /* NEXT_PAGE */);
            break;
          case "MetaLeft".toLowerCase():
          case "ControlLeft".toLowerCase():
            that.hasWhitePage = false;
            break;
          case "MetaRight".toLowerCase():
          case "ControlRight".toLowerCase():
            that.hasWhitePage = true;
            break;
        }
      });
    }
  });
  var action_default = ActionMixin;

  // src/monkey/copymanga-enhance/scripts/new-vue-mixin/image.ts
  var ImageMixin = (info) => ({
    data: {
      hasWhitePage: JSON.parse(sessionStorage.getItem(`${comic}.hasWhitePage.${chapter}`) || "false")
    },
    computed: {
      currentImageCount() {
        const that = this;
        return that.imageInfos.filter(Boolean).length;
      },
      totalImageCount() {
        const that = this;
        return that.imageInfos.length;
      },
      isAllImagesLoaded() {
        const that = this;
        return that.currentImageCount === that.totalImageCount;
      },
      canWhitePage() {
        const that = this;
        if (!["ltr" /* LTR */, "rtl" /* RTL */].includes(that.mode)) {
          return false;
        }
        return that.isAllImagesLoaded;
      },
      whitePageIndex() {
        const that = this;
        if (!that.hasWhitePage || !that.isAllImagesLoaded) return -1;
        const groupList = group(that.imageInfos, (info2) => info2?.type);
        if (groupList.length === 1) return 0;
        if (groupList.length >= 2) {
          const [firstList] = groupList;
          if (firstList.length !== 1 && firstList[0].type === "portrait" /* PORTRAIT */) return 0;
        }
        if (groupList.length >= 3) {
          const [firstList, secondList] = groupList;
          if (firstList.length === 1 && firstList[0].type === "portrait" /* PORTRAIT */) {
            return findIndex(
              that.imageInfos,
              (info2) => info2?.type === "portrait" /* PORTRAIT */,
              { startIndex: firstList.length + secondList.length }
            );
          }
        }
        return findIndex(that.imageInfos, (info2) => info2?.type === "portrait" /* PORTRAIT */);
      }
    },
    methods: {
      imageLoaded(e, index) {
        const that = this;
        const el = e.target;
        that.imageInfos.splice(index, 1, {
          width: el.width,
          height: el.height,
          type: el.width > el.height ? "landscape" /* LANDSCAPE */ : "portrait" /* PORTRAIT */
        });
        if (that.mode === "ltr" /* LTR */) {
        }
      },
      toggleWhitePage() {
        const that = this;
        that.hasWhitePage = !that.hasWhitePage;
      }
    },
    watch: {
      hasWhitePage(val) {
        sessionStorage.setItem(`${comic}.hasWhitePage.${chapter}`, JSON.stringify(val));
      }
    }
  });
  var image_default = ImageMixin;

  // src/monkey/copymanga-enhance/scripts/new-vue-mixin/init.ts
  var InitMixin = (info) => ({
    data: {
      ...info,
      imageInfos: Array(info.images.length).fill(void 0)
    }
  });
  var init_default = InitMixin;

  // src/monkey/copymanga-enhance/scripts/new-vue-mixin/mode.ts
  var ModeMixin = () => ({
    data: {
      mode: GM_getValue(`${comic}.direction.mode`, "rtl" /* RTL */)
    },
    computed: {
      ComicDirection: () => ComicDirection
    },
    methods: {
      selectMode(evt) {
        const value = evt.target?.value;
        this.switchMode(value);
        GM_setValue(`${comic}.direction.mode`, value);
      },
      switchMode(mode) {
        const that = this;
        that.mode = mode;
      }
    }
  });
  var mode_default = ModeMixin;

  // src/monkey/copymanga-enhance/scripts/new.ts
  var render = ({ info, preFn = Function }) => {
    preFn();
    new Vue({
      el: "#app",
      mixins: [
        init_default(info),
        mode_default(),
        action_default(),
        image_default(info)
      ]
    });
  };

  // src/monkey/copymanga-enhance/scripts/old.ts
  var getCurrentCount = () => $(".comicContent-list > li > img").length;
  var getTotalCount = () => Number(document.getElementsByClassName("comicCount")[0].innerText);
  var windowScrollTo = genScrollTo(window);
  var refreshImage = (cb) => {
    const nextTime = 15;
    let [cur, total] = [getCurrentCount(), getTotalCount()];
    console.log("Process:", getCurrentCount(), "/", getTotalCount());
    if (total === 0 || cur < total) {
      windowScrollTo(document.getElementsByClassName("comicContent")[0].clientHeight, true);
      cur = getCurrentCount();
      setTimeout(() => {
        windowScrollTo(0);
        setTimeout(() => refreshImage(cb), nextTime);
      }, nextTime);
      return;
    }
    cb();
  };
  var getPageInfo = () => {
    const list = [];
    $(".comicContent-list > li > img").each((_, el) => {
      list.push($(el).data("src"));
    });
    const footerElements = $(".footer a");
    const info = {
      images: list,
      title: $(".header").get(0)?.innerText,
      menuUrl: footerElements.get(3)?.href,
      prevUrl: footerElements.get(1)?.className.includes("prev-null") ? void 0 : footerElements.get(1)?.href,
      nextUrl: footerElements.get(2)?.className.includes("prev-null") ? void 0 : footerElements.get(2)?.href
    };
    console.log("PageInfo:", info);
    return info;
  };

  // src/monkey/copymanga-enhance/index.ts
  var sessionStorageKey = `${comic}.info.${chapter}`;
  var renderNewPage = (info) => render({
    info,
    preFn: () => {
      document.body.innerHTML = template_default;
      GM_addStyle(style_default);
    }
  });
  setTimeout(() => {
    let cacheContent = sessionStorage.getItem(sessionStorageKey);
    if (cacheContent) {
      const info = {
        prevUrl: void 0,
        nextUrl: void 0,
        menuUrl: void 0,
        ...JSON.parse(cacheContent)
      };
      return renderNewPage(info);
    }
    refreshImage(() => {
      windowScrollTo(0);
      const info = getPageInfo();
      sessionStorage.setItem(sessionStorageKey, JSON.stringify(info));
      renderNewPage(info);
    });
  }, 25);
})();