
const ORDER = {
  "started": 1,
  "completed": 1,
  "stopped": 2,
  null: 3
};
const sites = new Set()
const TAG_COLORS = ["#d32d41", "#00312f", "#0059ff", "#2c8", "#ffa500"]
const MAX_COLORS = TAG_COLORS.length

// function PyMRF(props) {

//     async toggleShowAnnounces(ctx) {
//       if (this.ctxShowAnnounces.includes(ctx.id)) {
//         this.ctxShowAnnounces = this.ctxShowAnnounces.filter(id => id !== ctx.id)
//       } else {
//         this.ctxShowAnnounces.push(ctx.id)
//         const res = await fetch("/api/get-announces/" + ctx.id);
//         var announces = await res.json()
//         this.announcesOfCtx[ctx.id] = announces
//       }
//     },
//     showShowAnnounces(ctx) {
//       return this.ctxShowAnnounces.includes(ctx.id)
//     },
//   }
// }

const convertSize = (sizeBytes) => {
  if (sizeBytes === undefined || sizeBytes === null) {
    return 0
  }
  sizeBytes = parseInt(sizeBytes)
  if (sizeBytes === 0) {
    return "0B";
  }
  var sizeName = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
  var i = Math.floor(Math.log(sizeBytes) / Math.log(1024));
  var p = Math.pow(1024, i);
  var s = (sizeBytes / p).toFixed(2);
  return s + " " + sizeName[i];
}

const shareRatio = (ctx) => {
  const download = ctx.total_download + ctx.session_download
  return download > 0 ? Math.round(1000 * (ctx.total_upload_actual + ctx.session_upload_actual) / download) / 1000 : 0
}

const cpValue = (ctx) => {
  if (ctx.leechers <= 3) {
    return "N/A";
  }
  const result = Math.round(100 * ctx.leechers / (ctx.size / 1024 / 1024 / 1024)) / 100;
  let attitude;
  if (result >= 3) {
    attitude = "🔥🔥";
  } else if (result >= 1) {
    attitude = "🔥";
  } else {
    attitude = "💩";
  }
  return attitude + " " + result;
}

const bool2YN = (val) => {
  return val ? "Y" : "N";
};

const formatTimedeltaToHHMMSS = (tdInSeconds) => {
  var hours = Math.floor(tdInSeconds / 3600);
  var remainder = tdInSeconds % 3600;
  var minutes = Math.floor(remainder / 60);
  var seconds = remainder % 60;

  hours = parseInt(hours, 10);
  minutes = parseInt(minutes, 10);
  seconds = parseInt(seconds, 10);

  if (minutes < 10) {
    minutes = "0" + minutes;
  }
  if (seconds < 10) {
    seconds = "0" + seconds;
  }

  return hours + ":" + minutes + ":" + seconds;
};

const timeDifference = (dateTime) => {
  var givenDateTime = new Date(dateTime.replace(/GMT$/, ""));

  var currentDateTime = this.now;
  var diffInSeconds = (currentDateTime - givenDateTime) / 1000;

  var hours = Math.floor(diffInSeconds / 3600);
  var remainder = diffInSeconds % 3600;
  var minutes = Math.floor(remainder / 60);
  var seconds = Math.floor(remainder % 60);

  hours = String(hours).padStart(2, '0');
  minutes = String(minutes).padStart(2, '0');
  seconds = String(seconds).padStart(2, '0');

  return hours + ":" + minutes + ":" + seconds;
};

const formatInfoHash = (info_hash) => {
  let hexString = info_hash.replace(/%/g, ''); // Remove '%' characters
  hexString = hexString.toLowerCase(); // Ensure consistent case for hex values
  return hexString.slice(0, 4) + '...' + hexString.slice(-4);
};

const percentage = (val) => {
  return Math.round(val * 100) + "%";
};

const harvest = (id, kind) => {
  console.log("Harvesting..." + id + kind)

  fetch('/api/do-harvest', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      torrent_id: id,
      harvest_kind: kind
    })
  })
};

const stopHarvestor = () => {
  fetch('/api/stop-harvestor', { method: 'POST' });
};

const tagColorBySite = (site) => {
  const index = Array.from(sites).indexOf(site);
  return {
    backgroundColor: TAG_COLORS[index % MAX_COLORS]
  };
};

const { ref, onMounted } = Vue;

const PyMRF = {
  setup () {
    console.log(`PyMRF 4 started.`)

    const allCtx = ref([])
    const totalUploadSpeed = ref(0)
    const foldedItems = ref([])
    const ctxShowAnnounces = ref([])
    const announcesOfCtx = ref({})
    const now = ref(new Date())
    const harvestor = ref({
      running: false,
      speed: 0,
      progress: 0
    })

    const getAllCtx = async () => {
      const responses = await Promise.all([fetch("/api/get-recent-torrents"), fetch("/api/get-last-announces")])
      let torrents = await responses[0].json()
      const lastAnnounces = await responses[1].json()

      foldedItems.value = torrents.filter(t => t.is_folded)

      torrents = torrents
        .filter(t => t.is_folded === false)
        .sort((a, b) => {
          if (a.last_event == b.last_event) {
            if (a.last_announced_at < b.last_announced_at) return 1;
            if (a.last_announced_at > b.last_announced_at) return -1;
            return 0;
          } else {
            return ORDER[a.last_event] - ORDER[b.last_event];
          }
        });
      torrents.forEach(ctx => {
        ctx.upload_speed = lastAnnounces.filter(announce => announce.torrent == ctx.id)[0]?.upload_speed;
        sites.add(ctx.site);
      });

      updateItems(torrents);
      totalUploadSpeed.value = lastAnnounces.map(announce => announce.upload_speed).reduce((prev, curr) => prev + curr, 0)

      setTimeout(getAllCtx, 1500);
    }

    const updateItems = (torrents) => {
      const DYN_KEYS = ["last_announced_at"]
      // Step 1: Create a map for quick lookup of existing items by their unique ID
      const itemsMap = {};
      allCtx.value.forEach(item => {
        itemsMap[item.id] = item;
      });

      // Step 2: Process each item from the server response
      torrents.forEach(newItem => {
        const existingItem = itemsMap[newItem.id];
        if (existingItem) {
          // Step 2a: Update properties of the existing item
          Object.keys(newItem).forEach(key => {
            // Only update if the value has changed
            if (DYN_KEYS.indexOf(key) >= 0 || existingItem[key] !== newItem[key]) {
              existingItem[key] = newItem[key];
            }
          });
        } else {
          // Step 2b: Add new item to 'this.allCtx' array
          allCtx.value.push(newItem);
        }
      });

      // Step 3: Remove items that are no longer present in the server response
      const responseIds = new Set(torrents.map(item => item.id));
      for (let i = allCtx.value.length - 1; i >= 0; i--) {
        const item = allCtx.value[i];
        if (!responseIds.has(item.id)) {
          allCtx.value.splice(i, 1); // Removes the item from the array
        }
      }
    }


    const refreshHarvestor = async () => {
      const res = await fetch("/api/get-harvestor-status");
      const harvestorStatus = await res.json();
      harvestor.value = harvestorStatus;
    };

    onMounted(() => {
      // setInterval(getAllCtx, 1500)
      getAllCtx();

      setInterval(() => {
        now.value = new Date()
      }, 2000)
      setInterval(refreshHarvestor, 1000)
    })

    const fold = (id) => {
      allCtx.value = allCtx.value.filter(ctx => ctx.id !== id)
      fetch(`/api/torrent/${id}/fold`, { method: 'POST' });
    };

    const unfoldAll = () => {
      fetch(`/api/torrent/unfoldAll`, { method: 'POST' });
      getAllCtx();
    };

    const autoFold = async () => {
      await fetch(`/api/torrent/autoFold`, { method: 'POST' });
      getAllCtx();
    }

    return {
      // state
      allCtx,
      totalUploadSpeed,
      foldedItems,
      ctxShowAnnounces,
      announcesOfCtx,
      now,
      harvestor,

      // util functions
      convertSize,
      shareRatio,
      bool2YN,
      formatTimedeltaToHHMMSS,
      timeDifference,
      formatInfoHash,
      percentage,
      cpValue,

      harvest,
      refreshHarvestor,
      stopHarvestor,
      tagColorBySite,
      fold,
      autoFold,
      // unfold,
      unfoldAll,
    }
  }
}

export { PyMRF }