import { defineStore } from 'pinia'
import Strings from '@/common/utils/strings.ts'

export interface SMHState {
  mode: 'every' | 'period1' | 'period2' | 'specify'
  period1: {
    start: number
    end: number
  }
  period2: {
    start: number
    end: number
  }
  specify: number[]
}

export interface DState {
  mode: 'none' | 'every' | 'last' | 'near' | 'period1' | 'period2' | 'specify'
  period1: {
    start: number
    end: number
  }
  period2: {
    start: number
    end: number
  }
  specify: number[]
  near: number
}

export interface MState {
  mode: 'none' | 'every' | 'period1' | 'period2' | 'specify'
  period1: {
    start: number
    end: number
  }
  period2: {
    start: number
    end: number
  }
  specify: number[]
}

export interface WState {
  mode: 'none' | 'every' | 'last' | 'period1' | 'period2' | 'specify'
  period1: {
    start: number
    end: number
  }
  period2: {
    start: number
    end: number
  }
  specify: number[]
  last: number
}

export interface YState {
  mode: 'none' | 'every' | 'period1'
  period1: {
    start: number
    end: number
  }
}

export const useCronStore = defineStore('Cron', () => {
  const secondState = reactive<SMHState>({
    mode: 'every',
    period1: {
      start: 1,
      end: 2,
    },
    period2: {
      start: 1,
      end: 1,
    },
    specify: [],
  })
  const secondVal = computed(() => {
    let data: string = '*'
    if (secondState.mode === 'period1') {
      data = `${secondState.period1.start}-${secondState.period1.end}`
    } else if (secondState.mode === 'period2') {
      data = `${secondState.period2.start}/${secondState.period2.end}`
    } else if (secondState.mode === 'specify') {
      data = secondState.specify.sort((a, b) => a - b).join(',')
    }
    return data
  })
  const setSecondVal = (val: string) => {
    if (val.includes('-')) {
      const s = val.split('-')
      secondState.period1.start = +s[0]
      secondState.period1.end = +s[1]
      secondState.mode = 'period1'
    } else if (val.includes('/')) {
      const s = val.split('/')
      secondState.period2.start = +s[0]
      secondState.period2.end = +s[1]
      secondState.mode = 'period2'
    } else if (val.includes(',')) {
      secondState.specify = val.split(',').map(it => +it)
      secondState.mode = 'specify'
    } else if (Strings.isNumStr(val)) {
      secondState.specify = [ +val ]
      secondState.mode = 'specify'
    } else {
      secondState.mode = 'every'
    }
  }

  const minuteState = reactive<SMHState>({
    mode: 'every',
    period1: {
      start: 1,
      end: 2,
    },
    period2: {
      start: 1,
      end: 1,
    },
    specify: [],
  })
  const minuteVal = computed(() => {
    let data: string = '*'
    if (minuteState.mode === 'period1') {
      data = `${minuteState.period1.start}-${minuteState.period1.end}`
    } else if (minuteState.mode === 'period2') {
      data = `${minuteState.period2.start}/${minuteState.period2.end}`
    } else if (minuteState.mode === 'specify') {
      data = minuteState.specify.sort((a, b) => a - b).join(',')
    }
    return data
  })
  const setMinuteVal = (val: string) => {
    if (val.includes('-')) {
      const s = val.split('-')
      minuteState.period1.start = +s[0]
      minuteState.period1.end = +s[1]
      minuteState.mode = 'period1'
    } else if (val.includes('/')) {
      const s = val.split('/')
      minuteState.period2.start = +s[0]
      minuteState.period2.end = +s[1]
      minuteState.mode = 'period2'
    } else if (val.includes(',')) {
      minuteState.specify = val.split(',').map(it => +it)
      minuteState.mode = 'specify'
    } else if (Strings.isNumStr(val)) {
      minuteState.specify = [ +val ]
      minuteState.mode = 'specify'
    } else {
      minuteState.mode = 'every'
    }
  }

  const hourState = reactive<SMHState>({
    mode: 'every',
    period1: {
      start: 1,
      end: 2,
    },
    period2: {
      start: 1,
      end: 1,
    },
    specify: [],
  })
  const hourVal = computed(() => {
    let data: string = '*'
    if (hourState.mode === 'period1') {
      data = `${hourState.period1.start}-${hourState.period1.end}`
    } else if (hourState.mode === 'period2') {
      data = `${hourState.period2.start}/${hourState.period2.end}`
    } else if (hourState.mode === 'specify') {
      data = hourState.specify.sort((a, b) => a - b).join(',')
    }
    return data
  })
  const setHourVal = (val: string) => {
    if (val.includes('-')) {
      const s = val.split('-')
      hourState.period1.start = +s[0]
      hourState.period1.end = +s[1]
      hourState.mode = 'period1'
    } else if (val.includes('/')) {
      const s = val.split('/')
      hourState.period2.start = +s[0]
      hourState.period2.end = +s[1]
      hourState.mode = 'period2'
    } else if (val.includes(',')) {
      hourState.specify = val.split(',').map(it => +it)
      hourState.mode = 'specify'
    } else if (Strings.isNumStr(val)) {
      hourState.specify = [ +val ]
      hourState.mode = 'specify'
    } else {
      hourState.mode = 'every'
    }
  }

  const dayState = reactive<DState>({
    mode: 'every',
    period1: {
      start: 1,
      end: 2,
    },
    period2: {
      start: 1,
      end: 1,
    },
    specify: [],
    near: 1,
  })
  const dayVal = computed(() => {
    let data: string = '*'
    if (dayState.mode === 'none') {
      data = '?'
    } else if (dayState.mode === 'last') {
      data = 'L'
    } else if (dayState.mode === 'near') {
      data = `${dayState.near}W`
    } else if (dayState.mode === 'period1') {
      data = `${dayState.period1.start}-${dayState.period1.end}`
    } else if (dayState.mode === 'period2') {
      data = `${dayState.period2.start}/${dayState.period2.end}`
    } else if (dayState.mode === 'specify') {
      data = dayState.specify.sort((a, b) => a - b).join(',')
    }
    return data
  })
  const setDayVal = (val: string) => {
    if (val === '?') {
      dayState.mode = 'none'
    } else if (val === 'L') {
      dayState.mode = 'last'
    } else if (val.includes('W')) {
      const s = val.split('W')
      dayState.near = +s[0]
      dayState.mode = 'near'
    } else if (val.includes('-')) {
      const s = val.split('-')
      dayState.period1.start = +s[0]
      dayState.period1.end = +s[1]
      dayState.mode = 'period1'
    } else if (val.includes('/')) {
      const s = val.split('/')
      dayState.period2.start = +s[0]
      dayState.period2.end = +s[1]
      dayState.mode = 'period2'
    } else if (val.includes(',')) {
      dayState.specify = val.split(',').map(it => +it)
      dayState.mode = 'specify'
    } else if (Strings.isNumStr(val)) {
      dayState.specify = [ +val ]
      dayState.mode = 'specify'
    } else {
      dayState.mode = 'every'
    }
  }

  const monthState = reactive<MState>({
    mode: 'every',
    period1: {
      start: 1,
      end: 2,
    },
    period2: {
      start: 1,
      end: 1,
    },
    specify: [],
  })
  const monthVal = computed(() => {
    let data: string = '*'
    if (monthState.mode === 'none') {
      data = '?'
    } else if (monthState.mode === 'period1') {
      data = `${monthState.period1.start}-${monthState.period1.end}`
    } else if (monthState.mode === 'period2') {
      data = `${monthState.period2.start}/${monthState.period2.end}`
    } else if (monthState.mode === 'specify') {
      data = monthState.specify.sort((a, b) => a - b).join(',')
    }
    return data
  })
  const setMonthVal = (val: string) => {
    if (val === '?') {
      monthState.mode = 'none'
    } else if (val.includes('-')) {
      const s = val.split('-')
      monthState.period1.start = +s[0]
      monthState.period1.end = +s[1]
      monthState.mode = 'period1'
    } else if (val.includes('/')) {
      const s = val.split('/')
      monthState.period2.start = +s[0]
      monthState.period2.end = +s[1]
      monthState.mode = 'period2'
    } else if (val.includes(',')) {
      monthState.specify = val.split(',').map(it => +it)
      monthState.mode = 'specify'
    } else if (Strings.isNumStr(val)) {
      monthState.specify = [ +val ]
      monthState.mode = 'specify'
    } else {
      monthState.mode = 'every'
    }
  }

  const weekState = reactive<WState>({
    mode: 'none',
    period1: {
      start: 1,
      end: 2,
    },
    period2: {
      start: 1,
      end: 1,
    },
    specify: [],
    last: 1,
  })
  const weekVal = computed(() => {
    let data: string = '*'
    if (weekState.mode === 'none') {
      data = '?'
    } else if (weekState.mode === 'last') {
      data = `${(weekState.last + 1) % 7}L`
    } else if (weekState.mode === 'period1') {
      data = `${(weekState.period1.start + 1) % 7}-${(weekState.period1.end + 1) % 7}`
    } else if (weekState.mode === 'period2') {
      data = `${(weekState.period2.start + 1) % 7}#${(weekState.period2.end + 1) % 7}`
    } else if (weekState.mode === 'specify') {
      data = weekState.specify.map(it => (it + 1) % 7).sort((a, b) => a - b).join(',')
    }
    return data
  })
  const setWeekVal = (val: string) => {
    if (val === '?') {
      weekState.mode = 'none'
    } else if (val.includes('L')) {
      const s = val.split('L')
      let s0 = +s[0]
      weekState.last = s0 === 0 ? 6 : (s0 - 1)
      weekState.mode = 'last'
    } else if (val.includes('-')) {
      const s = val.split('-')
      let s0 = +s[0]
      let s1 = +s[1]
      secondState.period1.start = s0 === 0 ? 6 : (s0 - 1)
      secondState.period1.end = s1 === 0 ? 6 : (s1 - 1)
      secondState.mode = 'period1'
    } else if (val.includes('#')) {
      const s = val.split('#')
      let s0 = +s[0]
      let s1 = +s[1]
      weekState.period2.start = s0 === 0 ? 6 : (s0 - 1)
      weekState.period2.end = s1 === 0 ? 6 : (s1 - 1)
      weekState.mode = 'period2'
    } else if (val.includes(',')) {
      weekState.specify = val.split(',').map(it => {
        let num = +it
        return num === 0 ? 6 : (num - 1)
      })
      weekState.mode = 'specify'
    } else if (Strings.isNumStr(val)) {
      let num = +val
      weekState.specify = [ num === 0 ? 6 : (num - 1) ]
      weekState.mode = 'specify'
    } else {
      weekState.mode = 'every'
    }
  }

  let year = new Date().getFullYear()
  const yearState = reactive<YState>({
    mode: 'none',
    period1: {
      start: year,
      end: year + 10,
    },

  })
  const yearVal = computed(() => {
    let data: string = ''
    if (yearState.mode === 'none') {
      data = ''
    } else if (yearState.mode === 'period1') {
      data = `${yearState.period1.start}-${yearState.period1.end}`
    }
    return data
  })
  const setYearVal = (val: string) => {
    if (val === '') {
      yearState.mode = 'none'
    } else if (val.includes('-')) {
      const s = val.split('-')
      yearState.period1.start = +s[0]
      yearState.period1.end = +s[1]
      yearState.mode = 'period1'
    } else {
      yearState.mode = 'every'
    }
  }

  const cronVal = computed({
    get() {
      return `${secondVal.value} ${minuteVal.value} ${hourVal.value} ${dayVal.value} ${monthVal.value} ${weekVal.value} ${yearVal.value}`
    },
    set(val: string = '* * * * * ?') {
      let sections = val.split(' ')
      if (sections.length === 6) {
        sections.push('')
      }
      if (sections.length != 7) {
        sections = [ '*', '*', '*', '*', '*', '*', '' ]
      }
      setSecondVal(sections[0])
      setMinuteVal(sections[1])
      setHourVal(sections[2])
      setDayVal(sections[3])
      setMonthVal(sections[4])
      setWeekVal(sections[5])
      setYearVal(sections[6])
    },
  })

  return {
    secondState,
    secondVal,
    setSecondVal,
    minuteState,
    minuteVal,
    setMinuteVal,
    hourState,
    hourVal,
    setHourVal,
    dayState,
    dayVal,
    setDayVal,
    monthState,
    monthVal,
    setMonthVal,
    weekState,
    weekVal,
    setWeekVal,
    yearState,
    yearVal,
    setYearVal,
    cronVal,
    // setCronVal,
  }
})
