<template>
  <div class="no-overflow cart-upgrade-steps">
    <stepped
      :steps="steps"
      :active-step="activeStep.index"
      class="my-4 flex-wrap overflow-hidden"
      :class="{ decreasing: decreasing }"
      :style="computedStyles"
      :progresses="progress"
      center
    >
      {{ calculateAmpPopCv }}
      <template slot="textArea" slot-scope="textAreaProps">
        <div class="text-area">
          <h5 class="mt-2 mb-0">
            {{ textAreaProps.text.rank_name }}
          </h5>
          <p v-if="showUpgText" class="text-upgrade mb-0">
            {{ $t('Common.Terminology.RnkCv') }} {{ textAreaProps.text.CV }}
          </p>
          <p
            v-if="showAmpText"
            class="text-amp fadeAnimation"
            :class="{ show: calculateStepAmpCv(textAreaProps.text.entitlement_lvl) }"
          >
            {{ $t('Eshop.Product.AMP') }} {{ calculateStepAmpCv(textAreaProps.text.entitlement_lvl) }}
          </p>
        </div>
      </template>
    </stepped>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
import Stepped from '@/app/_global/components/elements/Stepped'

/**
 * Display upgrade steps
 *
 * This component requires enrollment ranks to be loaded and available via getMemberEnrollmentRankList getter
 * This component requires cw-info to be loaded and available via getCwInfo getter
 */
export default {
  data() {
    return {
      ranksToDisplay: 3,
      decreasing: false, // used to remove animation when decreasing the cv
      levelToStartAmp: 2,
    }
  },
  props: {
    /**
     * Member Initial Enrollment Rank
     */
    memberEnrollmentRankId: {
      type: Number,
      default: 0,
    },
    /**
     * Minimum enrollment rank
     */
    minMemberEnrollmentRankId: {
      type: Number,
      default: 0,
    },
    /**
     * Cart cv, can be an object or empty array
     *
     * @param {object} cartCv
     * @param {object} cartCv.break_down
     * @param {float} cartCv.break_down.cv
     * @param {float} cartCv.amp
     * @param {float} cartCv.upgrade
     */
    cartCvs: {
      type: [Object, Array],
    },
    /**
     * This function is called when ever the step upgrade is changed
     */
    updateStepWatcher: {
      type: Function,
      default: function() {
        return () => {}
      },
    },
    /**
     * Show amp indicators
     */
    showAmpText: {
      type: Boolean,
      default: true,
    },
    /**
     * Show upg indicators
     */
    showUpgText: {
      type: Boolean,
      default: true,
    },
  },
  components: {
    Stepped,
  },
  computed: {
    ...mapGetters(['getMemberEnrollmentRankList']),
    ...mapGetters('eshop', ['getCwInfo']),
    /**
     * go thought all he steps and add the necessary classes
     */
    steps() {
      let firstStepIndex = this.firstDisplayStepIndex
      let ranksToDisplay = this.ranksToDisplay
      let memberRankIndex = this.getMemberEnrollmentRankList.findIndex(rank => {
        return rank.id === this.memberEnrollmentRankId
      })
      return this.getMemberEnrollmentRankList.map((item, index) => {
        item.class = ''
        if (index === firstStepIndex - 1) {
          item.class = 'hide-before-line'
        }
        if (index === firstStepIndex) {
          item.class = 'half-before-line'
        }
        if (index === firstStepIndex + ranksToDisplay) {
          item.class = 'hide-after-line'
        }
        if (index === firstStepIndex - 1 + ranksToDisplay) {
          item.class = 'half-after-line'
        }
        if (index === this.upgradingToStep.index && index >= this.activeStep.index) {
          item.class += ' pointer'
        }
        if (memberRankIndex >= firstStepIndex && index === firstStepIndex) {
          item.class += ' hide-progress'
        }
        item.class = item.class.trim()
        return item
      })
    },
    /**
     * Calculate WP steps used for upgrade
     *
     * @returns {{obj: Array, index: number, level: number, nextStep: *}}
     */
    wpSteps() {
      let index = 0
      let steps = []
      let level = 0
      let nextStep = null
      let totalUpgradeCv = this.$helpers.getValue(this.cartCvs, 'total_accumulated_upgrade') || 0
      this.getMemberEnrollmentRankList.forEach(function(item, idx) {
        if (totalUpgradeCv >= item.CV) {
          steps.push(item)
          if (idx >= index) {
            index = idx
          }
          if (item.entitlement_lvl > level) {
            level = item.entitlement_lvl
            nextStep = item
          }
        }
      })
      return {
        obj: steps,
        index: index,
        level: level,
        nextStep: nextStep,
      }
    },
    /**
     * Calculate amp steps used for upgrade
     *
     * @returns {{obj: Array, index: number, level: number, nextStep: *}}
     */
    ampSteps() {
      let index = 0
      let steps = []
      let self = this
      let nextStep = null
      let level = 0
      if (this.wpSteps.level >= this.levelToStartAmp) {
        this.getMemberEnrollmentRankList.forEach(function(item, idx) {
          let ampCv = self.calculateStepAmpCv(item.entitlement_lvl)
          if (ampCv) {
            if (self.calculateAmpPopCv >= ampCv) {
              steps.push(item)
              level = item.entitlement_lvl
              if (idx >= index) {
                index = idx
              }
              nextStep = item
            }
          }
        })
      }
      return {
        obj: steps,
        index: index,
        level: level,
        nextStep: nextStep,
      }
    },
    /**
     * Calculate amp cv for step
     *
     * the calculation depends on the levelToStartAmp which is the first level to start calculating from
     * and multiply the AMP cvs per level starting from the last step of wp upgrade
     *
     * @param vue
     * @returns {function(*)}
     */
    calculateStepAmpCv: vue => level => {
      return vue.$helpers.isSet(vue.getCwInfo, 'ampCvToUpgradeEachBaLevel') &&
        level > vue.wpSteps.level &&
        level > vue.levelToStartAmp
        ? Math.max(0, level - Math.max(vue.levelToStartAmp, vue.wpSteps.level)) *
            vue.getCwInfo.ampCvToUpgradeEachBaLevel
        : ''
    },
    /**
     * The step to upgrade to
     *
     * @returns {{ampCvToNextLevel: null, wpCvToNextLevel: null, isWp: boolean}}
     */
    upgradingToStep() {
      let nextStep = {
        ampCvToNextLevel: null,
        wpCvToNextLevel: null,
        isWp: false,
      }
      if (this.wpSteps.index >= this.ampSteps.index) {
        nextStep = this.wpSteps
        nextStep.isWp = true
      } else {
        nextStep = this.ampSteps
        nextStep.isWp = false
      }
      let followingRank = this.getMemberEnrollmentRankList[nextStep.index + 1]
      if (followingRank && this.hasAmpPopCv) {
        nextStep.ampCvToNextLevel = Math.max(
          0,
          this.calculateStepAmpCv(followingRank.entitlement_lvl) - this.calculateAmpPopCv
        )
      }
      if (followingRank && this.$helpers.getValue(this.cartCvs, 'total_accumulated_upgrade')) {
        nextStep.wpCvToNextLevel = Math.max(0, followingRank.CV - this.cartCvs.total_accumulated_upgrade)
      }
      nextStep.wpStep = this.wpSteps
      nextStep.ampStep = this.ampSteps
      this.updateStepWatcher(nextStep)
      return nextStep
    },
    /**
     * Get the current users step or first step
     *
     * @returns {{index: number, obj: *}}
     */
    activeStep() {
      let index = 0
      let activeObj = null
      let self = this
      this.getMemberEnrollmentRankList.forEach(function(item, idx) {
        if (item.id === self.memberEnrollmentRankId) {
          index = idx
          activeObj = item
        }
      })
      return {
        index: index,
        obj: activeObj,
      }
    },
    /**
     * First Display Step Index
     *
     * The first index from the list of ranks to start to display in the viewport
     *
     * @returns {number}
     */
    firstDisplayStepIndex() {
      let activeIndex = this.activeStep.index
      let totalRanks = this.getMemberEnrollmentRankList.length
      let pointerStep = Math.max(0, this.upgradingToStep.index + 1 - (this.ranksToDisplay - 1))
      let minRankIndex = this.getMemberEnrollmentRankList.findIndex(item => {
        return item.id === this.minMemberEnrollmentRankId
      })
      // Move step offset only if its not grater than ranks to display
      pointerStep = this.ranksToDisplay >= totalRanks - pointerStep ? totalRanks - this.ranksToDisplay : pointerStep
      return activeIndex >= totalRanks - this.ranksToDisplay
        ? totalRanks - this.ranksToDisplay
        : Math.max(minRankIndex, Math.max(0, activeIndex - 1) + Math.max(pointerStep))
    },
    /**
     * Calculates progress bars for the added cv
     *
     * @returns {Array}
     */
    progress() {
      let progresses = []
      for (let i = 0; i < this.getMemberEnrollmentRankList.length; i++) {
        if (this.ampSteps.index > this.wpSteps.index && this.ampSteps.index > i) {
          progresses.push({ index: i, value: 100, class: 'amp' })
        } else {
          progresses.push({ index: i, value: 0, class: 'amp' })
        }
      }
      for (let i = 0; i < this.getMemberEnrollmentRankList.length; i++) {
        if (this.wpSteps.index > i) {
          progresses.push({ index: i, value: 100, class: 'ba' })
        } else {
          progresses.push({ index: i, value: 0, class: 'ba' })
        }
      }
      return progresses
    },
    /**
     * Styles computed to display the viewport
     *
     * @returns {{width: string, transform: string}}
     */
    computedStyles() {
      let totalRanks = this.getMemberEnrollmentRankList.length
      let width = (totalRanks * 100) / this.ranksToDisplay
      let offsetPerRank = 100 / totalRanks
      let offsetLeft = offsetPerRank * this.firstDisplayStepIndex
      return {
        width: width + '%',
        transform: `translateX(-${offsetLeft}%)`,
      }
    },
    calculateAmpPopCv() {
      return (
        this.$helpers.getValue(this.cartCvs, 'total_accumulated_amp', 0) +
        this.$helpers.getValue(this.cartCvs, 'total_accumulated_base', 0)
      )
    },
    hasAmpPopCv() {
      return (
        this.$helpers.getValue(this.cartCvs, 'total_accumulated_amp') ||
        this.$helpers.getValue(this.cartCvs, 'total_accumulated_base')
      )
    },
  },
  watch: {
    /**
     * Watch the cart cv changes to identify if the progress is increasing or decreasing
     * to add class to the stepper to stop animation from running when decreasing progress
     *
     * @param to
     * @param from
     */
    cartCvs(to, from) {
      this.decreasing = false
      if (
        this.$helpers.isSet(from, 'total_accumulated_upgrade') &&
        this.$helpers.isSet(to, 'total_accumulated_upgrade') &&
        this.$helpers.isSet(to, 'total_accumulated_base')
      ) {
        if (from.upgrade > to.total_accumulated_upgrade) {
          this.decreasing = true
        }
      }
      if (this.$helpers.isSet(from, 'total_accumulated_amp') && this.$helpers.isSet(to, 'total_accumulated_amp')) {
        if (from.total_accumulated_amp > to.total_accumulated_amp) {
          this.decreasing = true
        }
      }

      if (this.$helpers.isSet(from, 'total_accumulated_base') && this.$helpers.isSet(to, 'total_accumulated_base')) {
        if (from.total_accumulated_base > to.total_accumulated_base) {
          this.decreasing = true
        }
      }
    },
  },
}
</script>
