<template>
  <div class="reader" v-shortkey="{left: ['arrowleft'], right: ['arrowright']}" @shortkey="navigation">
    <div class="page-container">
      <img ref="currentImage" :style="getRealPageStyle()" :src="info.pages[page]" @load="setScroll(); setOrientation()">
      <!-- prefetching -->
      <img style="display: none;" :src="info.pages[page-1]">
      <img style="display: none;" :src="info.pages[page+1]">
    </div>
    <div class="sidebar" :style="{ display: showSidebar ? '' : 'none' }">
      <h3>{{ info.title }}</h3>
      <router-link :to="'/series/' + info.series">All Volumes</router-link>
      <hr/>
      <div class="sidebar-item">{{ page + 1 }}/{{ info.pages.length }}</div>
      <div class="page-display-settings-wrapper">
        <div class="page-display-settings-item">
          <label for="page-width">Width</label>
          <input id="page-width" v-model.number="pageDisplay.width" type="number" min="5" max="100" step="5">
        </div>
        <div class="page-display-settings-item">
          <label for="page-height">Height</label>
          <input id="page-height" v-model.number="pageDisplay.height" type="number" min="5" max="100" step="5">
        </div>
        <div>
          <button class="sidebar-item" id="display-mode" v-on:click="cyclePageDisplayMode()">Fit: {{ pageDisplay.mode }}</button>
        </div>
      </div>
      <button class="sidebar-item" v-on:click="changeDirection">{{ direction.toUpperCase() }}</button>
      <button class="hide" v-on:click="showSidebar = false">Hide</button>
    </div>
    <div class="sidebar-enabler" :style="{ display: showSidebar ? 'none' : '' }" v-on:click="showSidebar = true"></div>
  </div>
</template>

<script>
import API from '@/api-client.js'

export default {
  name: 'Reader',
  data () {
    return {
      info: {
        pages: []
      },
      scrollPositions: [],
      pageDisplay: {
        width: 60,
        height: 100,
        mode: 'width'
      },
      showSidebar: true,
      direction: 'rtl',
      orientation: 'vertical'
    }
  },
  computed: {
    page: {
      get () {
        if (this.$route.hash) {
          return this.$route.hash.substr(1) - 1
        } else {
          return 0
        }
      },
      set (value) {
        this.$router.push({ hash: '#' + (value + 1) })
      }
    }
  },
  mounted () {
    API.getVolumeInfo(this.$route.params.id, info => (this.info = info))

    if (localStorage.pageDisplay) {
      this.pageDisplay = JSON.parse(localStorage.pageDisplay)
    }
  },
  watch: {
    pageDisplay: {
      handler (newPageDisplay) {
        localStorage.pageDisplay = JSON.stringify(newPageDisplay)
      },
      deep: true
    }
  },
  methods: {
    setPage (page) {
      // save scroll position
      this.scrollPositions[this.page] = window.pageYOffset

      // set page
      if (page >= 0 && page < this.info.pages.length) {
        this.page = page
      }
    },

    setScroll () {
      // load saved scroll posotion, if available, reset to 0 otherwise
      if (this.scrollPositions[this.page]) {
        window.scrollTo(0, this.scrollPositions[this.page])
      } else {
        window.scrollTo(0, 0)
      }
    },

    navigation (event) {
      if ((event.srcKey === 'right' && this.direction === 'ltr') || (event.srcKey === 'left' && this.direction === 'rtl')) {
        this.setPage(this.page + 1)
      } else if ((event.srcKey === 'left' && this.direction === 'ltr') || (event.srcKey === 'right' && this.direction === 'rtl')) {
        this.setPage(this.page - 1)
      } else {
        throw new Error('cannot nagivate: invalid parameters')
      }
    },

    changeDirection () {
      if (this.direction === 'rtl') {
        this.direction = 'ltr'
      } else if (this.direction === 'ltr') {
        this.direction = 'rtl'
      } else {
        throw new Error('cannot change reading direction: invalid direction currently set')
      }
    },

    setOrientation () {
      const image = this.$refs.currentImage

      if (image.width < image.height) {
        this.orientation = 'vertical'
      } else if (image.width > image.height) {
        this.orientation = 'horizontal'
      } else if (image.width === image.height) {
        this.orientation = 'square'
      }
    },

    getRealPageStyle () {
      let width = 'auto'
      let height = 'auto'

      if (this.pageDisplay.mode === 'width') {
        if (this.orientation === 'horizontal') {
          width = '100%'
        } else {
          width = this.pageDisplay.width + '%'
        }
      } else if (this.pageDisplay.mode === 'height') {
        height = this.pageDisplay.height + 'vh'
      }

      return {
        width: width,
        height: height
      }
    },

    cyclePageDisplayMode () {
      const pageDisplayModes = ['width', 'height', 'auto']

      this.pageDisplay.mode = pageDisplayModes[(pageDisplayModes.indexOf(this.pageDisplay.mode) + 1) % pageDisplayModes.length]
    }
  }
}
</script>

<style scoped lang="scss">
.reader {
  display: flex;
  position: relative;
}

.page-container {
  flex-grow: 1;
}

img {
  vertical-align: top;
}

.sidebar-enabler {
  position: absolute;
  top: 0px;
  right: 0px;
  height: 100%;
  width: 250px;
}

.sidebar {
  flex: 0 0 250px;
  background-color: #eee;
  height: 100vh;
  position: sticky;
  top: 0;
}

.sidebar-item {
  margin: 0.5em 0;
}

button.hide {
  bottom: 1em;
  right: 1em;
  position: absolute;
}

.page-display-settings-wrapper {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;

  .page-display-settings-item {
    margin: 10px;
    width: 33%;

    input {
      width: 100%;
    }
  }
}
</style>
