import { xss } from '@opentiny/utils'

export const createShepherd =
  ({ state, props, Shepherd, offset, designConfig }) =>
  () => {
    const tour = newTour(state, Shepherd, offset, designConfig, props)

    state.tour = tour

    const result = {}
    const deepCopy = getItemCopy(props, tour, result)

    if (state.domData && state.domData !== 0) {
      state.domData.forEach((item, i) => {
        let steps = itemStep(item, state, deepCopy, i, Shepherd)

        const step = tour.addStep(steps)
        if (steps.hightBox && steps.hightBox.length !== 0) {
          step.on('show', () => {
            steps.hightBox.forEach((item) => {
              document.querySelector(item).classList.add('tiny-guide__z-top')
            })
          })
          step.on('hide', () => {
            steps.hightBox.forEach((item) => {
              document.querySelector(item).classList.remove('tiny-guide__z-top')
            })
          })
          step.on('complete', () => {
            steps.hightBox.forEach((item) => {
              document.querySelector(item).classList.remove('tiny-guide__z-top')
            })
          })
          step.on('cancel', () => {
            steps.hightBox.forEach((item) => {
              document.querySelector(item).classList.remove('tiny-guide__z-top')
            })
          })
          step.on('destroy', () => {
            steps.hightBox.forEach((item) => {
              document.querySelector(item).classList.remove('tiny-guide__z-top')
            })
          })
        }
        callBack(step, item, tour)
      })
    }

    state.tour.start()
    if (props.width || props.height) {
      const dom = document.querySelector('.tiny-guide.shepherd-element') as HTMLElement
      document.documentElement.style.setProperty('--tiny-guide-shepherd-element-size', `${props.width}px`)
      dom.style.height = `${props.height}px`
    }
  }

export const mounted =
  ({ state, api }) =>
  () => {
    if (state.showStep) {
      api.createShepherd()
    }
  }

export const beforeUnmount = (state) => () => {
  state?.tour?.hide()
}

const getItemCopy = (props, tour, result) => {
  const { domData } = props

  result = domData.map((item) => {
    const itemCopy = JSON.parse(JSON.stringify(item))

    itemCopy.button = item.button.map((e) => {
      const eCopy = JSON.parse(JSON.stringify(e))

      eCopy.action = tour[e.action]
      return eCopy
    })
    return itemCopy
  })
  return result
}

const newTour = (state, Shepherd, offset, designConfig, props) => {
  const tour = new Shepherd.Tour({
    useModalOverlay: props.mask ?? designConfig?.state?.isUseModalOverlay,
    defaultStepOptions: {
      modalOverlayOpeningPadding: state.modalOverlayOpeningPadding,
      modalOverlayOpeningRadius: state.modalOverlayOpeningRadius,
      arrow: state.arrow,
      highlightClass: state.lightClass,
      classes: 'tiny-guide',
      floatingUIOptions: {
        middleware: [
          offset({
            mainAxis: state.mainAxis,
            crossAxis: state.crossAxis,
            alignmentAxis: state.alignmentAxis
          })
        ]
      }
    }
  })
  return tour
}

const itemStep = (item, state, deepCopy, index, Shepherd) => {
  let steps = {
    text: xss.filterUrl(item.text),
    title: xss.filterUrl(item.title),
    classes: item.classes,
    attachTo: {
      element: item.domElement,
      on: item.popPosition || state.popPosition
    },
    hightBox: item.hightBox || null,
    buttons: deepCopy[index].button,
    cancelIcon: {
      enabled: state.showClose
    },
    id: item.id,
    scrollTo: true,
    scrollToHandler(el) {
      if (el && el.getBoundingClientRect().top > document.documentElement.clientHeight) {
        if (document.documentElement.scrollTop > 0) {
          window.scrollTo(0, document.documentElement.scrollTop + el.getBoundingClientRect().top / 2)
        } else {
          window.scrollTo(0, el.getBoundingClientRect().top - document.documentElement.clientHeight / 2)
        }
      }
    },
    when: {
      show() {
        const currentStep = Shepherd.activeTour && Shepherd.activeTour.getCurrentStep()
        const currentStepElement = currentStep && currentStep.getElement()
        const footer = currentStepElement && currentStepElement.querySelector('.shepherd-footer')
        const cancelIcon =
          currentStepElement && currentStepElement.querySelector('.shepherd-header .shepherd-cancel-icon span')
        if (cancelIcon) {
          if (state.showClose) {
            const cloesIcon = `<svg  viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <desc fill="none">
                Created with Pixso.
            </desc>
            <defs fill="none" />
            <g>
              <path id="path" d="M12.49 3.3C12.66 3.47 12.66 3.74 12.54 3.92L8.58 7.89L12.49 11.77C12.7 11.96 12.72 12.25 12.54 12.48C12.37 12.67 12.05 12.72 11.83 12.54L7.88 8.58L4 12.49C3.82 12.66 3.5 12.67 3.32 12.5C3.13 12.33 3.08 12.05 3.24 11.83L7.17 7.89L3.29 4C3.12 3.79 3.13 3.48 3.33 3.29C3.5 3.15 3.75 3.13 3.91 3.24L7.88 7.17L11.78 3.3C11.96 3.08 12.29 3.08 12.49 3.3Z" fill-opacity="1.000000" fill-rule="evenodd"/>
            </g>
          </svg>`

            cancelIcon.innerHTML = cloesIcon
          } else {
            cancelIcon.parentElement.style.display = 'none'
          }
        }
        const progress = document.createElement('span')
        progress.classList.add('progress-style')
        progress.innerText = `${Shepherd.activeTour && Shepherd.activeTour.steps.indexOf(currentStep) + 1}/${
          Shepherd.activeTour && Shepherd.activeTour.steps.length
        }`
        footer && footer.insertBefore(progress, currentStepElement.querySelector('.shepherd-button'))
      }
    }
  }
  return steps
}

const callBack = (step, item, tour) => {
  step.on('before-show', () => {
    if (typeof item.beforeShow === 'function') {
      item.beforeShow()
    }
  })
  step.on('show', () => {
    if (typeof item.show === 'function') {
      item.show()
    }
  })
  step.on('before-hide', () => {
    if (typeof item.beforeHide === 'function') {
      item.beforeHide()
    }
  })
  step.on('hide', () => {
    if (typeof item.hide === 'function') {
      item.hide()
    }
  })
  tour.on('complete', () => {
    if (typeof item.complete === 'function') {
      item.complete()
    }
  })
  tour.on('cancel', () => {
    if (typeof item.cancel === 'function') {
      item.cancel()
    }
  })
  step.on('destroy', () => {
    if (typeof item.destroy === 'function') {
      item.destroy()
    }
  })
}