/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  defineComponent,
  PropType,
  toRefs,
  h,
  onMounted,
  ref,
  watch,
  computed,
  getCurrentInstance
} from 'vue'
import { useI18n } from 'vue-i18n'
import Modal from '@/components/modal'
import { useForm } from './use-form'
import { useModal } from './use-modal'
import {
  NForm,
  NFormItem,
  NButton,
  NIcon,
  NInput,
  NSpace,
  NRadio,
  NRadioGroup,
  NSelect,
  NDatePicker,
  NInputGroup,
  NList,
  NListItem,
  NThing,
  NPopover
} from 'naive-ui'
import { ArrowDownOutlined, ArrowUpOutlined } from '@vicons/antd'
import { timezoneList } from '@/common/timezone'
import Crontab from '@/components/crontab'

const props = {
  row: {
    type: Object,
    default: {}
  },
  show: {
    type: Boolean as PropType<boolean>,
    default: false
  },
  type: {
    type: String as PropType<String>,
    default: 'create'
  }
}

export default defineComponent({
  name: 'workflowDefinitionStart',
  props,
  emits: ['update:show', 'update:row', 'updateList'],
  setup(props, ctx) {
    const crontabRef = ref()
    const parallelismRef = ref(false)
    const { t } = useI18n()
    const { timingState } = useForm()
    const {
      variables,
      handleCreateTiming,
      handleUpdateTiming,
      getWorkerGroups,
      getAlertGroups,
      getEnvironmentList,
      getPreviewSchedule
    } = useModal(timingState, ctx)

    const environmentOptions = computed(() =>
      variables.environmentList.filter((item: any) =>
        item.workerGroups?.includes(timingState.timingForm.workerGroup)
      )
    )

    const hideModal = () => {
      ctx.emit('update:show')
    }

    const handleTiming = () => {
      if (props.type === 'create') {
        handleCreateTiming(props.row.code as number)
      } else {
        handleUpdateTiming(props.row.id)
      }
    }

    const priorityOptions = [
      {
        value: 'HIGHEST',
        label: 'HIGHEST',
        color: '#ff0000',
        icon: ArrowUpOutlined
      },
      {
        value: 'HIGH',
        label: 'HIGH',
        color: '#ff0000',
        icon: ArrowUpOutlined
      },
      {
        value: 'MEDIUM',
        label: 'MEDIUM',
        color: '#EA7D24',
        icon: ArrowUpOutlined
      },
      {
        value: 'LOW',
        label: 'LOW',
        color: '#2A8734',
        icon: ArrowDownOutlined
      },
      {
        value: 'LOWEST',
        label: 'LOWEST',
        color: '#2A8734',
        icon: ArrowDownOutlined
      }
    ]

    const timezoneOptions = () =>
      timezoneList.map((item) => ({ label: item, value: item }))

    const renderLabel = (option: any) => {
      return [
        h(
          NIcon,
          {
            style: {
              verticalAlign: 'middle',
              marginRight: '4px',
              marginBottom: '3px'
            },
            color: option.color
          },
          {
            default: () => h(option.icon)
          }
        ),
        option.label
      ]
    }

    const updateWorkerGroup = () => {
      timingState.timingForm.environmentCode = null
    }

    const handlePreview = () => {
      getPreviewSchedule()
    }

    const initEnvironment = () => {
      timingState.timingForm.environmentCode = null
      variables.environmentList.forEach((item) => {
        if (props.row.environmentCode === item.value) {
          timingState.timingForm.environmentCode = item.value
        }
      })
    }

    const initWarningGroup = () => {
      timingState.timingForm.warningGroupId = null
      variables.alertGroups.forEach((item) => {
        if (props.row.warningGroupId === item.value) {
          timingState.timingForm.warningGroupId = item.value
        }
      })
    }

    const trim = getCurrentInstance()?.appContext.config.globalProperties.trim

    onMounted(() => {
      getWorkerGroups()
      getAlertGroups()
      getEnvironmentList()
    })

    watch(
      () => props.row,
      () => {
        if (!props.row.crontab) return

        timingState.timingForm.startEndTime = [
          new Date(props.row.startTime),
          new Date(props.row.endTime)
        ]
        timingState.timingForm.crontab = props.row.crontab
        timingState.timingForm.timezoneId = props.row.timezoneId
        timingState.timingForm.failureStrategy = props.row.failureStrategy
        timingState.timingForm.warningType = props.row.warningType
        timingState.timingForm.processInstancePriority =
          props.row.processInstancePriority
        timingState.timingForm.workerGroup = props.row.workerGroup
        initWarningGroup()
        initEnvironment()
      }
    )

    return {
      t,
      crontabRef,
      parallelismRef,
      priorityOptions,
      environmentOptions,
      hideModal,
      handleTiming,
      timezoneOptions,
      renderLabel,
      updateWorkerGroup,
      handlePreview,
      ...toRefs(variables),
      ...toRefs(timingState),
      ...toRefs(props),
      trim
    }
  },

  render() {
    const { t } = this

    return (
      <Modal
        show={this.show}
        title={t('project.workflow.set_parameters_before_timing')}
        onCancel={this.hideModal}
        onConfirm={this.handleTiming}
        confirmLoading={this.saving}
      >
        <NForm ref='timingFormRef'>
          <NFormItem
            label={t('project.workflow.start_and_stop_time')}
            path='startEndTime'
          >
            <NDatePicker
              type='datetimerange'
              clearable
              v-model:value={this.timingForm.startEndTime}
            />
          </NFormItem>
          <NFormItem label={t('project.workflow.timing')} path='crontab'>
            <NInputGroup>
              <NPopover
                trigger='click'
                showArrow={false}
                placement='bottom'
                style={{ width: '500px' }}
              >
                {{
                  trigger: () => (
                    <NInput
                      allowInput={this.trim}
                      style={{ width: '80%' }}
                      readonly={true}
                      v-model:value={this.timingForm.crontab}
                    ></NInput>
                  ),
                  default: () => (
                    <Crontab v-model:value={this.timingForm.crontab} />
                  )
                }}
              </NPopover>
              <NButton type='primary' ghost onClick={this.handlePreview}>
                {t('project.workflow.execute_time')}
              </NButton>
            </NInputGroup>
          </NFormItem>
          <NFormItem
            label={t('project.workflow.timezone')}
            path='timezoneId'
            showFeedback={false}
          >
            <NSelect
              v-model:value={this.timingForm.timezoneId}
              options={this.timezoneOptions()}
              filterable
            />
          </NFormItem>
          <NFormItem label=' ' showFeedback={false}>
            <NList>
              <NListItem>
                <NThing
                  description={t('project.workflow.next_five_execution_times')}
                >
                  {this.schedulePreviewList.map((item: string) => (
                    <NSpace>
                      {item}
                      <br />
                    </NSpace>
                  ))}
                </NThing>
              </NListItem>
            </NList>
          </NFormItem>
          <NFormItem
            label={t('project.workflow.failure_strategy')}
            path='failureStrategy'
          >
            <NRadioGroup v-model:value={this.timingForm.failureStrategy}>
              <NSpace>
                <NRadio value='CONTINUE'>
                  {t('project.workflow.continue')}
                </NRadio>
                <NRadio value='END'>{t('project.workflow.end')}</NRadio>
              </NSpace>
            </NRadioGroup>
          </NFormItem>
          <NFormItem
            label={t('project.workflow.notification_strategy')}
            path='warningType'
          >
            <NSelect
              options={[
                {
                  value: 'NONE',
                  label: t('project.workflow.none_send')
                },
                {
                  value: 'SUCCESS',
                  label: t('project.workflow.success_send')
                },
                {
                  value: 'FAILURE',
                  label: t('project.workflow.failure_send')
                },
                {
                  value: 'ALL',
                  label: t('project.workflow.all_send')
                }
              ]}
              v-model:value={this.timingForm.warningType}
            />
          </NFormItem>
          <NFormItem
            label={t('project.workflow.workflow_priority')}
            path='processInstancePriority'
          >
            <NSelect
              options={this.priorityOptions}
              renderLabel={this.renderLabel}
              v-model:value={this.timingForm.processInstancePriority}
            />
          </NFormItem>
          <NFormItem
            label={t('project.workflow.worker_group')}
            path='workerGroup'
          >
            <NSelect
              options={this.workerGroups}
              onUpdateValue={this.updateWorkerGroup}
              v-model:value={this.timingForm.workerGroup}
            />
          </NFormItem>
          <NFormItem
            label={t('project.workflow.environment_name')}
            path='environmentCode'
          >
            <NSelect
              options={this.environmentOptions}
              v-model:value={this.timingForm.environmentCode}
              clearable
            />
          </NFormItem>
          {this.timingForm.warningType !== 'NONE' && ( <NFormItem
            label={t('project.workflow.alarm_group')}
            path='warningGroupId'
          >
            <NSelect
              options={this.alertGroups}
              placeholder={t('project.workflow.please_choose')}
              v-model:value={this.timingForm.warningGroupId}
              clearable
            />
          </NFormItem> )}
        </NForm>
      </Modal>
    )
  }
})
