import { useState, useContext, useEffect } from 'react'
import { Form, Flex, Alert } from 'antd'
import PropTypes from 'prop-types'

import ObjectSelect from '../../common/ObjectSelect'
import PrinterTemperaturePanel from '../../common/PrinterTemperaturePanel'
import WizardView from '../../common/WizardView'
import { ApiServerContext } from '../../context/ApiServerContext'

import { LoadingOutlined } from '@ant-design/icons'

const UnloadFilamentStock = ({ onOk, reset, printer = null }) => {
  const { connected, subscribeToObjectEvent, sendObjectAction } =
    useContext(ApiServerContext)
  UnloadFilamentStock.propTypes = {
    onOk: PropTypes.func.isRequired,
    reset: PropTypes.bool.isRequired,
    printer: PropTypes.object
  }

  const initialUnloadFilamentStockForm = {
    printer: printer
  }

  const [unloadFilamentStockLoading, setUnloadFilamentStockLoading] =
    useState(false)
  const [formValid, setFormValid] = useState(false)
  const [currentTemperature, setCurrentTemperature] = useState(-1)
  const [targetTemperature, setTargetTemperature] = useState(0)
  const [filamentSensorDetected, setFilamentSensorDetected] = useState(true)
  const [unloadFilamentStockForm] = Form.useForm()
  const [unloadFilamentStockFormValues, setUnloadFilamentStockFormValues] =
    useState(initialUnloadFilamentStockForm)

  useEffect(() => {
    if (printer?._id && connected) {
      const temperatureEventUnsubscribe = subscribeToObjectEvent(
        printer._id,
        'printer',
        'temperature',
        (event) => {
          if (event.data?.extruder?.current) {
            setCurrentTemperature(event.data.extruder.current)
          }
          if (event.data?.extruder?.target) {
            setTargetTemperature(event.data.extruder.target)
          }
        }
      )
      const filamentStockEventUnsubscribe = subscribeToObjectEvent(
        printer._id,
        'printer',
        'filamentSensor',
        (event) => {
          setFilamentSensorDetected(event.data.detected)
        }
      )
      return () => {
        if (temperatureEventUnsubscribe) temperatureEventUnsubscribe()
        if (filamentStockEventUnsubscribe) filamentStockEventUnsubscribe()
      }
    }
  }, [printer?._id, connected, subscribeToObjectEvent])

  useEffect(() => {
    if (reset) {
      unloadFilamentStockForm.resetFields()
    }
  }, [reset, unloadFilamentStockForm])

  useEffect(() => {
    unloadFilamentStockForm
      .validateFields({
        validateOnly: true
      })
      .then(() => {
        // Only enable next if we have a printer selected, we're not loading, and we've reached target temperature
        setFormValid(
          Boolean(unloadFilamentStockFormValues.printer) &&
            !unloadFilamentStockLoading &&
            currentTemperature + 1 > targetTemperature &&
            targetTemperature != 0
        )
      })
      .catch(() => setFormValid(false))
  }, [
    unloadFilamentStockForm,
    unloadFilamentStockFormValues,
    unloadFilamentStockLoading,
    currentTemperature,
    targetTemperature
  ])

  const handleUnloadFilamentStock = async () => {
    setUnloadFilamentStockLoading(true)
    // Send G-code to retract the filament
    await sendObjectAction(
      unloadFilamentStockFormValues.printer._id,
      'printer',
      {
        type: 'unloadFilamentStock'
      }
    )
    //setUnloadFilamentStockLoading(false)
  }

  useEffect(() => {
    if (unloadFilamentStockLoading == true && filamentSensorDetected == false) {
      setUnloadFilamentStockLoading(false)
      onOk()
    }
  }, [unloadFilamentStockLoading, filamentSensorDetected, onOk])

  const steps = [
    {
      title: 'Preheat',
      key: 'preHeat',
      content: (
        <Flex vertical gap={'middle'} style={{ paddingBottom: 16 }}>
          <Form.Item
            label='Printer'
            name='printer'
            style={{ margin: 0 }}
            rules={[
              {
                required: true,
                message: 'Please select a printer'
              }
            ]}
          >
            <ObjectSelect type='printer' checkable={false} />
          </Form.Item>

          {unloadFilamentStockLoading == false ? (
            <>
              {targetTemperature == 0 ? (
                <Alert
                  message={'Heat the extruder to start unloading filament.'}
                  type='info'
                  showIcon
                />
              ) : null}

              {targetTemperature > 0 &&
              currentTemperature < targetTemperature ? (
                <Alert
                  message={'Heating extruder...'}
                  type='error'
                  showIcon
                  icon={<LoadingOutlined />}
                />
              ) : null}

              {targetTemperature > 0 &&
              currentTemperature + 1 > targetTemperature &&
              filamentSensorDetected ? (
                <Alert
                  message={'Ready to unload filament stock.'}
                  type='success'
                  showIcon
                />
              ) : null}
            </>
          ) : (
            <Alert
              message={'Unloading filament stock...'}
              type='info'
              showIcon
              icon={<LoadingOutlined />}
            />
          )}

          {unloadFilamentStockFormValues.printer?._id ? (
            <PrinterTemperaturePanel
              showBed={false}
              showMoreInfo={false}
              id={unloadFilamentStockFormValues.printer._id}
              offline={!connected}
            />
          ) : null}
        </Flex>
      )
    }
  ]

  return (
    <Form
      name='unloadFilamentStock'
      autoComplete='off'
      form={unloadFilamentStockForm}
      onFinish={handleUnloadFilamentStock}
      onValuesChange={(changedValues) =>
        setUnloadFilamentStockFormValues((prevValues) => ({
          ...prevValues,
          ...changedValues
        }))
      }
      initialValues={initialUnloadFilamentStockForm}
    >
      <WizardView
        title='Unload Filament Stock'
        steps={steps}
        onSubmit={() => unloadFilamentStockForm.submit()}
        formValid={formValid}
        loading={unloadFilamentStockLoading}
        submitText={unloadFilamentStockLoading ? 'Unloading...' : 'Unload'}
      />
    </Form>
  )
}

export default UnloadFilamentStock
