import { createElement, lazy } from 'react'

const PrinterProfileInfo = lazy(
  () => import('../../components/Dashboard/Production/PrinterProfiles/PrinterProfileInfo')
)
import PrinterProfileIcon from '../../components/Icons/PrinterProfileIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon'
import BinIcon from '../../components/Icons/BinIcon'

const THUMBNAIL_PROPERTIES = [
  {
    name: 'width',
    label: 'Width',
    type: 'number',
    min: 0,
    step: 1,
    columnWidth: 120
  },
  {
    name: 'height',
    label: 'Height',
    type: 'number',
    min: 0,
    step: 1,
    columnWidth: 120
  }
]

const BED_EXCLUDE_AREA_PROPERTIES = [
  {
    name: 'x',
    label: 'X',
    type: 'number',
    step: 0.01,
    columnWidth: 120
  },
  {
    name: 'y',
    label: 'Y',
    type: 'number',
    step: 0.01,
    columnWidth: 120
  }
]

const EXTRUDER_PROPERTIES = [
  {
    name: 'nozzleDiameter',
    label: 'Nozzle Diameter',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.05,
    columnWidth: 150
  },
  {
    name: 'nozzleVolume',
    label: 'Nozzle Volume',
    type: 'number',
    suffix: ' mm³',
    min: 0,
    step: 0.1,
    columnWidth: 150
  },
  {
    name: 'nozzleType',
    label: 'Nozzle Type',
    type: 'text',
    columnWidth: 160
  },
  {
    name: 'minLayerHeight',
    label: 'Min Layer Height',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.01,
    columnWidth: 180
  },
  {
    name: 'maxLayerHeight',
    label: 'Max Layer Height',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.01,
    columnWidth: 180
  },
  {
    name: 'positionOffsetX',
    label: 'Extruder Offset X',
    type: 'number',
    suffix: ' mm',
    step: 0.01,
    columnWidth: 180
  },
  {
    name: 'positionOffsetY',
    label: 'Extruder Offset Y',
    type: 'number',
    suffix: ' mm',
    step: 0.01,
    columnWidth: 180
  },
  {
    name: 'retractionLength',
    label: 'Retraction Length',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 170
  },
  {
    name: 'retractionExtraLengthOnRestart',
    label: 'Extra Length on Restart',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 210
  },
  {
    name: 'retractionSpeed',
    label: 'Retraction Speed',
    type: 'number',
    suffix: ' mm/s',
    min: 0,
    step: 1,
    columnWidth: 170
  },
  {
    name: 'deretractionSpeed',
    label: 'Deretraction Speed',
    type: 'number',
    suffix: ' mm/s',
    min: 0,
    step: 1,
    columnWidth: 180
  },
  {
    name: 'retractionTravelDistanceThreshold',
    label: 'Travel Distance Threshold',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 220
  },
  {
    name: 'retractOnLayerChange',
    label: 'Retract on Layer Change',
    type: 'bool',
    columnWidth: 210
  },
  {
    name: 'wipeWhileRetracting',
    label: 'Wipe While Retracting',
    type: 'bool',
    columnWidth: 190
  },
  {
    name: 'wipeDistance',
    label: 'Wipe Distance',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 150
  },
  {
    name: 'retractAmountBeforeWipe',
    label: 'Retract Amount Before Wipe',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 230
  },
  {
    name: 'retractAmountAfterWipe',
    label: 'Retract Amount After Wipe',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 230
  },
  {
    name: 'zHopOnSurfaces',
    label: 'Z-Hop On Surfaces',
    type: 'select',
    options: [
      { label: 'All Surfaces', value: 'All Surfaces' },
      { label: 'Top Only', value: 'Top Only' },
      { label: 'Bottom Only', value: 'Bottom Only' },
      { label: 'None', value: 'None' }
    ],
    columnWidth: 170
  },
  {
    name: 'zHopType',
    label: 'Z-Hop Type',
    type: 'select',
    options: [
      { label: 'Auto', value: 'Auto' },
      { label: 'Normal', value: 'Normal' },
      { label: 'Spiral', value: 'Spiral' },
      { label: 'Slope', value: 'Slope' }
    ],
    columnWidth: 140
  },
  {
    name: 'zHopHeight',
    label: 'Z-Hop Height',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.01,
    columnWidth: 150
  },
  {
    name: 'zHopTravelingAngle',
    label: 'Traveling Angle',
    type: 'number',
    suffix: '°',
    min: 0,
    step: 1,
    columnWidth: 160
  },
  {
    name: 'zHopOnlyLiftZAbove',
    label: 'Only Lift Z Above',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.01,
    columnWidth: 170
  },
  {
    name: 'zHopOnlyLiftZBelow',
    label: 'Only Lift Z Below',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.01,
    columnWidth: 170
  },
  {
    name: 'materialSwitchRetractionLength',
    label: 'Material Switch Retraction Length',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 250
  },
  {
    name: 'materialSwitchExtraLengthOnRestart',
    label: 'Material Switch Extra Length on Restart',
    type: 'number',
    suffix: ' mm',
    min: 0,
    step: 0.1,
    columnWidth: 290
  },
  {
    name: 'longRetractionWhenCut',
    label: 'Long Retraction When Cut (beta)',
    type: 'bool',
    columnWidth: 240
  }
]

export const PrinterProfile = {
  name: 'printerProfile',
  label: 'Printer Profile',
  labelPlural: 'Printer Profiles',
  url: '/dashboard/production/printerprofiles',
  prefix: 'PPF',
  icon: PrinterProfileIcon,
  actions: [
    {
      name: 'info',
      type: 'page',
      pageName: 'info',
      label: 'Info',
      default: true,
      row: true,
      icon: InfoCircleIcon
    },
    {
      name: 'edit',
      type: 'page',
      pageName: 'info',
      label: 'Edit',
      row: true,
      icon: EditIcon,
      visible: (objectData) => {
        return !(objectData?._isEditing && objectData?._isEditing == true)
      }
    },
    {
      name: 'cancelEdit',
      label: 'Cancel Edits',
      type: 'page',
      pageName: 'info',
      icon: XMarkIcon,
      visible: (objectData) => {
        return objectData?._isEditing && objectData?._isEditing == true
      }
    },
    {
      name: 'finishEdit',
      label: 'Save Edits',
      type: 'page',
      pageName: 'info',
      icon: CheckIcon,
      visible: (objectData) => {
        return objectData?._isEditing && objectData?._isEditing == true
      }
    },
    { type: 'divider' },
    {
      name: 'delete',
      type: 'page',
      pageName: 'info',
      label: 'Delete',
      row: true,
      icon: BinIcon,
      danger: true
    }
  ],
  pages: [
    {
      name: 'info',
      content: () => createElement(PrinterProfileInfo)
    }
  ],
  columns: [
    '_reference',
    'name',
    'printer',
    'printBedWidth',
    'printBedHeight',
    'printableHeight',
    'extruders.0.nozzleDiameter',
    'extruders.0.nozzleType',
    'zOffset',
    'scanFirstLayer',
    'auxiliaryFan',
    'createdAt',
    'updatedAt'
  ],
  filters: ['_id','name','createdAt','updatedAt','_reference'],
  sorters: [
    'name',
    'printBedWidth',
    'printBedHeight',
    'printableHeight',
    'zOffset',
    'createdAt',
    'updatedAt'
  ],
  properties: [
    {
      name: '_id',
      label: 'ID',
      type: 'id',
      objectType: 'printerProfile',
      showCopy: true,
      readOnly: true,
      columnWidth: 140
    },
    {
      name: 'createdAt',
      label: 'Created At',
      type: 'dateTime',
      readOnly: true,
      columnWidth: 175
    },
    {
      name: '_reference',
      label: 'Reference',
      type: 'reference',
      objectType: 'printerProfile',
      showCopy: true,
      readOnly: true,
      columnFixed: 'left',
      columnWidth: 180
    },
    {
      name: 'updatedAt',
      label: 'Updated At',
      type: 'dateTime',
      readOnly: true,
      columnWidth: 175
    },
    {
      name: 'name',
      label: 'Name',
      type: 'text',
      required: true,
      columnFixed: 'left',
      columnWidth: 220,
      value: (objectData) => {
        if (objectData?.name == undefined) {
          return objectData?.printer?.name
        }
        return objectData?.name
      }
    },
    {
      name: 'printer',
      label: 'Printer',
      type: 'object',
      objectType: 'printer',
      required: true,
      showHyperlink: true,
      columnWidth: 220
    },
    {
      name: 'printBedWidth',
      label: 'Print Bed Width',
      type: 'number',
      suffix: ' mm',
      min: 0,
      step: 1,
      columnWidth: 170
    },
    {
      name: 'printBedHeight',
      label: 'Print Bed Height',
      type: 'number',
      suffix: ' mm',
      min: 0,
      step: 1,
      columnWidth: 170
    },
    {
      name: 'originX',
      label: 'Origin X',
      type: 'number',
      suffix: ' mm',
      step: 0.01,
      columnWidth: 150
    },
    {
      name: 'originY',
      label: 'Origin Y',
      type: 'number',
      suffix: ' mm',
      step: 0.01,
      columnWidth: 150
    },
    {
      name: 'bestObjectPositionX',
      label: 'Best Object Position X',
      type: 'number',
      suffix: ' mm',
      step: 0.01,
      columnWidth: 200
    },
    {
      name: 'bestObjectPositionY',
      label: 'Best Object Position Y',
      type: 'number',
      suffix: ' mm',
      step: 0.01,
      columnWidth: 200
    },
    {
      name: 'bedExcludeArea',
      label: 'Excluded Bed Area',
      type: 'objectChildren',
      canAddRemove: true,
      span: 2,
      columns: ['x', 'y'],
      properties: BED_EXCLUDE_AREA_PROPERTIES
    },
    {
      name: 'printableHeight',
      label: 'Printable Height',
      type: 'number',
      suffix: ' mm',
      min: 0,
      step: 1,
      columnWidth: 170
    },
    {
      name: 'supportMultiBedTypes',
      label: 'Support Multi Bed Types',
      type: 'bool',
      columnWidth: 200
    },
    {
      name: 'zOffset',
      label: 'Z Offset',
      type: 'number',
      suffix: ' mm',
      step: 0.01,
      columnWidth: 140
    },
    {
      name: 'preferredOrientation',
      label: 'Preferred Orientation',
      type: 'number',
      suffix: '°',
      min: 0,
      max: 360,
      step: 1,
      columnWidth: 190
    },
    {
      name: 'extruders.0.nozzleDiameter',
      label: 'Nozzle Diameter',
      type: 'number',
      suffix: ' mm',
      min: 0,
      step: 0.05,
      readOnly: true,
      columnWidth: 150
    },
    {
      name: 'extruders.0.nozzleType',
      label: 'Nozzle Type',
      type: 'text',
      readOnly: true,
      columnWidth: 160
    },
    {
      name: 'extruders',
      label: 'Extruders',
      type: 'objectChildren',
      canAddRemove: true,
      span: 2,
      columns: [
        'nozzleDiameter',
        'nozzleType',
        'nozzleVolume',
        'minLayerHeight',
        'maxLayerHeight',
        'positionOffsetX',
        'positionOffsetY'
      ],
      hiddenPropertyWidth: 330,
      properties: EXTRUDER_PROPERTIES
    },
    {
      name: 'machineMaxAccelerationRetracting',
      label: 'Max Retracting Accel',
      type: 'minMax',
      suffix: ' mm/s²',
      min: 0,
      step: 1,
      columnWidth: 260
    },
    {
      name: 'machineMaxSpeedE',
      label: 'Max Extruder Speed',
      type: 'minMax',
      suffix: ' mm/s',
      min: 0,
      step: 1,
      columnWidth: 220
    },
    {
      name: 'machineMaxSpeedX',
      label: 'Max X Speed',
      type: 'minMax',
      suffix: ' mm/s',
      min: 0,
      step: 1,
      columnWidth: 190
    },
    {
      name: 'machineMaxSpeedY',
      label: 'Max Y Speed',
      type: 'minMax',
      suffix: ' mm/s',
      min: 0,
      step: 1,
      columnWidth: 190
    },
    {
      name: 'machinePauseGcode',
      label: 'Pause G-code',
      type: 'codeBlock',
      language: 'gcode',
      height: '180px',
      span: 2
    },
    {
      name: 'machineStartGcode',
      label: 'Start G-code',
      type: 'codeBlock',
      language: 'gcode',
      height: '240px',
      span: 2
    },
    {
      name: 'machineEndGcode',
      label: 'End G-code',
      type: 'codeBlock',
      language: 'gcode',
      height: '240px',
      span: 2
    },
    {
      name: 'layerChangeGcode',
      label: 'Layer Change G-code',
      type: 'codeBlock',
      language: 'gcode',
      height: '180px',
      span: 2
    },
    {
      name: 'beforeLayerChangeGcode',
      label: 'Before Layer Change G-code',
      type: 'codeBlock',
      language: 'gcode',
      height: '180px',
      span: 2
    },
    {
      name: 'machineLoadFilamentTime',
      label: 'Filament Load Time',
      type: 'number',
      suffix: ' s',
      min: 0,
      step: 0.1,
      columnWidth: 180
    },
    {
      name: 'scanFirstLayer',
      label: 'Scan First Layer',
      type: 'bool',
      columnWidth: 150
    },
    {
      name: 'machineUnloadFilamentTime',
      label: 'Filament Unload Time',
      type: 'number',
      suffix: ' s',
      min: 0,
      step: 0.1,
      columnWidth: 190
    },
    {
      name: 'thumbnails',
      label: 'Thumbnail Sizes',
      type: 'objectChildren',
      canAddRemove: true,
      span: 2,
      columns: ['width', 'height'],
      properties: THUMBNAIL_PROPERTIES
    },
    {
      name: 'auxiliaryFan',
      label: 'Auxiliary Fan',
      type: 'bool',
      columnWidth: 140
    },
    {
      name: 'printerNotes',
      label: 'Printer Notes',
      type: 'markdown',
      span: 2
    },
    {
      name: 'machineMaxJunctionDeviation',
      label: 'Max Junction Deviation',
      type: 'minMax',
      suffix: ' mm',
      min: 0,
      step: 0.01,
      columnWidth: 240
    }
  ]
}
