// npm
const flyd = require('flyd')
const mergeAll = require('flyd/module/mergeall')
const flatMap = require('flyd/module/flatmap')
const lift = require('flyd/module/lift')
const snabbdom = require('snabbdom')
const h = require('snabbdom/h')
const R = require('ramda')
const render = require('ff-core/render')
const modal = require('ff-core/modal')
const notification = require('ff-core/notification')
const button = require('ff-core/button')
const request = require('../../common/request')
// local
const cardForm = require('../../components/card-form.es6')
const readableInterval = require('../../nonprofits/recurring_donations/readable_interval')
const format = require('../../common/format')
const supporterAddressForm = require('../../components/supporter-address-form.es6')
const changeAmountWizard = require('./change-amount-wizard.es6')


function init() {
  var state = {
    submitPaydate$: flyd.stream()
  , confirmCancel$: flyd.stream()
  , changeAmount$: flyd.stream()
  , error$: flyd.stream()
  }
  
  const rdPath = `/recurring_donations/${app.pageLoadData.recurring_donation.id}`
  const rdUpdateAmountPath = `/recurring_donations/${app.pageLoadData.recurring_donation.id}/update_amount`
  const token = utils.get_param('t')
  state.donate_again_url = app.pageLoadData.miscellaneous_np_info.donate_again_url;

  // Paydate update and cancellation streams
  const updatePaydate$ = flatMap(updatePaydate(rdPath), state.submitPaydate$)
  const cancellation$  = flatMap(reqCancel(rdPath), state.confirmCancel$)

state.changeAmountWizard = changeAmountWizard.init( {nonprofit:app.pageLoadData.nonprofit,
        recurring_donation: app.pageLoadData.recurring_donation,
        supporter: app.pageLoadData.supporter,
        custom_amounts: app.pageLoadData.change_amount_suggestions});
  
  state.cardForm = cardForm.init({
    card: {
      name: app.pageLoadData.supporter.name
    , address_zip: app.pageLoadData.supporter.zip_code
    }
  , path: '/cards'
  , payload: {
      edit_token: token
    , path: rdPath
    , card: { holder_id: app.pageLoadData.supporter.id, holder_type: 'Supporter'}
    }
  })

  state.addressForm = supporterAddressForm.init({
    supporter: app.pageLoadData.supporter
  , path: rdPath
  , payload: { edit_token: token }
  })

  // Card update streams
  // update the card id on the recurring donation after the card has been saved on CC
  // (card-form.es6 component will post the card but will not update the card id on the recurring donation)
  state.updateCardID$ = flatMap(
    resp => request({
      method: 'put'
    , path: rdPath
    , send: {edit_token: token, card_id: resp.id, card_name: resp.name}
    }).load
  , state.cardForm.saved$
  )


  // Stream of notification messages
  const message$ = flyd.mergeAll([
    flyd.map(R.always('Paydate successfully updated'), updatePaydate$)
  , flyd.map(R.always('Address successfully updated'), state.addressForm.response$)
  , flyd.map(R.always('Card successfully updated'), state.updateCardID$)
  ])
  state.notification = notification.init({message$})

  // A bunch of streams that cause the modal to close:
  state.modalID$ = flyd.map(
    R.always(null)
  , mergeAll([
      updatePaydate$
    , state.updateCardID$
    , cancellation$
    , state.addressForm.response$
    ])
  )

  // Stream of vals that cause loading animation to show/hide
  state.loading$ = mergeAll([
    flyd.map(R.always(true), state.submitPaydate$)
  , flyd.map(R.always(true), state.confirmCancel$)
  , flyd.map(R.always(false), updatePaydate$)
  , flyd.map(R.always(false), cancellation$)
  ])

  // Simply replace old recurring donations with new ones based on ajax responses
  const setNew = (old, resp) => resp.body.recurring_donation
  state.recDon$ = flyd.scanMerge([
    [updatePaydate$, setNew]
  , [cancellation$, setNew]
  , [state.updateCardID$, setNew]
  , [state.updateCardAndAmount$, setNew]
  ], app.pageLoadData.recurring_donation)

  return state
}


// -- Stream creator functions

const updatePaydate = path => ev => {
  ev.preventDefault()
  const paydate = Number(ev.currentTarget.querySelector('input').value)
  return request({
    method: 'PUT'
  , path: path
  , send: {edit_token: utils.get_param('t'), paydate: paydate}
  }).load
}


const reqCancel = path => ev => {
  ev.preventDefault()
  return request({
    method: 'delete'
  , path: path
  , send: {edit_token: utils.get_param('t')}
  }).load
}


// -- Virtual DOM functions

function view(state) {
  var rd = state.recDon$()
  var supporter = state.addressForm.supporter$()
  var status = rd.active ? 'Active' : 'Deactivated'
  var interval = rd.active ? readableInterval(rd.interval, rd.time_unit) : 'Deactivated'

  return h('div.u-maxWidth--600.u-margin--auto.u-marginTop--50.u-padding--15.js-view-confirm', [
    h('h3.u-centered.u-marginBottom--20', ['Recurring Donation for ', String(supporter.name|| supporter.email)])
    // Show deactivated notification box if deactivated
  , rd.active ? '' : h('p.u-centered.pastelBox--orange.u-padding--10.u-marginBottom--20', 'This recurring donation has been deactivated')
    // Recurring Donation info table
  , h('table.table--striped.u-marginBottom--50', [
      h('tr', [
        h('td.u-strong', 'Created on')
      , h('td', format.date.toSimple(rd.created_at))
    ])
    , h('tr', [
        h('td.u-strong', 'Recurring amount')
      , h('td', '$' + format.centsToDollars(rd.amount))
    ])
    , h('tr', [
        h('td.u-strong', 'Organization')
      , h('td', [h('a', {props: {href: `/nonprofits/${rd.nonprofit_id}`, target: '_blank'}}, String(rd.nonprofit_name))])
    ])
    , h('tr', [
        h('td.u-strong', 'Card')
      , h('td', String(rd.card_name))
    ])
    , h('tr', [
        h('td.u-strong', 'Donor email')
      , h('td', String(app.pageLoadData.supporter.email))
    ])
    , h('tr', [
        h('td.u-strong', 'Recurring donation status')
      , h('td', String(status))
    ])
    , h('tr', [
        h('td.u-strong', 'Recurring interval')
      , h('td', String(interval))
    ])
    , rd.active
      ? ''
      : h('tr', [
        h('td.u-strong', 'Cancelled By')
      , h('td', String(rd.cancelled_by))
      ])
    , rd.active
      ? ''
      : h('tr', [
        h('td.u-strong', 'Cancelled At')
      , h('td', format.date.readableWithTime(rd.cancelled_at))
      ])
    , h('tr', [
        h('td.strong', 'Address')
      , h('td', [
          h('small', [
            [supporter.address, supporter.city].filter(R.identity).join(', ')
          , h('br')
          , [supporter.state_code, supporter.zip_code, supporter.country].filter(R.identity).join(', ')
        ])
      ])
    ])
    , rd.interval === 1 && rd.time_unit === 'month'
      ? h('tr', [
          h('td.u-strong', 'Fixed paydate')
        , h('td', String(rd.paydate ? rd.paydate : 'None'))
      ])
      : ''
    ])
  , actions(state)
  , rd.active ? '' : reactivate(rd.nonprofit_id)
  , cancelModal(state)
  , updateCardModal(state)
  , editPaydateModal(state)
  , updateAddressModal(state)
  , changeAmountModal(state)
  , notification.view(state.notification)
  ])
}


const reactivate = np_id =>
  h('p.u-centered', [ h('a.button', {props: {href: `/nonprofits/${np_id}/donate`}}, 'Reactivate') ])


function actions(state) {
  var rd = state.recDon$()
  if(!rd.active) return ''
  var modalID$ = state.modalID$
  return h('div.pastelBox--looseleaf.u-padding--15.u-marginBottom--50', [
    h('p.u-strong.u-centered', 'What would you like to do?')
  , h('ul.hasBullets.u-maxWidth--400.u-margin--auto', [
      h('li', [changeAmountBtn(modalID$)])
    , h('li', [updateCardBtn(modalID$)])

    , h('li', [updateAddressBtn(modalID$)])
    , rd.interval === 1 && rd.time_unit === 'month'
        ? h('li', [updatePaydateBtn(modalID$)])
        : ''
    , h('li', [giveOneTimeDonationBtn(state)])
    , h('li', [cancelBtn(modalID$)])
    ])
  ])
}


const changeAmountBtn = modalID$ =>
    h('strong', [
        h('a.test-changeAmount', {
            on: {click: [modalID$, 'changeAmountModal']}
        }, 'Change my donation amount')
    ])

const updateCardBtn = modalID$ => 
  h('strong', [
    h('a.test-updateCard', {
      on: {click: [modalID$, 'updateCardModal']}
    }, 'Update my card')
  ])


const cancelBtn = modalID$ =>
  h('strong', [
    h('a.test-cancelDonation', {
      on: {click: [modalID$, 'cancelRecDonModal']}
    }, 'Cancel my recurring donation')
  ])


const updatePaydateBtn = modalID$ =>
  h('strong', [
    h('a', {
      on: {click: [modalID$, 'editPaydateModal']}
    }, 'Change the day I\'m billed')
  ])


const updateAddressBtn = modalID$ =>
  h('strong', [
    h('a', {
      on: {click: [modalID$, 'updateAddressModal']}
    }, 'Update my address')
  ])


const giveOneTimeDonationBtn = (state) =>
    h('strong', [
        h('a', {
            props:{href: state.donate_again_url}
        }, 'Give a one-time donation')
    ])


const cancelModal = state =>
  modal({
    thisID: 'cancelRecDonModal'
  , id$: state.modalID$
  , body: h('div.u-marginTop--30.u-centered', [
      h('p.u-marginBottom--20', 'Cancelling your recurring donation will prevent any future charges for this donation.')
    , h('hr.diamonds.u-marginBottom--40')
    , h('p.u-strong', state.recDon$().nonprofit_name + ' will miss your support!')
    , h('hr.diamonds')
    , h('div.u-marginTop--30', [confirmCancelBtn(state)])
    ])
  })


const updateCardModal = state =>
  modal({
    thisID: 'updateCardModal'
  , id$: state.modalID$
  , title: 'Update Card'
  , body: cardForm.view(state.cardForm)
  })

const changeAmountModal = state =>
    modal({
        thisID: 'changeAmountModal'
        , id$: state.modalID$
        , title: 'Change Amount'
        , body: changeAmountWizard.view(state.changeAmountWizard)
    })


const editPaydateModal = state =>
  modal({
    thisID: 'editPaydateModal'
  , id$: state.modalID$
  , title: 'Edit Paydate'
  , body: paydateForm(state)
  })


const updateAddressModal = state =>
  modal({
    thisID: 'updateAddressModal'
  , id$: state.modalID$
  , title: 'Edit your address'
  , body: supporterAddressForm.view(state.addressForm)
  })


const paydateForm = state =>
  h('form', { on: {submit: state.submitPaydate$} }, [
    h('p', 'Enter a day of the month (between 1 and 28) when you want to be charged for this donation.')
  , h('p', 'This will fix your donations to that date each month for all future payments.')
  , h('input.input--small', {
      props: {
        type: 'number'
      , max: 28
      , min: 1
      , name: 'paydate'
      , value: state.recDon$().paydate || 1
      }
    })
  , h('br')
  , button(R.pick(['loading$', 'error$'], state))
  ])


const confirmCancelBtn = state =>
  h('form', { on: { submit: state.confirmCancel$ } }, [
    button({
      buttonText: 'Cancel My Donation'
    , loading$: state.loading$
    , error$: state.error$
    , buttonClass: 'red'
    })
  ])


// -- Render to the page

var container = document.querySelector('#js-main')
const patch = snabbdom.init([
  require('snabbdom/modules/eventlisteners')
, require('snabbdom/modules/class')
, require('snabbdom/modules/props')
, require('snabbdom/modules/style')
])
var state = init()
render({patch, view, state, container})