(() => {

// quick reply spoiler fix
(() => {
  const addspoiler = () => {
    $qr = $('#quick-reply')
    if (($qr.length == 0) || ($qr.find('input[name="spoiler"]').length != 0)) return;
    $qr.find('div.banner').append(' ', $('<span></span>').attr("title", _('Spoiler Image')).append($('<input id="q-spoiler-image" name="spoiler" type="checkbox">'), $('<label for="q-spoiler-image">').text("SI")))
  };
  addspoiler()
  $(window).on('quick-reply', addspoiler)
})();

// catalog links
Array.from (document.querySelectorAll ("div.boardlist a")).filter (a => a.hasAttribute ("href")).forEach (a => {
  href = a.getAttribute ("href")
  ma   = href.match (/^(\/[^\/]+\/)index.html$/)
  if (ma != null) {
    cata = ma [1] + "catalog.html"
  } else if (href == "/overboard/") {
    cata = "/overboard/catalog.html"
  } else {
    cata = null
  }
  if (cata != null) {
    e = document.createElement ("a")
    e.setAttribute ("href", cata)
    e.innerText = "+"
    if (a.hasAttribute ("title")) {
      e.setAttribute ("title", a.getAttribute ("title") + " - Catalog")
    }
    a.insertAdjacentElement ("afterend", e)
  }
});

// thread stats + Unique IPs
(() => {
  $('.clear').after($('#thread_stats'))
  $('#uniqueip > span').attr('style', 'display: block;  float:   right;  margin:  0em 1em;')
})();

// post filter individual hiding
(() => {
  const pcid2tid = (board, pcid) => {
    const n = document.querySelector ('[data-board="' + board + '"].thread > div#' + pcid)
    return n == null ? null : n.parentNode.getAttribute ('id').replace ('thread_', '')
  }
  const merge = (have, posts) => {
    let changed = false
    for (p of posts) {
      if (!have.some (e => e.post === p.post)) {
        have.push (p)
        changed = true
      }
    }
    return changed
  }
  const fixids = () => {
    let lspf    = JSON.parse (localStorage.postFilter)
    let changed = false
    for (const [board, threads] of Object.entries (lspf.postFilter)) {
      for (const [id, posts] of Object.entries (threads)) {
        if (!id.startsWith ('pc')) { continue; }
        const tid = pcid2tid (board, id)
        if (tid == null) { continue; }
        if (tid in threads) {
          const have = threads [tid]
          if (merge (have, posts)) { changed = true; }
        } else {
          threads [tid] = posts
          changed = true
        }
        delete threads [id]
      }
    }
    if (changed) {
      lspf = JSON.stringify (lspf)
      localStorage.postFilter = lspf
      $(document).trigger('filter_page')
    }
  }
  fixids ()
  $(document).on('filter_page', fixids)

  // post-filter.js
  const removepost = function (boardId, threadId, postId) {
    const list   = JSON.parse (localStorage.postFilter)
    const filter = list.postFilter

    // thread already pruned
    if (typeof filter[boardId] == 'undefined' || typeof filter[boardId][threadId] == 'undefined') return;

    for (var i=0; i<filter[boardId][threadId].length; i++) {
      if (filter[boardId][threadId][i].post == postId) {
        filter[boardId][threadId].splice(i, 1);
        break;
      }
    }

    if ($.isEmptyObject(filter[boardId][threadId])) {
      delete filter[boardId][threadId];
      delete list.nextPurge[boardId][threadId];

      if ($.isEmptyObject(filter[boardId])) {
        delete filter[boardId];
        delete list.nextPurge[boardId];
      }
    }

    localStorage.postFilter = JSON.stringify (list)
  }

  Menu.onclick(function (e, $buffer) {
    var ele      = e.target.parentElement.parentElement;
    var $ele     = $(ele);
    var threadId = $ele.parents('.thread').attr('id').replace('thread_', '');
    var boardId  = $ele.parent().data('board');
    var postId   = $ele.find('.post_no').not('[id]').text();

    if ($ele.data('hidden')) {
      $buffer.find('#filter-menu-unhide').click(function () {
        removepost(boardId, threadId, postId)
        $(document).trigger('filter_page')
      })
    }
  })
})();

// sorted, labeled style selector
(() => {
  $('#style-select > select').before ('Select theme: ')
  const selected = $('div.styles > a.selected').attr ('id').replace ('style-select-', '')
  const stylesSelect = $('<select></select>').css ({float: "none"})

  Array.from (document.querySelectorAll ('div.styles > a')).map (a => [a.innerText.replace (/^\[(.+)\]$/, '$1'), a.getAttribute ('id').replace ('style-select-', '')]).sort ((a, b) => {
    const au = a [0].toUpperCase ()
    const bu = b [0].toUpperCase ()
    if (au < bu) { return -1; }
    if (au > bu) { return  1; }
    return 0
  }).forEach (([name, id]) => {
    const opt = $('<option></option>').html(name).val(id)
    if (id === selected) { opt.attr('selected', true); }
    stylesSelect.append(opt)
  })

  $('#style-select > select').detach ()
  stylesSelect.change(function() {
    $('#style-select-' + $(this).val()).click()
  })
  $('#style-select').append (stylesSelect)
})();

// batch video loop/once
(() => {
  if (!(window.Options && localStorage && document.querySelector ('div.post.op') && Options.get_tab ('webm'))) { return; }

  const setloopsto = (root, loop) => {
    if (typeof setupVideosIn === "function") {
      // expand-video.js
      const label = loop ? '[loop]' : '[play once]'
      $(root).find ('p.fileinfo > span').filter ((k, e) => e.innerText === label).each ((k, e) => e.click ())
    } else {
      const flag = loop ? '1' : '0'
      Array.from (root.querySelectorAll ("div.file > a.file")).filter (e => e.hasAttribute ("href")).map (e => [e, e.getAttribute ("href").match (/^(\/player[.]php[?].+&loop=)([01])$/)]).filter (e_match => e_match [1] != null).forEach (e_match => e_match [0].setAttribute ("href", e_match [1] [1] + flag))
    }
  }

  const prefix  = 'videoloop-'
  const getcb   = (name) => document.getElementById (prefix + name)
  const checked = (name) => getcb (name).checked
  const cbset   = (name, flag) => { getcb (name).checked = flag; }

  const addgui = () => {
    const vlautoset = ((localStorage [prefix + "autoset"] || "false") === "true")
    const vlonoff   = ((localStorage [prefix + "onoff"  ] || "true" ) === "true")
    const gui       = '<span>'
      + _('Loop:')
      + ' <label><input type="checkbox" id="' + prefix + 'onoff">'   + _('On')       + '</label>'
      + ' <label><input type="checkbox" id="' + prefix + 'autoset">' + _('Auto set') + '</label>'
      + ' <button id="' + prefix + 'setnow">' + _('Set now') + '</button>'
      + '</span>';
    Options.extend_tab ("webm", gui)
    cbset ('autoset', vlautoset)
    cbset ('onoff',   vlonoff)
    $('#' + prefix + 'autoset, #' + prefix + 'onoff').on("change", (ev) => {
      const cb = ev.target
      localStorage [cb.getAttribute ("id")] = cb.checked ? "true" : "false"
    })
    $('#' + prefix + 'setnow').on("click", () => {
      setloopsto (document, checked ('onoff'))
    })
  }

  addgui()
  if (checked ('autoset')) {
    setloopsto (document, checked ('onoff'))
  }
  $(document).on('new_post', function (ev, post) {
    if (checked ('autoset')) {
      if (typeof setupVideosIn === "function") {
        // preempt MutationObserver
        setupVideosIn (post)
      }
      setloopsto (post, checked ('onoff'))
    }
  })
})();

// top/bottom navlinks
(() => {
  const makea = (href, title, html) => {
    const a = document.createElement ("a")
    a.setAttribute ('href', href)
    a.setAttribute ('title', title)
    a.innerHTML = html
    return a
  }
  if (document.querySelectorAll ('div.post.op').length == 1) {
    const span = document.createElement ("span")
    span.setAttribute ('id',    'topbottom-boardlist-navlinks')
    span.setAttribute ('style', 'float:right;')
    span.appendChild (makea ('#top',    'Go to top',    '&#x25B2;'))
    span.appendChild (makea ('#bottom', 'Go to bottom', '&#x25BC;'))
    document.querySelector ('div.boardlist').appendChild (span)
  }
})();

// generic file thumbs
Array.from (document.getElementsByTagName ('img')).filter (e => e.hasAttribute ('src')).map (e => [e, e.getAttribute ('src').match (/^\/([^\/]+)\/thumb\/file$/)]).filter (([e, m]) => m != null).forEach (([e, m]) => e.setAttribute ('src', '/static/file.png'));

// overboard catalog sort
(() => {
  if ((active_page != 'catalog') || (board_name != "overboard")) { return; }
  const state = { added: false }
  $("#sort_by").change((e) => {
    if (state.added) { return; }
    state.added = true
    $('#Grid').on('mixEnd', (ev, st) => {
      as = st.activeSort
      if ((typeof as === 'string') && as.startsWith ('sticky:desc ')) {
        $('#Grid').mixItUp('sort', as.replace ('sticky:desc ', ""))
      }
    })
  })
})();

// threadlinks-noup
(() => {
  if (active_page !== "thread") { return; }
  const added = ' [ <span class="threadlink"><a href="/' + board_name + '/catalog.html">Catalog</a></span> / <span class="threadlink"><a href="/">Home</a></span> ]'
  document.querySelector ('div.threadlinks-noup').innerHTML += added
})();

})()