import { writable, get } from "svelte/store"
import { store as frontendStore } from "builderStore"
import { findComponentPath } from "builderStore/storeUtils"

export const DropEffect = {
  MOVE: "move",
  COPY: "copy",
}

export const DropPosition = {
  ABOVE: "above",
  BELOW: "below",
  INSIDE: "inside",
}

export default function () {
  const store = writable({})

  store.actions = {
    dragstart: component => {
      store.update(state => {
        state.dragged = component
        return state
      })
    },
    dragover: ({
      component,
      index,
      canHaveChildrenButIsEmpty,
      mousePosition,
    }) => {
      store.update(state => {
        state.targetComponent = component
        // only allow dropping inside when container is empty
        // if container has children, drag over them

        if (canHaveChildrenButIsEmpty && index === 0) {
          // hovered above center of target
          if (mousePosition < 0.4) {
            state.dropPosition = DropPosition.ABOVE
          }

          // hovered around bottom of target
          if (mousePosition > 0.8) {
            state.dropPosition = DropPosition.BELOW
          }

          // hovered in center of target
          if (mousePosition > 0.4 && mousePosition < 0.8) {
            state.dropPosition = DropPosition.INSIDE
          }
          return state
        }

        // bottom half
        if (mousePosition > 0.5) {
          state.dropPosition = DropPosition.BELOW
        } else {
          state.dropPosition = canHaveChildrenButIsEmpty
            ? DropPosition.INSIDE
            : DropPosition.ABOVE
        }

        return state
      })
    },
    reset: () => {
      store.update(state => {
        state.dropPosition = ""
        state.targetComponent = null
        state.dragged = null
        return state
      })
    },
    drop: () => {
      const state = get(store)

      // Stop if the target and source are the same
      if (state.targetComponent === state.dragged) {
        return
      }
      // Stop if the target or source are null
      if (!state.targetComponent || !state.dragged) {
        return
      }
      // Stop if the target is a child of source
      const path = findComponentPath(state.dragged, state.targetComponent._id)
      const ids = path.map(component => component._id)
      if (ids.includes(state.targetComponent._id)) {
        return
      }

      // Cut and paste the component
      frontendStore.actions.components.copy(state.dragged, true)
      frontendStore.actions.components.paste(
        state.targetComponent,
        state.dropPosition
      )
      store.actions.reset()
    },
  }

  return store
}
