const m = require('mithril')
const Authentication = require('./authentication')
const api = require('./api')
const Input = require('./input')
const lang = require('./lang')
const videos = require('./videos')

const Upload = {
  oninit: function(vnode) {
    Authentication.requiresLogin()
    this.error = ''
    let d = new Date()
    d.setDate(d.getDate() - d.getDay())
    d.setHours(11)
    d.setMinutes(0)
    d.setSeconds(0)
    d.setMilliseconds(0)

    this.cacheVideo = null
    this.cacheImage = null
    this.uploading = null
    this.form = {
      title: 'Sunnudagssamkoma',
      date: d,
      file: null,
      banner: null,
      metadata: {
        speaker: '',
      },
    }
  },
  
  uploadvideo: function(vnode, e) {
    this.error = ''

    if (!this.form.title) this.error = lang.upload_missing_title // Title is missing
    if (!this.form.date) this.error = lang.upload_missing_date // Date is missing
    if (!this.form.file) this.error = lang.upload_missing_file // Video file missing
    if (!this.form.banner) this.error = lang.upload_missing_banner // Poster image missing

    if (this.error) return false

    api.sendRequest({
      method: 'GET',
      url: '/api/auth/uploadToken',
    })
    .then(res => {
      if (this.cacheImage?.file === this.form.banner) {
        return this.cacheImage
      }

      return api.uploadBanner(this.form.banner, res)
      .then(imageData => {
        this.cacheImage = imageData
        return res
      })
    })
    .then(res => {
      if (this.cacheVideo?.file === this.form.file) {
        return this.cacheVideo
      }

      return api.uploadFileProgress({
        url: res.path + '?token=' + res.token,
      }, this.form.file, (xhr, progress, perSecond) => {
        this.uploading = {
          progress,
          xhr,
          perSecond
        }
        m.redraw()
      })
    })
    .then(res => {
      this.cacheVideo = {
        file: this.form.file,
        filename: res.filename,
        path: res.path,
      }
      this.uploading = null

      return api.sendRequest({
        method: 'PUT',
        url: '/api/auth/articles/0',
        body: {
          name: this.form.title,
          page_id: 'null',
          path: this.form.date.toISOString().replace('T', '_').replace(/:/g, '').split('.')[0],
          content: JSON.stringify(this.form.metadata),
          publish_at: this.form.date,
          admin_id: Authentication.getTokenDecoded().user_id,
          is_featured: false,
          media: {
            filename: res.filename,
            path: res.path,
            type: this.form.file.type,
            size: this.form.file.size,
          },
          banner: {
            filename: this.cacheImage.medium.filename,
            path: this.cacheImage.medium.path,
            type: 'image/avif',
            size: this.cacheImage.size,
            preview: {
              base64: this.cacheImage.preview.base64,
            },
          },
        },
      })
    })
    .then(res => {
      videos.refreshTree()
      m.route.set('/')
    })
    .catch((error) => {
      this.uploading = null
      if (!error) return

      this.error = lang.format(lang.upload_error, error.message) // Error while uploading:
    })

    return false
  },

  cancelUpload(e) {
    e.stopPropagation()
    this.uploading.xhr.abortRequest()
    this.uploading = null
    return false
  },

  filechanged(file) {
    if (!file || !file.name) return
    
    let matches = /^(\d{4})-(\d\d)-(\d\d)_(\d\d)-(\d\d)/.exec(file.name)
    if (!matches) return

    var date = new Date(matches.slice(1, 4).join('-') + 'T' + matches.slice(4,6).join(':') + ':00')
    if (isNaN(date.getTime())) return

    if (date.getMinutes() >= 30 || date.getHours() === 10) {
      date.setHours(date.getHours() + 1)
    }
    date.setMinutes(0)
    this.form.date = date
  },

  view: function(vnode) {
    return [
      m('div.page.page-upload', [
        m('div.modal', [
          m('form', {
            onsubmit: this.uploadvideo.bind(this, vnode),
          }, [
            m('h3', 'Upload new video'),
            this.error ? m('p.error', this.error) : null,
            m(Input, {
              label: 'Title',
              form: this.form,
              formKey: 'title',
            }),
            m(Input, {
              label: 'Date (dd.mm.yyyy)',
              type: 'text',
              utility: 'datetime',
              form: this.form,
              formKey: 'date',
            }),
            m(Input, {
              label: 'Video',
              type: 'file',
              accept: '.webm',
              utility: 'file',
              button: 'fa-video',
              form: this.form,
              formKey: 'file',
              oninput: (file) => this.filechanged(file),
            }),
            m(Input, {
              label: 'Mynd',
              type: 'file',
              accept: 'image/*',
              utility: 'image',
              form: this.form,
              formKey: 'banner',
            }),
            m('p.separator', 'Optional'),
            m(Input, {
              label: 'Speaker',
              form: this.form.metadata,
              formKey: 'speaker',
            }),
            m('input.spinner', {
              hidden: api.loading,
              type: 'submit',
              value: 'Begin upload',
            }),
            api.loading ? m('div.loading-spinner') : null,
            this.uploading ? [
              m('p', `${Math.floor(this.uploading.progress)}% (${this.uploading.perSecond}/s)`),
              m('.loading-bar', { style: `--progress: ${this.uploading.progress}%` }),
              m('button.button.button-alert', {
                onclick: this.cancelUpload.bind(this),
              }, 'Cancel upload'),
            ] : null,
          ]),
        ]),
        m('footer', lang.mformat(
            lang.unsplash, // Photo by X on Y
            m('a', { href: 'https://unsplash.com/@franhotchin?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash', target: '_blank' }, 'Francesca Hotchin'),
            m('a', { href: 'https://unsplash.com/photos/landscape-photo-of-mountain-covered-with-snow-FN-cedy6NHA?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash', target: '_blank' }, 'Unsplash'),
        )),
      ]),
    ]
  },
}

module.exports = Upload
