/*
 * main.js
 * UI layer. builds DOM, listens to user events, relays
 * everything to player.js via IPC.
 */

/* global confirm */
const ipc = require('electron').ipcRenderer
const $ = window.jQuery
const Nanobar = window.Nanobar

const path = require('path')
const vnGames = require(path.join(__dirname, '../../app/vn.json'))
const changelog = require(path.join(__dirname, '../../app/release-log.json'))

const translations = {
  en: require(path.join(__dirname, './js/i18n/VNook_English.json'))
}

let i18n = key => key // eslint-disable-line no-unused-vars
let language = 'en' // eslint-disable-line no-unused-vars

// the language system is mostly useless now but
// you can bring it back, i won't do it myself tho.
const setupI18n = (lang) => {
  language = lang
  i18n = (key) => {
    const t = translations[lang]?.[key] || translations.en[key] || key
    return t
  }
}

const vnOptions = () => vnGames.map(vn =>
  `<option value="${vn.id}" title="${vn.description}">${vn.name}</option>`
).join('')

const changelogHtml = () => {
  let html = ''
  Object.entries(changelog).forEach(([version, notes]) => {
    html += `<p>${version}</p><ul><li>${notes.join('</li><li>')}</li></ul>`
  })
  return html
}

const template = `
<div class="container overlay">
  <div class="error"><div></div></div>
  <div class="header">
    <span class="title">
      <span id="appTitle">vnook</span> |
      <button id="btnSettings" title="Settings">⚙</button>
      <button id="btnHome" class="hidden" title="Home">⌂</button>
      <button id="btnPause" title="Pause">⏸</button>
    </span>
    <div class="buttonbox">
      <button id="btnMin" title="Minimize to tray">—</button>
      <button id="btnExit" title="Exit VNook">✕</button>
    </div>
  </div>

  <div class="main">

    <!-- HOME PAGE -->
    <div class="home page">
      <div class="controls">
        <label>
          <span>Music Volume</span>
          <input id="sliderMusic" type="range" step="1" min="0" max="100" />
        </label>
        <label>
          <span>Rain Volume</span>
          <input id="sliderRain" type="range" step="1" min="0" max="100" />
        </label>
      </div>
      <div class="game-select">
        <select id="vnSelect">
          ${vnOptions()}
        </select>
      </div>
      <div class="bottom-support">
        <button id="btnChangelog">changelog</button>
        <button id="btnCredits">credits</button>
      </div>
    </div>

    <!-- SETTINGS PAGE -->
    <div class="settings page hidden">
      <p role="heading" aria-level="1">player settings</p>
      <label>
        <input id="chkGrandFather" type="checkbox"/>
        <span>Grandfather clock mode</span>
        <span class="tiny">(plays once, no loop)</span>
      </label>
      <label>
        <input id="chkGameRain" class="rains" type="checkbox"/>
        <span>Use game rain sound</span>
      </label>
      <label>
        <input id="chkPeacefulRain" class="rains" type="checkbox"/>
        <span>Use no-thunder rain sound</span>
      </label>
      <label>
        <input id="chkPreferNoDownload" type="checkbox"/>
        <span>Stream only (no local cache)</span>
      </label>
      <label>
        <input id="chkTownTune" type="checkbox"/>
        <span>Enable town tune on hour change</span>
      </label>
      <label>
        <input id="chkOpenOnStartup" type="checkbox"/>
        <span>Open on startup</span>
      </label>

      <!-- Custom URL for self-hosted audio -->
      <label class="url-label">
        <span>Custom audio server URL</span>
        <span class="tiny">(leave blank to use default)</span>
        <input id="inputCustomUrl" type="text" placeholder="http://localhost:8080" />
        <button id="btnSaveUrl">Save URL</button>
      </label>

      <div class="towntune-setting">
        <button id="btnTowntuneCustomize">customize town tune</button>
      </div>

      <p role="heading" aria-level="2">language</p>
      <select id="langSelect">
        <option value="en">English</option>
      </select>

      <div class="btnContainer">
        <button id="btnClearSettings">clear local files and settings</button>
      </div>
    </div>

    <!-- TUNE SETTINGS PAGE -->
    <div class="tune-settings page hidden">
      <p role="heading" aria-level="1">town tune settings</p>
      <div class="creator">
        <div class="inputs">
          ${Array(16).fill(0).map(() => `
          <label>
            <input type="range" class="tune-slider" step="1" min="1" max="16">
            <span></span>
          </label>`).join('')}
        </div>
      </div>
      <p class="tiny">tip: use the mouse wheel to adjust notes!</p>
      <div class="save-tune-btn btnContainer">
        <button id="btnSaveTune">save</button>
        <button id="btnPlayTune">play</button>
      </div>
    </div>

    <!-- CREDITS PAGE -->
    <div class="credits page hidden">
      <p role="heading" aria-level="1">credits</p>
      <div class="credits-body">
        <p><strong>VNook</strong> is a fork of <strong>Nook Desktop</strong> by <a id="linkNookGithub">mn6</a>.</p>
        <p>Nook Desktop: <a id="linkNookRepo">github.com/mn6/nook-desktop</a></p>
        <hr/>
        <p>VN music courtesy of the respective developers:</p>
        <ul>
          <li><strong>CLANNAD</strong> — Key / Visual Arts</li>
          <li><strong>Little Busters!</strong> — Key / Visual Arts</li>
          <li><strong>Kanon</strong> — Key / Visual Arts</li>
          <li><strong>AIR</strong> — Key / Visual Arts</li>
        </ul>
        <p class="tiny">Please support the original creators. Music is streamed from your configured server. VNook does not redistribute copyrighted audio.</p>
        <hr/>
        <p>Music sources / where to find BGMs:</p>
        <ul>
          <li><a id="linkKhinsider">KHInsider — downloads.khinsider.com</a></li>
          <li>Your own self-hosted collection (set URL in Settings)</li>
        </ul>
      </div>
    </div>

    <!-- CHANGELOG PAGE -->
    <div class="changelog page hidden">
      <p role="heading" aria-level="1">changelog</p>
      <div class="log">${changelogHtml()}</div>
    </div>

  </div>
</div>
`

const showPage = (pageClass, fromSettings = false) => {
  $('.page').addClass('hidden')
  $(`.${pageClass}.page`).removeClass('hidden')
  if (fromSettings) {
    $('#btnSettings').addClass('hidden')
    $('#btnHome').removeClass('hidden').focus()
  } else {
    $('#btnHome').addClass('hidden')
    $('#btnSettings').removeClass('hidden').focus()
  }
}

let paused = false
const setPauseUI = (state) => {
  paused = state
  $('#btnPause').text(state ? '▶' : '⏸').attr('title', state ? 'Play' : 'Pause')
}

const exec = () => {
  $('#btnMin').on('click', () => ipc.send('min'))
  $('#btnExit').on('click', () => ipc.send('close'))

  $('#btnPause').on('click', () => {
    paused = !paused
    setPauseUI(paused)
    ipc.send('toPlayer', ['paused', paused])
  })

  $('#btnSettings').on('click', () => showPage('settings', true))
  $('#btnHome').on('click', () => showPage('home', false))
  $('#btnChangelog').on('click', () => showPage('changelog', true))
  $('#btnCredits').on('click', () => showPage('credits', true))

  $('#linkNookGithub, #linkNookRepo').on('click', () => {
    require('electron').shell.openExternal('https://github.com/mn6/nook-desktop')
  })
  $('#linkKhinsider').on('click', () => {
    require('electron').shell.openExternal('https://downloads.khinsider.com/game-soundtracks/album/clannad-video-game-original-soundtrack')
  })

  $('#sliderMusic').on('change', e => ipc.send('toPlayer', ['musicVol', e.target.value]))
  $('#sliderRain').on('change', e => ipc.send('toPlayer', ['rainVol', e.target.value]))
  $('#vnSelect').on('change', e => ipc.send('toPlayer', ['vn', e.target.value]))

  $('#chkGrandFather').on('change', e => ipc.send('toPlayer', ['grandFather', e.target.checked]))
  $('#chkGameRain').on('change', e => {
    ipc.send('toPlayer', ['gameRain', e.target.checked])
    $('#chkPeacefulRain').prop('checked', false)
  })
  $('#chkPeacefulRain').on('change', e => {
    ipc.send('toPlayer', ['peacefulRain', e.target.checked])
    $('#chkGameRain').prop('checked', false)
  })
  $('#chkTownTune').on('change', e => ipc.send('toPlayer', ['tuneEnabled', e.target.checked]))
  $('#chkPreferNoDownload').on('change', e => ipc.send('toPlayer', ['preferNoDownload', e.target.checked]))
  $('#chkOpenOnStartup').on('change', e => ipc.send('toPlayer', ['openOnStartup', e.target.checked]))

  $('#langSelect').on('change', e => {
    setupI18n(e.target.value)
    ipc.send('toPlayer', ['lang', e.target.value])
  })

  $('#btnSaveUrl').on('click', () => {
    const url = $('#inputCustomUrl').val().trim()
    ipc.send('toPlayer', ['customBaseUrl', url])
    $('#btnSaveUrl').text('saved!').prop('disabled', true)
    setTimeout(() => $('#btnSaveUrl').text('Save URL').prop('disabled', false), 1500)
  })

  $('#btnClearSettings').on('click', () => {
    if (confirm('Delete all local files and settings?')) ipc.send('clearSettings')
  })

  $('#btnTowntuneCustomize').on('click', () => showPage('tune-settings', true))

  $('.tune-settings input[type="range"]').on('wheel', e => {
    e.preventDefault()
    e.currentTarget.valueAsNumber += e.originalEvent.deltaY < 0 ? 1 : -1
    e.currentTarget.dispatchEvent(new CustomEvent('input'))
  })
  $('.tune-settings input[type="range"]').on('click input', e => {
    ipc.send('toPlayer', ['playNote', e.currentTarget.value])
  })

  $('#btnSaveTune').on('click', () => {
    const tunes = ['-', 'zZz', 'G0', 'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'A2', 'B2', 'C2', 'D2', 'E2', '?']
    const tune = []
    $('.tune-settings input[type="range"]').each((i, e) => tune.push(tunes[$(e).val() - 1]))
    ipc.send('toPlayer', ['tune', tune])
    $('#btnSaveTune').text('saved!')
    setTimeout(() => $('#btnSaveTune').text('save'), 1000)
  })

  $('#btnPlayTune').on('click', () => {
    const vals = []
    $('.tune-settings input[type="range"]').each((i, e) => vals.push($(e).val()))
    ipc.send('toPlayer', ['playTune', vals])
  })
}

let nanobar

$(document).ready(() => {
  ipc.on('toWindow', (event, arg) => {
    const cmd = arg[0]

    if (cmd === 'bar') {
      nanobar.go(+arg[1])
    } else if (cmd === 'configs') {
      const cfg = arg[1]
      setupI18n(cfg.lang)
      $('body').append($(template))

      nanobar = new Nanobar({ classname: 'nanobar', id: 'nanobar', target: $('.header')[0] })
      nanobar.go(0)

      $('#sliderMusic').val(cfg.soundVol)
      $('#sliderRain').val(cfg.rainVol)
      $('#chkGrandFather').prop('checked', cfg.grandFather)
      $('#chkGameRain').prop('checked', cfg.gameRain)
      $('#chkPeacefulRain').prop('checked', cfg.peacefulRain)
      $('#vnSelect').val(cfg.vn)
      $('#langSelect').val(cfg.lang)
      $('#chkTownTune').prop('checked', cfg.tuneEnabled)
      $('#chkPreferNoDownload').prop('checked', cfg.preferNoDownload)
      $('#chkOpenOnStartup').prop('checked', cfg.openOnStartup)
      if (cfg.customBaseUrl) $('#inputCustomUrl').val(cfg.customBaseUrl)

      const tuneMap = ['-', 'zZz', 'G0', 'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'A2', 'B2', 'C2', 'D2', 'E2', '?']
      $('.tune-settings input[type="range"]').each((i, e) => {
        const idx = tuneMap.indexOf(cfg.tune[i])
        $(e).val(idx >= 0 ? idx + 1 : 1)
      })

      setPauseUI(cfg.paused)

      exec()
      $('.container').addClass('visible')
    } else if (cmd === 'error') {
      $('.error div').html(arg[1]).parent().addClass('show-error')
      setTimeout(() => $('.error').removeClass('show-error'), 4000)
    } else if (cmd === 'pause') {
      setPauseUI(true)
    }
  })
})
