import { useMemo } from 'react'
import PropTypes from 'prop-types'
import NewObjectForm from '../../common/NewObjectForm'
import ObjectInfo from '../../common/ObjectInfo'
import WizardView from '../../common/WizardView'

const DEFAULT_EXTRUDER = {
  nozzleDiameter: 0.4,
  nozzleVolume: 0,
  nozzleType: 'hardened_steel',
  minLayerHeight: 0.05,
  maxLayerHeight: 0.3,
  positionOffsetX: 0,
  positionOffsetY: 0,
  retractionLength: 0.8,
  retractionExtraLengthOnRestart: 0,
  retractionSpeed: 35,
  deretractionSpeed: 0,
  retractionTravelDistanceThreshold: 2,
  retractOnLayerChange: false,
  wipeWhileRetracting: false,
  wipeDistance: 1,
  retractAmountBeforeWipe: 70,
  retractAmountAfterWipe: 0,
  zHopOnSurfaces: 'All Surfaces',
  zHopType: 'Auto',
  zHopHeight: 0,
  zHopTravelingAngle: 0,
  zHopOnlyLiftZAbove: 0,
  zHopOnlyLiftZBelow: 0,
  materialSwitchRetractionLength: 10,
  materialSwitchExtraLengthOnRestart: 0,
  longRetractionWhenCut: false
}

const PRUSA_MK3S_PROFILE_DEFAULTS = {
  extruders: [{ ...DEFAULT_EXTRUDER }],
  printBedWidth: 250,
  printBedHeight: 210,
  originX: 0,
  originY: 0,
  bedExcludeArea: [{ x: 0, y: 0 }],
  printableHeight: 210,
  supportMultiBedTypes: false,
  bestObjectPositionX: 125,
  bestObjectPositionY: 105,
  zOffset: 0,
  preferredOrientation: 0,
  machineMaxAccelerationRetracting: { min: 2500, max: 2500 },
  machineMaxSpeedE: { min: 120, max: 120 },
  machineMaxSpeedX: { min: 200, max: 200 },
  machineMaxSpeedY: { min: 200, max: 200 },
  machinePauseGcode: 'M601',
  machineStartGcode: `M862.1 P[nozzle_diameter] ; nozzle diameter check
M115 U3.13.0 ; tell printer latest fw version
G90 ; use absolute coordinates
M83 ; extruder relative mode
M104 S[first_layer_temperature] ; set extruder temp
M140 S[first_layer_bed_temperature] ; set bed temp
M190 S[first_layer_bed_temperature] ; wait for bed temp
M109 S[first_layer_temperature] ; wait for extruder temp
G28 W ; home all without mesh bed level
G80 ; mesh bed leveling
G1 Z0.3 F720
G1 Y-3 F1000 ; go outside print area
G92 E0
G1 X60 E9 F1000 ; intro line
G1 X100 E9 F1000 ; intro line
{else}
G1 Z0.2 F720
G1 Y-3 F1000 ; go outside print area
G92 E0
G1 X60 E9 F1000 ; intro line
G1 X100 E12.5 F1000 ; intro line
{endif}
G92 E0
M221 S{if layer_height<0.075}100{else}95{endif}`,
  machineEndGcode: `{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}
G1 X0 Y200 F3600 ; park
{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}
G4 ; wait
M221 S100 ; reset flow
M900 K0 ; reset LA
M104 S0 ; turn off temperature
M140 S0 ; turn off heatbed
M107 ; turn off fan
M84 ; disable motors
; max_layer_z = [max_layer_z]`,
  layerChangeGcode: `;AFTER_LAYER_CHANGE
;[layer_z]`,
  beforeLayerChangeGcode: `;BEFORE_LAYER_CHANGE
;[layer_z]
G92 E0
`,
  printerNotes: `Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.
PRINTER_VENDOR_PRUSA3D
PRINTER_MODEL_MK3
`,
  scanFirstLayer: false,
  machineLoadFilamentTime: 17,
  machineUnloadFilamentTime: 16,
  thumbnails: [{ width: 160, height: 120 }],
  auxiliaryFan: false,
  machineMaxJunctionDeviation: { min: 0.02, max: 0 }
}

const REQUIRED_PROPERTIES = ['name', 'printer']

const DIMENSION_PROPERTIES = [
  'printBedWidth',
  'printBedHeight',
  'originX',
  'originY',
  'printableHeight',
  'supportMultiBedTypes',
  'bestObjectPositionX',
  'bestObjectPositionY',
  'zOffset',
  'preferredOrientation'
]

const EXTRUDER_STEP_PROPERTIES = ['extruders']

const MOTION_PROPERTIES = [
  'machineMaxAccelerationRetracting',
  'machineMaxSpeedE',
  'machineMaxSpeedX',
  'machineMaxSpeedY',
  'machineMaxJunctionDeviation'
]

const OPTIONAL_PROPERTIES = [
  'scanFirstLayer',
  'machineLoadFilamentTime',
  'machineUnloadFilamentTime',
  'auxiliaryFan'
]

const SUMMARY_PROPERTIES = [
  ...REQUIRED_PROPERTIES,
  ...DIMENSION_PROPERTIES,
  ...MOTION_PROPERTIES,
  ...OPTIONAL_PROPERTIES
]

const NewPrinterProfile = ({ onOk, reset, defaultValues = {} }) => {
  const mergedDefaultValues = useMemo(
    () => ({
      ...PRUSA_MK3S_PROFILE_DEFAULTS,
      ...defaultValues
    }),
    [defaultValues]
  )

  return (
    <NewObjectForm
      type='printerProfile'
      reset={reset}
      defaultValues={mergedDefaultValues}
    >
      {({ handleSubmit, submitLoading, objectData, formValid }) => {
        const steps = [
          {
            title: 'Required',
            key: 'required',
            content: (
              <ObjectInfo
                type='printerProfile'
                properties={REQUIRED_PROPERTIES}
                column={1}
                bordered={false}
                isEditing
                labelWidth='75px'
                required={true}
                objectData={objectData}
              />
            )
          },
          {
            title: 'Dimensions',
            key: 'dimensions',
            content: (
              <ObjectInfo
                type='printerProfile'
                properties={DIMENSION_PROPERTIES}
                column={1}
                bordered={false}
                isEditing
                labelWidth='190px'
                objectData={objectData}
              />
            )
          },
          {
            title: 'Extruders',
            key: 'extruders',
            content: (
              <ObjectInfo
                type='printerProfile'
                properties={EXTRUDER_STEP_PROPERTIES}
                column={1}
                bordered={false}
                isEditing
                showLabels={false}
                labelWidth='90px'
                objectData={objectData}
              />
            )
          },
          {
            title: 'Motion',
            key: 'motion',
            content: (
              <ObjectInfo
                type='printerProfile'
                properties={MOTION_PROPERTIES}
                column={1}
                bordered={false}
                isEditing
                labelWidth='185px'
                objectData={objectData}
              />
            )
          },
          {
            title: 'Optional',
            key: 'optional',
            content: (
              <ObjectInfo
                type='printerProfile'
                properties={OPTIONAL_PROPERTIES}
                column={1}
                labelWidth='170px'
                bordered={false}
                isEditing
                objectData={objectData}
              />
            )
          },
          {
            title: 'Summary',
            key: 'summary',
            content: (
              <ObjectInfo
                type='printerProfile'
                properties={SUMMARY_PROPERTIES}
                column={1}
                bordered={false}
                isEditing={false}
                labelWidth='210px'
                objectData={objectData}
              />
            )
          }
        ]

        return (
          <WizardView
            sizeBarWidth='160px'
            steps={steps}
            loading={submitLoading}
            formValid={formValid}
            title='New Printer Profile'
            submitText='Create'
            onSubmit={async () => {
              const result = await handleSubmit()
              if (result?._id) onOk(result)
            }}
          />
        )
      }}
    </NewObjectForm>
  )
}

NewPrinterProfile.propTypes = {
  onOk: PropTypes.func.isRequired,
  reset: PropTypes.bool,
  defaultValues: PropTypes.object
}

export default NewPrinterProfile
