/*
 * 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, ref, inject, PropType, Ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Styles from './dag.module.scss'
import {
  NTooltip,
  NIcon,
  NButton,
  NSelect,
  NPopover,
  NText,
  NTag
} from 'naive-ui'
import {
  SearchOutlined,
  DownloadOutlined,
  FullscreenOutlined,
  FullscreenExitOutlined,
  InfoCircleOutlined,
  FormatPainterOutlined,
  CopyOutlined,
  DeleteOutlined,
  RightCircleOutlined,
  FundViewOutlined,
  SyncOutlined
} from '@vicons/antd'
import { useNodeSearch, useTextCopy } from './dag-hooks'
import { DataUri } from '@antv/x6'
import { useFullscreen } from '@vueuse/core'
import { useRoute, useRouter } from 'vue-router'
import { useThemeStore } from '@/store/theme/theme'
import type { Graph } from '@antv/x6'
import StartupParam from './dag-startup-param'
import VariablesView from '@/views/projects/workflow/instance/components/variables-view'
import { WorkflowDefinition, WorkflowInstance } from './types'
import { useDependencies } from '@/views/projects/components/dependencies/use-dependencies'

const props = {
  layoutToggle: {
    type: Function as PropType<(bool?: boolean) => void>,
    default: () => {}
  },
  // If this prop is passed, it means from definition detail
  instance: {
    type: Object as PropType<WorkflowInstance>,
    default: null
  },
  definition: {
    // The same as the structure responsed by the queryWorkflowDefinitionByCode api
    type: Object as PropType<WorkflowDefinition>,
    default: null
  },
  dependenciesData: {
    type: Object as PropType<any>,
    require: false
  }
}

export default defineComponent({
  name: 'workflow-dag-toolbar',
  props,
  emits: ['versionToggle', 'saveModelToggle', 'removeTasks', 'refresh'],
  setup(props, context) {
    const { t } = useI18n()

    const themeStore = useThemeStore()

    const graph = inject<Ref<Graph | undefined>>('graph', ref())
    const router = useRouter()
    const route = useRoute()
    const projectCode = Number(route.params.projectCode)
    const workflowCode = Number(route.params.code)
    const { getDependentTaskLinksByMultipleTasks } = useDependencies()

    const dependenciesData = props.dependenciesData

    /**
     * Node search and navigate
     */
    const {
      searchSelectValue,
      navigateTo,
      toggleSearchInput,
      searchInputVisible,
      reQueryNodes,
      nodesDropdown
    } = useNodeSearch({ graph })

    /**
     * Download Workflow Image
     * @param {string} fileName
     * @param {string} bgColor
     */
    const downloadPNG = (options = { fileName: 'dag', bgColor: '#f2f3f7' }) => {
      const { fileName, bgColor } = options
      graph.value?.toPNG(
        (dataUri: string) => {
          DataUri.downloadDataUri(dataUri, `${fileName}.png`)
        },
        {
          padding: {
            top: 50,
            right: 50,
            bottom: 50,
            left: 50
          },
          backgroundColor: bgColor
        }
      )
    }

    /**
     * Toggle fullscreen
     */
    const { isFullscreen, toggle } = useFullscreen()

    /**
     * Open workflow version modal
     */
    const openVersionModal = () => {
      context.emit('versionToggle', true)
    }

    /**
     * Open DAG format modal
     */
    const onFormat = () => {
      props.layoutToggle(true)
    }

    /**
     * Back to the entrance
     */
    const onClose = () => {
      const { back, current } = history.state
      if (back && back !== '/login') {
        router.go(-1)
        return
      }
      if (!back || current.includes('workflow/definitions')) {
        router.push({
          path: `/projects/${route.params.projectCode}/workflow-definition`
        })
        return
      }
      if (current.includes('workflow/instances')) {
        router.push({
          path: `/projects/${route.params.projectCode}/workflow/instances`
        })
        return
      }
    }

    /**
     *  Copy workflow name
     */
    const { copy } = useTextCopy()

    /**
     * Delete selected edges and nodes
     */
    const removeCells = async () => {
      if (graph.value) {
        const cells = graph.value.getSelectedCells()
        if (cells) {
          const codes = cells
            .filter((cell) => cell.isNode())
            .map((cell) => +cell.id)
          const res = await getDependentTaskLinksByMultipleTasks(
            projectCode,
            workflowCode,
            codes
          )
          if (res.length > 0) {
            dependenciesData.showRef = true
            dependenciesData.taskLinks = res
            dependenciesData.tip = t(
              'project.task.delete_validate_dependent_tasks_desc'
            )
            dependenciesData.required = true
          } else {
            context.emit('removeTasks', codes, cells)
            graph.value?.removeCells(cells)
          }
        }
      }
    }

    return () => (
      <div
        class={[
          Styles.toolbar,
          Styles[themeStore.darkTheme ? 'toolbar-dark' : 'toolbar-light']
        ]}
      >
        <span class={Styles['workflow-name']}>
          {route.name === 'workflow-instance-detail'
            ? props.instance?.name
            : props.definition?.workflowDefinition?.name ||
              t('project.dag.create')}
        </span>
        {props.definition?.workflowDefinition?.name && (
          <NTooltip
            v-slots={{
              trigger: () => (
                <NButton
                  quaternary
                  circle
                  onClick={() => {
                    const name =
                      route.name === 'workflow-instance-detail'
                        ? props.instance?.name
                        : props.definition?.workflowDefinition?.name
                    copy(name)
                  }}
                  class={Styles['toolbar-btn']}
                >
                  <NIcon>
                    <CopyOutlined />
                  </NIcon>
                </NButton>
              ),
              default: () => t('project.dag.copy_name')
            }}
          ></NTooltip>
        )}
        {props.definition?.workflowDefinition?.name && (
          <NTooltip
            v-slots={{
              trigger: () => (
                <NPopover
                  placement='bottom'
                  trigger='click'
                  scrollable
                  style={{ maxWidth: '50vw', maxHeight: '70vh' }}
                >
                  {{
                    trigger: () => (
                      <NButton quaternary circle class={Styles['toolbar-btn']}>
                        <NIcon>
                          <FundViewOutlined />
                        </NIcon>
                      </NButton>
                    ),
                    header: () => (
                      <NText strong depth={1}>
                        {t('project.workflow.parameters_variables')}
                      </NText>
                    ),
                    default: () => <VariablesView onCopy={copy} />
                  }}
                </NPopover>
              ),
              default: () => t('project.dag.view_variables')
            }}
          ></NTooltip>
        )}
        <div class={Styles['toolbar-left-part']}>
          {route.name !== 'workflow-instance-detail' &&
            props.definition?.workflowDefinition?.releaseState === 'ONLINE' && (
              <NTag round size='small' type='info'>
                {t('project.dag.online')}
              </NTag>
            )}
          {route.name === 'workflow-instance-detail' && (
            <>
              <NTooltip
                v-slots={{
                  trigger: () => (
                    <NPopover placement='bottom' trigger='click'>
                      {{
                        trigger: () => (
                          <NButton
                            quaternary
                            circle
                            class={Styles['toolbar-btn']}
                          >
                            <NIcon>
                              <RightCircleOutlined />
                            </NIcon>
                          </NButton>
                        ),
                        header: () => (
                          <NText strong depth={1}>
                            {t('project.workflow.startup_parameter')}
                          </NText>
                        ),
                        default: () => (
                          <StartupParam startupParam={props.instance} />
                        )
                      }}
                    </NPopover>
                  ),
                  default: () => t('project.dag.startup_parameter')
                }}
              ></NTooltip>
            </>
          )}
        </div>
        <div class={Styles['toolbar-right-part']}>
          {/* Search node */}
          <NTooltip
            v-slots={{
              trigger: () => (
                <NButton
                  class={Styles['toolbar-right-item']}
                  strong
                  secondary
                  circle
                  type='info'
                  onClick={toggleSearchInput}
                  v-slots={{
                    icon: () => (
                      <NIcon>
                        <SearchOutlined />
                      </NIcon>
                    )
                  }}
                />
              ),
              default: () => t('project.dag.search')
            }}
          ></NTooltip>
          <div
            class={`${Styles['toolbar-right-item']} ${
              Styles['node-selector']
            } ${searchInputVisible.value ? Styles['visible'] : ''}`}
          >
            <NSelect
              size='small'
              value={searchSelectValue.value}
              options={nodesDropdown.value}
              onFocus={reQueryNodes}
              onUpdateValue={navigateTo}
              filterable
            />
          </div>
          {/* Download workflow PNG */}
          <NTooltip
            v-slots={{
              trigger: () => (
                <NButton
                  class={Styles['toolbar-right-item']}
                  strong
                  secondary
                  circle
                  type='info'
                  onClick={() => downloadPNG()}
                  v-slots={{
                    icon: () => (
                      <NIcon>
                        <DownloadOutlined />
                      </NIcon>
                    )
                  }}
                />
              ),
              default: () => t('project.dag.download_png')
            }}
          ></NTooltip>
          {/* Refresh */}
          {props.instance && (
            <NTooltip
              v-slots={{
                trigger: () => (
                  <NButton
                    class={Styles['toolbar-right-item']}
                    strong
                    secondary
                    circle
                    type='info'
                    onClick={() => {
                      context.emit('refresh')
                    }}
                    v-slots={{
                      icon: () => (
                        <NIcon>
                          <SyncOutlined />
                        </NIcon>
                      )
                    }}
                  />
                ),
                default: () => t('project.dag.refresh_dag_status')
              }}
            ></NTooltip>
          )}
          {/* Delete */}
          <NTooltip
            v-slots={{
              trigger: () => (
                <NButton
                  class={Styles['toolbar-right-item']}
                  strong
                  secondary
                  circle
                  type='info'
                  onClick={() => removeCells()}
                  v-slots={{
                    icon: () => (
                      <NIcon>
                        <DeleteOutlined />
                      </NIcon>
                    )
                  }}
                />
              ),
              default: () => t('project.dag.delete_cell')
            }}
          ></NTooltip>
          {/* Toggle fullscreen */}
          <NTooltip
            v-slots={{
              trigger: () => (
                <NButton
                  class={Styles['toolbar-right-item']}
                  strong
                  secondary
                  circle
                  type='info'
                  onClick={toggle}
                  v-slots={{
                    icon: () => (
                      <NIcon>
                        {isFullscreen.value ? (
                          <FullscreenExitOutlined />
                        ) : (
                          <FullscreenOutlined />
                        )}
                      </NIcon>
                    )
                  }}
                />
              ),
              default: () =>
                isFullscreen.value
                  ? t('project.dag.fullscreen_close')
                  : t('project.dag.fullscreen_open')
            }}
          ></NTooltip>
          {/* DAG Format */}
          <NTooltip
            v-slots={{
              trigger: () => (
                <NButton
                  class={Styles['toolbar-right-item']}
                  strong
                  secondary
                  circle
                  type='info'
                  onClick={onFormat}
                  v-slots={{
                    icon: () => (
                      <NIcon>
                        <FormatPainterOutlined />
                      </NIcon>
                    )
                  }}
                />
              ),
              default: () => t('project.dag.format')
            }}
          ></NTooltip>
          {/* Version info */}
          {!!props.definition && (
            <NTooltip
              v-slots={{
                trigger: () => (
                  <NButton
                    class={Styles['toolbar-right-item']}
                    strong
                    secondary
                    circle
                    type='info'
                    onClick={openVersionModal}
                    v-slots={{
                      icon: () => (
                        <NIcon>
                          <InfoCircleOutlined />
                        </NIcon>
                      )
                    }}
                  />
                ),
                default: () => t('project.workflow.version_info')
              }}
            ></NTooltip>
          )}
          {/* Save workflow */}
          <NButton
            class={[Styles['toolbar-right-item'], 'btn-save']}
            type='info'
            secondary
            round
            disabled={
              props.definition?.workflowDefinition?.releaseState === 'ONLINE' &&
              !props.instance
            }
            onClick={() => {
              context.emit('saveModelToggle', true)
            }}
          >
            {t('project.dag.save')}
          </NButton>
          {/* Return to previous page */}
          <NButton secondary round onClick={onClose} class='btn-close'>
            {t('project.dag.close')}
          </NButton>
        </div>
      </div>
    )
  }
})
