/**
 * assistant.html — 随堂测发布弹窗 + 发布后统计/排行榜（轮询）+ 送奖杯
 * 随堂测 eva 发布/送奖走 assistantsdk：DWLive.hdPublishPractice / hdSendPracticePrize
 * 统计仍用 DWLive.getPracticeStatisInfo（view 域名 interaction）
 */
;(function ($) {
  var LETTERS = ['A', 'B', 'C', 'D', 'E', 'F']
  var TYPE_MAP = { radio: 1, checkbox: 2, judge: 0 }
  var JUDGE_OPTS = [
    { id: 0, label: '对' },
    { id: 1, label: '错' }
  ]

  var state = {
    questionType: 'radio',
    optionsNum: 4,
    options: [],
    correctAnswer: false,
    correctAnswers: [],
    requesting: false
  }

  var poll = {
    on: false,
    pid: null,
    publisherId: '',
    updateTimer: null,
    countTimer: null,
    countBase: 0,
    closed: false,
    practiceStatus: 0
  }

  var dwHooksBound = false
  var cupViewerIds = []
  var prizeSending = false
  var prizePending = { id: '', name: '' }

  function cupHas(id) {
    var sid = String(id)
    for (var i = 0; i < cupViewerIds.length; i++) {
      if (String(cupViewerIds[i]) === sid) return true
    }
    return false
  }

  function addCup(id) {
    if (id == null || id === '') return
    if (!cupHas(id)) cupViewerIds.push(id)
  }

  function clearCups() {
    cupViewerIds = []
  }

  function syncRankCupPrized() {
    var nodes = document.querySelectorAll('#practice-result-rank-list .demo-practice-result-rank-cup')
    for (var i = 0; i < nodes.length; i++) {
      var nid = nodes[i].getAttribute('data-viewer-id')
      if (nid != null && cupHas(nid)) nodes[i].classList.add('is-prized')
      else nodes[i].classList.remove('is-prized')
    }
  }

  function escapeHtml(s) {
    if (s == null) return ''
    return String(s)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
  }

  /** 解析 assistantsdk 回调体（兼容 axios 形态 { data }） */
  function unwrapSdkRes(res) {
    if (res == null || typeof res === 'number') return null
    if (typeof res === 'object' && res.data !== undefined) return res.data
    return res
  }

  function formatSeconds(value) {
    var result = parseInt(value, 10)
    if (isNaN(result) || result < 0) result = 0
    var m = Math.floor(result / 60)
    var s = Math.floor(result % 60)
    var ms = (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s
    return ms
  }

  function extractPractice(raw) {
    if (!raw || typeof raw !== 'object') return null
    if (raw.data && raw.data.practice) return raw.data.practice
    if (raw.datas && raw.datas.practice) return raw.datas.practice
    if (raw.practice) return raw.practice
    return null
  }

  function labelForContext(ctx) {
    if (ctx === 'dui') return '对'
    if (ctx === 'cuo') return '错'
    return ctx
  }

  function formatCorrectPercent(v) {
    if (v == null) return '0%'
    if (typeof v === 'number') return v + '%'
    var s = String(v)
    return s.indexOf('%') === -1 ? s + '%' : s
  }

  /** 对齐运营端 user.id：随堂测 publisherId 为观众 id（viewerid） */
  function getSelfViewerId() {
    return typeof DWLive !== 'undefined' && DWLive.viewerid != null ? String(DWLive.viewerid) : ''
  }

  function isMyPublisher(publisherId) {
    var selfId = getSelfViewerId()
    return !!(selfId && publisherId != null && String(publisherId) === selfId)
  }

  function hasResumablePractice() {
    return !!(poll.pid && isMyPublisher(poll.publisherId))
  }

  function isOpen() {
    var m = document.getElementById('practice-modal-mask')
    return !!(m && m.classList.contains('is-open'))
  }

  function isResultOpen() {
    var m = document.getElementById('practice-result-mask')
    return !!(m && m.classList.contains('is-open'))
  }

  function isPrizeOpen() {
    var m = document.getElementById('practice-prize-mask')
    return !!(m && m.classList.contains('is-open'))
  }

  function openPrizeModal(id, name) {
    prizePending.id = id != null ? String(id) : ''
    prizePending.name = name != null ? String(name) : ''
    var sp = document.getElementById('practice-prize-name')
    if (sp) sp.textContent = prizePending.name || '—'
    var mask = document.getElementById('practice-prize-mask')
    if (mask) {
      mask.classList.add('is-open')
      mask.setAttribute('aria-hidden', 'false')
    }
  }

  function closePrizeModal() {
    prizePending.id = ''
    prizePending.name = ''
    var mask = document.getElementById('practice-prize-mask')
    if (mask) {
      mask.classList.remove('is-open')
      mask.setAttribute('aria-hidden', 'true')
    }
    var ok = document.getElementById('practice-prize-ok')
    if (ok) ok.disabled = false
  }

  function confirmSendPrize() {
    if (prizeSending) return
    var id = prizePending.id
    var name = prizePending.name
    if (!id || typeof DWLive === 'undefined' || !DWLive.userid || !DWLive.roomid) {
      window.alert('缺少登录信息')
      return
    }
    if (typeof DWLive.hdSendPracticePrize !== 'function') {
      window.alert('请更新 assistantsdk（需包含 hdSendPracticePrize）')
      return
    }
    prizeSending = true
    var okBtn = document.getElementById('practice-prize-ok')
    if (okBtn) okBtn.disabled = true
    DWLive.hdSendPracticePrize({ viewerId: id, viewerName: name || '', type: 1 }, function (res) {
      prizeSending = false
      if (okBtn) okBtn.disabled = false
      var root = unwrapSdkRes(res)
      if (!root) {
        window.alert('请求失败（网络或跨域）')
        return
      }
      var success = root.success === true || root.success === 'true'
      if (success) {
        addCup(id)
        closePrizeModal()
        syncRankCupPrized()
      } else {
        window.alert((root && root.msg) || '发送失败')
      }
    })
  }

  function isCloseTipOpen() {
    var m = document.getElementById('practice-close-tip-mask')
    return !!(m && m.classList.contains('is-open'))
  }

  function openCloseTipModal() {
    var mask = document.getElementById('practice-close-tip-mask')
    if (mask) {
      mask.classList.add('is-open')
      mask.setAttribute('aria-hidden', 'false')
    }
  }

  function closeCloseTipModal() {
    var mask = document.getElementById('practice-close-tip-mask')
    if (mask) {
      mask.classList.remove('is-open')
      mask.setAttribute('aria-hidden', 'true')
    }
  }

  function pauseResultPoll() {
    poll.on = false
    if (poll.updateTimer) {
      clearTimeout(poll.updateTimer)
      poll.updateTimer = null
    }
    if (poll.countTimer) {
      clearInterval(poll.countTimer)
      poll.countTimer = null
    }
  }

  function hideResultModal() {
    closePrizeModal()
    closeCloseTipModal()
    var mask = document.getElementById('practice-result-mask')
    if (mask) {
      mask.classList.remove('is-open')
      mask.setAttribute('aria-hidden', 'true')
    }
    pauseResultPoll()
  }

  function closePracticeApi() {
    var pid = poll.pid
    if (!pid || typeof DWLive === 'undefined' || typeof DWLive.hdClosePractice !== 'function') {
      closeResultModal()
      return
    }
    var btn = document.getElementById('practice-result-action')
    if (btn) btn.disabled = true
    DWLive.hdClosePractice(pid, function (res) {
      if (btn) btn.disabled = false
      var root = unwrapSdkRes(res)
      if (root && (root.success === true || root.success === 'true')) {
        closeResultModal()
      } else {
        window.alert((root && root.msg) || '关闭失败，请稍后再试')
      }
    })
  }

  function stopPracticeApi() {
    var pid = poll.pid
    if (!pid || typeof DWLive === 'undefined' || typeof DWLive.hdStopPractice !== 'function') {
      window.alert('请更新 assistantsdk（需包含 hdStopPractice）')
      return
    }
    var btn = document.getElementById('practice-result-action')
    if (btn) btn.disabled = true
    DWLive.hdStopPractice(pid, function (res) {
      if (btn) btn.disabled = false
      var root = unwrapSdkRes(res)
      if (root && (root.success === true || root.success === 'true')) {
        poll.closed = true
        poll.practiceStatus = 2
        pauseResultPoll()
        if (typeof DWLive.getPracticeStatisInfo === 'function') {
          DWLive.getPracticeStatisInfo(pid, function (res2) {
            var p = extractPractice(res2)
            if (p) renderPracticeResult(p)
          })
        } else {
          syncResultActionBtn()
        }
      } else {
        window.alert((root && root.msg) || '网络错误，请稍后再试')
      }
    })
  }

  function syncResultActionBtn() {
    var btn = document.getElementById('practice-result-action')
    if (!btn) return
    if (!isMyPublisher(poll.publisherId)) {
      btn.hidden = true
      return
    }
    btn.hidden = false
    btn.textContent = poll.closed ? '关闭' : '停止答题'
  }

  function onResultActionClick() {
    if (!poll.pid || !isMyPublisher(poll.publisherId)) return
    if (!poll.closed) stopPracticeApi()
    else closePracticeApi()
  }

  function requestCloseResult() {
    if (!poll.closed) {
      openCloseTipModal()
      return
    }
    closePracticeApi()
  }

  function confirmCloseResult() {
    closeCloseTipModal()
    hideResultModal()
    if (poll.practiceStatus === 2) closePracticeApi()
  }

  function stopPoll() {
    pauseResultPoll()
  }

  function openResultModal() {
    var mask = document.getElementById('practice-result-mask')
    if (!mask) return
    mask.classList.add('is-open')
    mask.setAttribute('aria-hidden', 'false')
  }

  function closeResultModal() {
    closePrizeModal()
    closeCloseTipModal()
    var mask = document.getElementById('practice-result-mask')
    if (!mask) return
    mask.classList.remove('is-open')
    mask.setAttribute('aria-hidden', 'true')
    stopPoll()
    poll.pid = null
    poll.publisherId = ''
    poll.closed = false
    poll.practiceStatus = 0
    clearCups()
    syncResultActionBtn()
  }

  function restartCountTimer(status, stopTime) {
    if (poll.countTimer) {
      clearInterval(poll.countTimer)
      poll.countTimer = null
    }
    poll.countBase = parseInt(stopTime, 10) || 0
    var el = document.getElementById('practice-result-timer')
    if (el) el.textContent = formatSeconds(poll.countBase)
    if (status !== 1) return
    poll.countTimer = setInterval(function () {
      poll.countBase++
      var el2 = document.getElementById('practice-result-timer')
      if (el2) el2.textContent = formatSeconds(poll.countBase)
    }, 1000)
  }

  function renderPracticeResult(practice) {
    if (!practice || !practice.statistic) return
    var statistic = practice.statistic
    var typ = practice.type
    var lettersRow = typ === 0 ? ['dui', 'cuo'] : LETTERS.slice()
    var rawOpts = statistic.options ? statistic.options.slice() : []
    var i
    var html = ''
    for (i = 0; i < rawOpts.length; i++) {
      var item = rawOpts[i]
      var ctx = lettersRow[i] != null ? lettersRow[i] : LETTERS[i] || String(i)
      var isCorrect = Number(item.correct) === 1
      var pct = item.percent != null ? String(item.percent) : '0%'
      var w = pct.indexOf('%') === -1 ? pct + '%' : pct
      html +=
        '<dd class="' +
        (isCorrect ? 'is-correct' : '') +
        '">' +
        '<span class="demo-practice-result-badge">' +
        escapeHtml(labelForContext(ctx)) +
        '</span>' +
        '<div class="demo-practice-result-row-main">' +
        '<div class="demo-practice-result-meta"><span class="cnt">' +
        (item.count != null ? item.count : 0) +
        '人</span><span class="pct">(' +
        escapeHtml(pct) +
        ')</span></div>' +
        '<div class="demo-practice-result-bar"><span style="width:' +
        escapeHtml(w) +
        '"></span></div>' +
        '</div></dd>'
    }
    var statEl = document.getElementById('practice-result-stat-list')
    if (statEl) statEl.innerHTML = html

    var ranking = practice.ranking ? practice.ranking.slice(0, 10) : []
    var rankHtml = ''
    for (i = 0; i < ranking.length; i++) {
      var r = ranking[i]
      var uid = r.userId != null ? r.userId : r.viewerId
      var uname = r.userName || r.name || '—'
      var hasUid = uid != null && String(uid) !== ''
      var prized = hasUid && cupHas(uid)
      rankHtml +=
        '<li><span class="demo-practice-result-rank-num">' +
        (i + 1) +
        '</span><span class="demo-practice-result-rank-name">' +
        escapeHtml(uname) +
        '</span><span class="demo-practice-result-rank-time">' +
        escapeHtml(formatSeconds(r.costTime != null ? r.costTime : 0)) +
        '</span><span role="button" tabindex="0" class="demo-practice-result-rank-cup' +
        (prized ? ' is-prized' : '') +
        '" title="' +
        (prized ? '已送奖杯' : '送奖杯') +
        '" data-viewer-id="' +
        escapeHtml(hasUid ? String(uid) : '') +
        '" data-viewer-name="' +
        escapeHtml(uname) +
        '">🏆</span></li>'
    }
    var rankEl = document.getElementById('practice-result-rank-list')
    if (rankEl) rankEl.innerHTML = rankHtml

    var ans = document.getElementById('practice-result-answered')
    if (ans) ans.textContent = '已有' + (statistic.answerCount != null ? statistic.answerCount : 0) + '人回答'
    var cor = document.getElementById('practice-result-correct')
    if (cor) cor.textContent = '正确率: ' + formatCorrectPercent(statistic.correctPercent)

    poll.practiceStatus = practice.status
    poll.closed = practice.status !== 1
    if (practice.publisherId != null) poll.publisherId = String(practice.publisherId)

    restartCountTimer(practice.status, practice.stopTime)
    syncResultActionBtn()
  }

  function fetchPracticeStats(pid, scheduleNext) {
    if (!poll.on || poll.pid !== pid) return
    if (typeof DWLive === 'undefined' || !DWLive.userid || typeof DWLive.getPracticeStatisInfo !== 'function') return
    DWLive.getPracticeStatisInfo(pid, function (res) {
      if (!poll.on || poll.pid !== pid) return
      var data = extractPractice(res)
      if (!data) {
        console.error('获取随堂测统计数据异常', res)
      } else {
        renderPracticeResult(data)
      }
      if (scheduleNext && poll.on && poll.pid === pid) {
        poll.updateTimer = setTimeout(function () {
          fetchPracticeStats(pid, true)
        }, 3000)
      }
    })
  }

  function beginPracticeStats(pid) {
    if (!pid) return
    stopPoll()
    clearCups()
    closePrizeModal()
    poll.pid = pid
    poll.on = true
    openResultModal()
    fetchPracticeStats(pid, true)
  }

  function chainDwLive(name, handler) {
    if (typeof DWLive === 'undefined') return
    var prev = DWLive[name]
    DWLive[name] = function () {
      var args = arguments
      if (typeof prev === 'function') {
        try {
          prev.apply(DWLive, args)
        } catch (e1) {}
      }
      try {
        handler.apply(null, args)
      } catch (e2) {
        console.warn('DemoPractice.' + name, e2)
      }
    }
  }

  // 监听到直播中且本人有进行中随堂测
  DWLive.onRoomOngoing = function (data) {
    if (data && data.success && data.data?.interaction) {
      const pid = data.data?.interaction[0]?.id
      if (!pid) return
      closeModal()
      beginPracticeStats(pid)
    }
    
  }

  // 监听到随堂测发布
  function onDwPracticePublish(j) {
    console.log('onDwPracticePublish', j)
    var pid = j && (j.practiceId != null ? j.practiceId : j.practice_id)
    if (!pid) return
    closeModal()
    beginPracticeStats(pid)
  }

  // 监听到随堂测停止答题
  function onDwPracticePublishStop(data) {
    var pid = data && data.practiceId
    stopPoll()
    if (pid && typeof DWLive !== 'undefined' && DWLive.userid && typeof DWLive.getPracticeStatisInfo === 'function') {
      DWLive.getPracticeStatisInfo(pid, function (res) {
        var p = extractPractice(res)
        if (p) renderPracticeResult(p)
      })
    }
  }

  // 监听到随堂测关闭
  function onDwPracticeClose() {
    closeResultModal()
  }

  function onDwPrizeSend(res) {
    if (res && res.viewerId != null) addCup(res.viewerId)
    syncRankCupPrized()
  }

  function bindDwHooks() {
    if (dwHooksBound) return
    if (typeof DWLive === 'undefined') return
    if (!document.getElementById('practice-result-mask')) return
    dwHooksBound = true
    chainDwLive('onPracticePublish', onDwPracticePublish)
    chainDwLive('onPracticePublishStop', onDwPracticePublishStop)
    chainDwLive('onPracticeClose', onDwPracticeClose)
    chainDwLive('onPrizeSend', onDwPrizeSend)
  }

  function buildLetterOptions() {
    var arr = []
    for (var i = 0; i < state.optionsNum; i++) {
      arr.push({ id: i, label: LETTERS[i] })
    }
    return arr
  }

  function syncOptionsFromState() {
    if (state.questionType === 'judge') {
      state.options = JUDGE_OPTS.slice()
    } else {
      state.options = buildLetterOptions()
    }
  }

  function publishCheck() {
    if (state.questionType === 'checkbox') return state.correctAnswers.length > 0
    return state.correctAnswer !== false
  }

  function renderOptions() {
    var ul = document.getElementById('practice-option-list')
    var pub = document.getElementById('practice-publish')
    if (!ul) return
    var html = ''
    for (var i = 0; i < state.options.length; i++) {
      var o = state.options[i]
      var sel = false
      if (state.questionType === 'checkbox') {
        sel = state.correctAnswers.indexOf(o.id) !== -1
      } else {
        sel = state.correctAnswer === o.id
      }
      html +=
        '<li type="button" role="button" tabindex="0" data-opt-id="' +
        o.id +
        '" class="' +
        (sel ? 'is-selected' : '') +
        '">' +
        '<span class="demo-practice-check">✓</span>' +
        o.label +
        '</li>'
    }
    ul.innerHTML = html
    if (pub) {
      if (publishCheck()) pub.classList.add('is-ready')
      else pub.classList.remove('is-ready')
    }
  }

  function renderTools() {
    var tools = document.getElementById('practice-option-tools')
    var addBtn = document.getElementById('practice-add-option')
    var rmBtn = document.getElementById('practice-remove-option')
    if (!tools || !addBtn || !rmBtn) return
    if (state.questionType === 'judge') {
      tools.classList.add('is-hidden')
      return
    }
    tools.classList.remove('is-hidden')
    addBtn.disabled = state.optionsNum > 5
    rmBtn.disabled = state.optionsNum < 3
  }

  function renderTabs() {
    var tabs = document.querySelectorAll('#practice-modal-tabs [data-qtype]')
    for (var i = 0; i < tabs.length; i++) {
      var t = tabs[i]
      if (t.getAttribute('data-qtype') === state.questionType) t.classList.add('active')
      else t.classList.remove('active')
    }
  }

  function initState() {
    state.questionType = 'radio'
    state.optionsNum = 4
    state.correctAnswer = false
    state.correctAnswers = []
    state.requesting = false
    syncOptionsFromState()
    renderTabs()
    renderTools()
    renderOptions()
  }

  function openModal() {
    var mask = document.getElementById('practice-modal-mask')
    if (!mask) return
    initState()
    mask.classList.add('is-open')
    mask.setAttribute('aria-hidden', 'false')
  }

  /** 直播中且本人有进行中随堂测 → 统计弹窗，否则 → 新建 */
  function onPracticeToolClick(e) {
    e.preventDefault()
    if (typeof DWLive === 'undefined' || DWLive.livestatus !== 1) return
    if (hasResumablePractice()) {
      closeModal()
      beginPracticeStats(poll.pid)
      return
    }
    closeResultModal()
    openModal()
  }

  function closeModal() {
    var mask = document.getElementById('practice-modal-mask')
    if (!mask) return
    mask.classList.remove('is-open')
    mask.setAttribute('aria-hidden', 'true')
  }

  function setQuestionType(type) {
    state.questionType = type
    state.correctAnswer = false
    state.correctAnswers = []
    state.optionsNum = 4
    syncOptionsFromState()
    renderTabs()
    renderTools()
    renderOptions()
  }

  function addOption() {
    if (state.optionsNum > 5) return
    state.optionsNum++
    trimCorrectForCount()
    syncOptionsFromState()
    renderTools()
    renderOptions()
  }

  function removeOption() {
    if (state.optionsNum < 3) return
    state.optionsNum--
    trimCorrectForCount()
    syncOptionsFromState()
    renderTools()
    renderOptions()
  }

  function trimCorrectForCount() {
    var max = state.optionsNum - 1
    if (state.questionType === 'radio' || state.questionType === 'judge') {
      if (state.correctAnswer !== false && state.correctAnswer > max) {
        state.correctAnswer = false
      }
    } else {
      state.correctAnswers = state.correctAnswers.filter(function (id) {
        return id <= max
      })
    }
  }

  function toggleOption(id) {
    id = Number(id)
    if (state.questionType === 'checkbox') {
      var ix = state.correctAnswers.indexOf(id)
      if (ix === -1) state.correctAnswers.push(id)
      else state.correctAnswers.splice(ix, 1)
    } else {
      state.correctAnswer = id
    }
    renderOptions()
  }

  function publish() {
    if (state.requesting || !publishCheck()) return
    if (typeof DWLive === 'undefined' || !DWLive.userid || !DWLive.roomid) {
      window.alert('请先完成 DWLive 登录（userid / roomid）')
      return
    }
    var _options = []
    for (var i = 0; i < state.options.length; i++) {
      var item = state.options[i]
      var isCorrect = false
      if (state.questionType === 'checkbox') {
        isCorrect = state.correctAnswers.indexOf(item.id) !== -1
      } else {
        isCorrect = state.correctAnswer === item.id
      }
      _options.push({ index: item.id, isCorrect: isCorrect ? 1 : 0 })
    }
    var payload = {
      type: TYPE_MAP[state.questionType],
      options: _options
    }
    var dataStr = encodeURIComponent(JSON.stringify(payload))
    if (typeof DWLive.hdPublishPractice !== 'function') {
      window.alert('请更新 assistantsdk（需包含 hdPublishPractice）')
      return
    }

    state.requesting = true
    DWLive.hdPublishPractice(dataStr, function (res) {
      state.requesting = false
      var root = unwrapSdkRes(res)
      if (!root) {
        window.alert('发布请求失败（网络或跨域）')
        return
      }
      var ok = root.success === true || root.success === 'true'
      var datas = root.datas
      if (ok && datas && datas.practiceId) {
        poll.publisherId = getSelfViewerId()
        closeModal()
        beginPracticeStats(datas.practiceId)
      } else {
        window.alert((root && root.msg) || '发布失败，请重试')
      }
    })
  }

  function bindUi() {
    document.addEventListener('click', function (e) {
      var t = e.target
      if (!t || !t.closest) return
      if (t.closest('[data-interact-tool="practice"]')) {
        onPracticeToolClick(e)
      }
    })

    var mask = document.getElementById('practice-modal-mask')
    var dlg = document.getElementById('practice-modal-dialog')
    if (mask) {
      mask.addEventListener('click', function (e) {
        if (e.target === mask) closeModal()
      })
    }
    if (dlg) {
      dlg.addEventListener('click', function (e) {
        e.stopPropagation()
      })
    }

    var closeBtn = document.getElementById('practice-modal-close')
    if (closeBtn) closeBtn.addEventListener('click', closeModal)

    var rMask = document.getElementById('practice-result-mask')
    var rDlg = document.getElementById('practice-result-dialog')
    if (rMask) {
      rMask.addEventListener('click', function (e) {
        if (e.target === rMask) requestCloseResult()
      })
    }
    if (rDlg) {
      rDlg.addEventListener('click', function (e) {
        e.stopPropagation()
      })
    }
    var rClose = document.getElementById('practice-result-close')
    if (rClose) rClose.addEventListener('click', requestCloseResult)

    var rAction = document.getElementById('practice-result-action')
    if (rAction) rAction.addEventListener('click', onResultActionClick)

    var rankList = document.getElementById('practice-result-rank-list')
    if (rankList) {
      rankList.addEventListener('click', function (e) {
        var cup = e.target.closest && e.target.closest('.demo-practice-result-rank-cup')
        if (!cup) return
        if (cup.classList.contains('is-prized')) return
        var id = cup.getAttribute('data-viewer-id')
        if (!id) return
        var name = cup.getAttribute('data-viewer-name') || ''
        e.stopPropagation()
        if (cupHas(id)) return
        openPrizeModal(id, name)
      })
    }

    var pMask = document.getElementById('practice-prize-mask')
    var pDlg = document.getElementById('practice-prize-dialog')
    if (pMask) {
      pMask.addEventListener('click', function (e) {
        if (e.target === pMask) closePrizeModal()
      })
    }
    if (pDlg) {
      pDlg.addEventListener('click', function (e) {
        e.stopPropagation()
      })
    }
    var pClose = document.getElementById('practice-prize-close')
    var pCancel = document.getElementById('practice-prize-cancel')
    var pOk = document.getElementById('practice-prize-ok')
    if (pClose) pClose.addEventListener('click', closePrizeModal)
    if (pCancel) pCancel.addEventListener('click', closePrizeModal)
    if (pOk) pOk.addEventListener('click', confirmSendPrize)

    var cMask = document.getElementById('practice-close-tip-mask')
    var cDlg = document.getElementById('practice-close-tip-dialog')
    if (cMask) {
      cMask.addEventListener('click', function (e) {
        if (e.target === cMask) closeCloseTipModal()
      })
    }
    if (cDlg) {
      cDlg.addEventListener('click', function (e) {
        e.stopPropagation()
      })
    }
    var cClose = document.getElementById('practice-close-tip-close')
    var cCancel = document.getElementById('practice-close-tip-cancel')
    var cOk = document.getElementById('practice-close-tip-ok')
    if (cClose) cClose.addEventListener('click', closeCloseTipModal)
    if (cCancel) cCancel.addEventListener('click', closeCloseTipModal)
    if (cOk) cOk.addEventListener('click', confirmCloseResult)

    var tabs = document.getElementById('practice-modal-tabs')
    if (tabs) {
      tabs.addEventListener('click', function (e) {
        var li = e.target.closest && e.target.closest('[data-qtype]')
        if (!li) return
        setQuestionType(li.getAttribute('data-qtype'))
      })
    }

    var addBtn = document.getElementById('practice-add-option')
    var rmBtn = document.getElementById('practice-remove-option')
    if (addBtn) addBtn.addEventListener('click', addOption)
    if (rmBtn) rmBtn.addEventListener('click', removeOption)

    var ul = document.getElementById('practice-option-list')
    if (ul) {
      ul.addEventListener('click', function (e) {
        var li = e.target.closest && e.target.closest('li[data-opt-id]')
        if (!li) return
        toggleOption(li.getAttribute('data-opt-id'))
      })
    }

    var pub = document.getElementById('practice-publish')
    if (pub) pub.addEventListener('click', publish)

    document.addEventListener('keydown', function (e) {
      if (e.keyCode !== 27) return
      if (isCloseTipOpen()) {
        closeCloseTipModal()
        return
      }
      if (isPrizeOpen()) {
        closePrizeModal()
        return
      }
      if (isOpen()) closeModal()
      if (isResultOpen()) requestCloseResult()
    })
  }

  function install() {
    if (!document.getElementById('practice-modal-mask')) return
    bindUi()
    bindDwHooks()
  }

  $(install)
})(window.jQuery)
