import { useRef, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { Card, Flex, Space } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
import ActionHandler from '../../common/ActionHandler'
import AuditLogIcon from '../../../Icons/AuditLogIcon'
import DocumentPrintButton from '../../common/DocumentPrintButton'
import EditButtons from '../../common/EditButtons'
import FilamentIcon from '../../../Icons/FilamentIcon'
import GCodeFileIcon from '../../../Icons/GCodeFileIcon'
import HotEndIcon from '../../../Icons/HotEndIcon'
import InfoCircleIcon from '../../../Icons/InfoCircleIcon'
import InfoCollapse from '../../common/InfoCollapse'
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder'
import ActivityIndicator from '../../common/ActivityIndicator'
import MultiMotionIcon from '../../../Icons/MultiMotionIcon'
import NoteIcon from '../../../Icons/NoteIcon'
import NotesPanel from '../../common/NotesPanel'
import ObjectActions from '../../common/ObjectActions'
import ObjectForm from '../../common/ObjectForm'
import ObjectInfo from '../../common/ObjectInfo'
import ObjectTable from '../../common/ObjectTable'
import RulerIcon from '../../../Icons/RulerIcon'
import ScrollBox from '../../common/ScrollBox'
import SettingsIcon from '../../../Icons/SettingsIcon'
import UserNotifierToggle from '../../common/UserNotifierToggle'
import ViewButton from '../../common/ViewButton'
import useCollapseState from '../../hooks/useCollapseState'
import {
  FILAMENT_PROFILE_BED_TEMPERATURE_PROPERTIES,
  FILAMENT_PROFILE_COMPATIBILITY_PROPERTIES,
  FILAMENT_PROFILE_COOLING_PROPERTIES,
  FILAMENT_PROFILE_EXHAUST_FAN_PROPERTIES,
  FILAMENT_PROFILE_FLOW_PRESSURE_PROPERTIES,
  FILAMENT_PROFILE_GCODE_PROPERTIES,
  FILAMENT_PROFILE_LOADING_PROPERTIES,
  FILAMENT_PROFILE_MATERIAL_PROPERTIES,
  FILAMENT_PROFILE_RETRACTION_PROPERTIES,
  FILAMENT_PROFILE_SHRINKAGE_DRYING_PROPERTIES,
  FILAMENT_PROFILE_SPEED_PROPERTIES,
  FILAMENT_PROFILE_TEMPERATURE_PROPERTIES,
  FILAMENT_PROFILE_WIPE_TOWER_PROPERTIES
} from '../../../../database/models/FilamentProfile'

const toVisibleProperties = (propertyNames) =>
  Object.fromEntries(propertyNames.map((name) => [name, true]))

const FilamentProfileInfo = () => {
  const location = useLocation()
  const objectFormRef = useRef(null)
  const actionHandlerRef = useRef(null)
  const filamentProfileId = new URLSearchParams(location.search).get(
    'filamentProfileId'
  )
  const [collapseState, updateCollapseState] = useCollapseState(
    'FilamentProfileInfo',
    {
      info: true,
      material: true,
      flowPressure: true,
      temperature: true,
      bedTemperature: true,
      speed: true,
      cooling: true,
      exhaustFan: true,
      retraction: true,
      loading: true,
      wipeTower: true,
      gCodeSettings: true,
      compatibility: true,
      shrinkageDrying: true,
      notes: true,
      auditLogs: false
    }
  )
  const [objectFormState, setObjectFormState] = useState({
    isEditing: false,
    editLoading: false,
    formValid: false,
    lock: null,
    loading: false,
    objectData: {}
  })

  const actions = {
    edit: () => {
      objectFormRef.current?.startEditing?.()
      return false
    },
    cancelEdit: () => {
      objectFormRef.current?.cancelEditing?.()
      return true
    },
    finishEdit: () => {
      objectFormRef.current?.handleUpdate?.()
      return true
    },
    delete: () => {
      objectFormRef.current?.handleDelete?.()
      return true
    }
  }

  return (
    <Flex
      gap='large'
      vertical='true'
      style={{ maxHeight: '100%', minHeight: 0 }}
    >
      <Flex justify='space-between'>
        <Space size='small'>
          <Space size='small'>
            <ObjectActions
              type='filamentProfile'
              id={filamentProfileId}
              disabled={objectFormState.loading}
              objectData={objectFormState.objectData}
            />
            <ViewButton
              disabled={objectFormState.loading}
              items={[
                { key: 'info', label: 'Filament Profile Information' },
                { key: 'material', label: 'Material' },
                { key: 'flowPressure', label: 'Flow & Pressure' },
                { key: 'temperature', label: 'Temperature' },
                { key: 'bedTemperature', label: 'Bed Temperatures' },
                { key: 'speed', label: 'Speed' },
                { key: 'cooling', label: 'Part Cooling Fan' },
                { key: 'exhaustFan', label: 'Exhaust Fan' },
                { key: 'retraction', label: 'Retraction Overrides' },
                { key: 'loading', label: 'Loading & Multi-tool' },
                { key: 'wipeTower', label: 'Wipe Tower & Flushing' },
                { key: 'gCodeSettings', label: 'G-Code Settings' },
                { key: 'compatibility', label: 'Compatibility' },
                { key: 'shrinkageDrying', label: 'Shrinkage & Drying' },
                { key: 'notes', label: 'Notes' },
                { key: 'auditLogs', label: 'Audit Logs' }
              ]}
              visibleState={collapseState}
              updateVisibleState={updateCollapseState}
            />
            <UserNotifierToggle
              type='filamentProfile'
              objectData={objectFormState.objectData}
              disabled={objectFormState.loading}
            />
            <DocumentPrintButton
              type='filamentProfile'
              objectData={objectFormState.objectData}
              disabled={objectFormState.loading}
            />
          </Space>
          <ActivityIndicator
            activities={objectFormState.activities}
            showStartingDivider={true}
          />
        </Space>
        <EditButtons
          isEditing={objectFormState.isEditing}
          handleUpdate={() => actionHandlerRef.current.callAction('finishEdit')}
          cancelEditing={() =>
            actionHandlerRef.current.callAction('cancelEdit')
          }
          startEditing={() => actionHandlerRef.current.callAction('edit')}
          editLoading={objectFormState.editLoading}
          formValid={objectFormState.formValid}
          disabled={objectFormState.beingEditedByOther || objectFormState.loading}
          loading={objectFormState.editLoading}
        />
      </Flex>

      <ScrollBox>
        <Flex vertical gap='large'>
          <ActionHandler
            actions={actions}
            loading={objectFormState.loading}
            ref={actionHandlerRef}
          >
            <ObjectForm
              id={filamentProfileId}
              type='filamentProfile'
              ref={objectFormRef}
              onStateChange={(state) =>
                setObjectFormState((current) => ({ ...current, ...state }))
              }
            >
              {({ loading, isEditing, objectData }) => (
                <Flex vertical gap='large'>
                  <InfoCollapse
                    title='Filament Profile Information'
                    icon={<InfoCircleIcon />}
                    active={collapseState.info}
                    onToggle={(expanded) =>
                      updateCollapseState('info', expanded)
                    }
                    collapseKey='info'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='140px'
                      visibleProperties={{
                        _id: true,
                        name: true,
                        _reference: true,
                        filamentType: true,
                        filament: true,
                        createdAt: true,
                        updatedAt: true
                      }}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Material'
                    icon={<FilamentIcon />}
                    active={collapseState.material}
                    onToggle={(expanded) =>
                      updateCollapseState('material', expanded)
                    }
                    collapseKey='material'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='220px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_MATERIAL_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Flow & Pressure'
                    icon={<SettingsIcon />}
                    active={collapseState.flowPressure}
                    onToggle={(expanded) =>
                      updateCollapseState('flowPressure', expanded)
                    }
                    collapseKey='flowPressure'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='325px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_FLOW_PRESSURE_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Temperature'
                    icon={<HotEndIcon />}
                    active={collapseState.temperature}
                    onToggle={(expanded) =>
                      updateCollapseState('temperature', expanded)
                    }
                    collapseKey='temperature'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='280px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_TEMPERATURE_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Bed Temperatures'
                    icon={<RulerIcon />}
                    active={collapseState.bedTemperature}
                    onToggle={(expanded) =>
                      updateCollapseState('bedTemperature', expanded)
                    }
                    collapseKey='bedTemperature'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='280px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_BED_TEMPERATURE_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Speed'
                    icon={<MultiMotionIcon />}
                    active={collapseState.speed}
                    onToggle={(expanded) =>
                      updateCollapseState('speed', expanded)
                    }
                    collapseKey='speed'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='265px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_SPEED_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Part Cooling Fan'
                    icon={<SettingsIcon />}
                    active={collapseState.cooling}
                    onToggle={(expanded) =>
                      updateCollapseState('cooling', expanded)
                    }
                    collapseKey='cooling'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='350px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_COOLING_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Exhaust Fan'
                    icon={<SettingsIcon />}
                    active={collapseState.exhaustFan}
                    onToggle={(expanded) =>
                      updateCollapseState('exhaustFan', expanded)
                    }
                    collapseKey='exhaustFan'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='285px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_EXHAUST_FAN_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Retraction Overrides'
                    icon={<SettingsIcon />}
                    active={collapseState.retraction}
                    onToggle={(expanded) =>
                      updateCollapseState('retraction', expanded)
                    }
                    collapseKey='retraction'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='250px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_RETRACTION_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Loading & Multi-tool'
                    icon={<FilamentIcon />}
                    active={collapseState.loading}
                    onToggle={(expanded) =>
                      updateCollapseState('loading', expanded)
                    }
                    collapseKey='loading'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='220px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_LOADING_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Wipe Tower & Flushing'
                    icon={<SettingsIcon />}
                    active={collapseState.wipeTower}
                    onToggle={(expanded) =>
                      updateCollapseState('wipeTower', expanded)
                    }
                    collapseKey='wipeTower'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='330px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_WIPE_TOWER_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='G-Code Settings'
                    icon={<GCodeFileIcon />}
                    active={collapseState.gCodeSettings}
                    onToggle={(expanded) =>
                      updateCollapseState('gCodeSettings', expanded)
                    }
                    collapseKey='gCodeSettings'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='270px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_GCODE_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Compatibility'
                    icon={<SettingsIcon />}
                    active={collapseState.compatibility}
                    onToggle={(expanded) =>
                      updateCollapseState('compatibility', expanded)
                    }
                    collapseKey='compatibility'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='270px'
                      visibleProperties={toVisibleProperties(
                        FILAMENT_PROFILE_COMPATIBILITY_PROPERTIES
                      )}
                    />
                  </InfoCollapse>
                  <InfoCollapse
                    title='Shrinkage & Drying'
                    icon={<SettingsIcon />}
                    active={collapseState.shrinkageDrying}
                    onToggle={(expanded) =>
                      updateCollapseState('shrinkageDrying', expanded)
                    }
                    collapseKey='shrinkageDrying'
                  >
                    <ObjectInfo
                      loading={loading}
                      indicator={<LoadingOutlined />}
                      isEditing={isEditing}
                      type='filamentProfile'
                      objectData={objectData}
                      labelWidth='340px'
                      visibleProperties={{
                        ...toVisibleProperties(
                          FILAMENT_PROFILE_SHRINKAGE_DRYING_PROPERTIES
                        ),
                        filamentNotes: true
                      }}
                    />
                  </InfoCollapse>
                </Flex>
              )}
            </ObjectForm>
          </ActionHandler>

          <InfoCollapse
            title='Notes'
            icon={<NoteIcon />}
            active={collapseState.notes}
            onToggle={(expanded) => updateCollapseState('notes', expanded)}
            collapseKey='notes'
          >
            <Card>
              <NotesPanel _id={filamentProfileId} type='filamentProfile' />
            </Card>
          </InfoCollapse>

          <InfoCollapse
            title='Audit Logs'
            icon={<AuditLogIcon />}
            active={collapseState.auditLogs}
            onToggle={(expanded) => updateCollapseState('auditLogs', expanded)}
            collapseKey='auditLogs'
          >
            {objectFormState.loading ? (
              <InfoCollapsePlaceholder />
            ) : (
              <ObjectTable
                type='auditLog'
                masterFilter={{ 'parent._id': filamentProfileId }}
                visibleColumns={{ _id: false, 'parent._id': false }}
              />
            )}
          </InfoCollapse>
        </Flex>
      </ScrollBox>
    </Flex>
  )
}

export default FilamentProfileInfo
