"use strict";

//
// UI ELEMENTS
//

class SaveButton {
  constructor(div) {
    this.root = div
    this.root.className = "savebutton"
    this.root.style.display = "block"

    this.element = {
      root: this.root,
      button: this.root.querySelector('.savebutton--button'),
      icon: this.root.querySelector('.savebutton--icon'),
      details: this.root.querySelector('.savebutton--details')
    }

    this.switchStateInitial()
  }

  changeState(data) {
    var data = data || {}
    this.element.button.innerText = data.buttonText || "Save"
    this.element.button.disabled = data.buttonClickable === false ? true : false
    this.element.icon.className = 'savebutton--icon ' + (data.iconClasses || "")
    this.element.details.innerText = data.detailsText || ""
  }

  switchStateInitial() {
    this.changeState({
      buttonClickable: false
    })
  }

  switchStateUnsaved() {
    this.changeState({
      detailsText: django.gettext("You have unsaved changes. Click here to save a draft, which you can access next time you are here.")
    })
  }

  switchStateSaving() {
    this.changeState({
      buttonText: django.gettext("Saving..."),
      iconClasses: "fa fa-spinner fa-spin"
    })
  }

  switchStateSaveSuccess() {
    this.changeState({
      buttonText: django.gettext("Saved"),
      detailsText: django.gettext("Saved successfully."),
      iconClasses: "fa fa-check",
      buttonClickable: false
    })
  }

  switchStateSaveFailed(reason = "") {
    this.changeState({
      detailsText: django.gettext("Save failed! ") + reason,
      iconClasses: "fa fa-exclamation-triangle savebutton--icon-failed"
    })
  }
}


class DraftPrompt {
  constructor(opts) {
    this.restoreDraft = opts.restoreFn
    this.deleteDraft = opts.deleteFn

    this.root = opts.root
    this.element = {
      root: this.root,
      restore: this.root.querySelector('.draftprompt--restore'),
      delete: this.root.querySelector('.draftprompt--delete'),
      details: this.root.querySelector('.draftprompt--details')
    }

    // Restore should restore, then hide the prompt
    this.element.restore.addEventListener('click', () => {
      this.restoreDraft()
      this.switchStateHidden()
    })

    // Delete button will delete the draft
    this.element.delete.addEventListener('click', () => {
      if (window.confirm(django.gettext('Are you sure you want to delete your draft?'))) {
        this.switchStateDeleting()
        this.deleteDraft().then(ok => ok ?
                                          this.switchStateHidden() :
                                          this.switchStateDeleteFailed()
        )
      }
    })

    this.switchStateShown()
  }

  changeState(data) {
    var data = data || {}
    this.element.root.style.display = data.visible ? "block" : "none"
    this.element.details.innerHTML = data.detailsText || ""
  }

  switchStateHidden() {
    this.changeState({
      visible: false
    })
  }

  switchStateShown() {
    this.changeState({
      visible: true
    })
  }

  switchStateDeleting() {
    this.changeState({
      visible: true,
      details: '<i classs="fa fa-spinner fa-spin"></i>'
    })
  }

  switchStateDeleteFailed() {
    this.changeState({
      details: django.gettext("Delete failed!")
    })
  }
}


//
// API UTILITIES
//

function apiGetDraft() {
  return fetch('/en-gb/case-study/draft', {
    method: 'GET',
    credentials: "same-origin",
    headers: {
        "X-CSRFToken": jQuery("[name=csrfmiddlewaretoken]").val(),
    }
  })
}

function apiPutDraft(formSaver) {
  if (!formSaver) {
    throw new Error("apiPutDraft: parameter not provided")
  }

  return fetch('/en-gb/case-study/draft', {
      method: 'PUT',
      credentials: "same-origin",
      headers: {
          "X-CSRFToken": jQuery("[name=csrfmiddlewaretoken]").val(),
          "Accept": "application/json",
          "Content-Type": "application/json"
      },
      body: JSON.stringify({ version: 1, data: formSaver.serialise() })
    })
}

function apiDeleteDraft() {
  return fetch('/en-gb/case-study/draft', {
      method: 'DELETE',
      credentials: "same-origin",
      headers: {
          "X-CSRFToken": jQuery("[name=csrfmiddlewaretoken]").val(),
      }
    })
}


//
// GNARLY BITS TYING API & UI STUFF TOGETHER
//

function showDraftPrompt(formSaver, serialisedForm) {
  let prompt = new DraftPrompt({
    root: document.querySelector('.draftprompt'),
    restoreFn: () => formSaver.deserialise(serialisedForm),
    deleteFn: () => apiDeleteDraft().then(response => response.ok)
  })
}

function initDrafts() {
  const formSaver = new FormSaver({
    formId: 'case-study-form',
    except: [ 'csrfmiddlewaretoken' ]
  })

  // Use whether the form has errors as a proxy for whether the server has
  // returned us data in the form.  In this case, don't show a draft.
  const formHasErrors = document.getElementById('form_errors').value === 'true' ? true : false
  if (!formHasErrors) {
  // Get the previous draft, if any
    apiGetDraft()
      .then(response => response.json())
      .then(json => {
        // Handle the case where we didn't get a response
        if (!json) return

        if (json.version !== 1) {
          throw new Error("Bad JSON response version")
        }

        showDraftPrompt(formSaver, json.data.form)
      }).catch(err => {
        console.error(err);
      })
  }

  // Init the button controller
  var button = new SaveButton(document.querySelector('.savebutton'))

  // Dirty forms set up
  $('#case-study-form').dirtyForms();
  $('#case-study-form').on('dirty.dirtyforms', ev => {
    button.switchStateUnsaved()
  });

  // Save button
  button.element.button.addEventListener('click', evt => {
    button.switchStateSaving()

    apiPutDraft(formSaver).then(response => {
      if (response.ok) {
        button.switchStateSaveSuccess();
        $('#case-study-form').dirtyForms('setClean');
        document.querySelector('.draftprompt').style.display = "none"
      } else {
        button.switchStateSaveFailed();
      }
    }).catch(err => {
      console.error(err);
      button.switchStateSaveFailed();
    })
  })
}

// https://github.com/snikch/jquery.dirtyforms