import { useState, useEffect } from 'react'
import { Select } from 'antd'

import { MonitoringColumn } from './MonitoringColumn'
import { CustomColumn } from './CustomColumn'
import ActiveMessagesOnline from './ActiveMessagesOnline'
import { ModeDisplay } from './ModeDisplay'
import { UserOfWell } from './UserOfWells'

import LoaderPortal from '../../components/LoaderPortal'
import { Grid, GridItem, Flex } from '../../components/Grid'
import { Subscribe } from '../../services/signalr'
import {
  DrillFlowChartService,
  TelemetryDataSaubService,
  TelemetryDataSpinService,
  WellService
} from '../../services/api'
import { makeDateSorter } from '../../components/Table'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { PeriodPicker, defaultPeriod } from '../../components/PeriodPicker'

import MomentStabPicEnabled from '../../images/DempherOn.png'
import MomentStabPicDisabled from '../../images/DempherOff.png'
import SpinPicEnabled from '../../images/SpinEnabled.png'
import SpinPicDisabled from '../../images/SpinDisabled.png'

import '../../styles/message.css'

const { Option } = Select

const dash = [7, 3]

const blockHeightGroup = [
  {
    label: 'Высота блока',
    units: 'м',
    xAccessorName: 'blockPosition',
    yAccessorName: 'date',
    color: '#333',
    showLabels: true
  }, {
    label: 'wellDepth',
    units: 'м',
    xAccessorName: 'wellDepth',
    yAccessorName: 'date',
    color: '#333',
    showLine: false,
    xConstValue: 30,
    dash
  }, {
    label: 'Расход',
    units: 'л/c',
    xAccessorName: 'flow',
    yAccessorName: 'date',
    color: '#077',
    showLabels: true,
    showLine: true
  }, {
    label: 'flowLimits',
    units: 'л/с',
    xAccessorName: 'flow',
    yAccessorName: 'date',
    color: 'rgba(0,119,119,.1)',
    isShape: true
  }
]

const blockSpeedGroup = [
  {
    label: 'Скорость блока',
    units: 'м/ч',
    xAccessorName: 'blockSpeed',
    yAccessorName: 'date',
    color: '#0a0',
    showLabels: true,
  }, {
    label: 'blockSpeedSp',
    units: 'м/ч',
    xAccessorName: 'blockSpeedSp',
    yAccessorName: 'date',
    color: '#0a0',
    footer: 'SP',
    dash
  }
]

const pressureGroup = [
  {
    label: 'Давление',
    units: 'атм',
    xAccessorName: 'pressure',
    yAccessorName: 'date',
    color: '#c00',
    showLabels: true
  }, {
    label: 'pressureSp',
    units: 'атм',
    xAccessorName: 'pressureSp',
    yAccessorName: 'date',
    color: '#c00',
    footer: 'SP',
    dash
  }, {
    label: 'pressureIdle',
    units: 'атм',
    xAccessorName: 'pressureIdle',
    yAccessorName: 'date',
    color: '#c00',
    footer: 'IDLE',
    dash
  }, {
    label: 'pressureDeltaLimitMax',
    units: 'атм',
    xAccessorName: 'pressureDeltaLimitMax',
    yAccessorName: 'date',
    color: '#c00',
    footer: true,
    dash
  }, {
    label: 'pressureLimits',
    units: 'атм',
    xAccessorName: 'pressure',
    yAccessorName: 'date',
    color: 'rgba(204,0,0,.1)',
    isShape: true
  }
]

const axialLoadGroup = [
  {
    label: 'Осевая нагрузка',
    units: 'т',
    xAccessorName: 'axialLoad',
    yAccessorName: 'date',
    color: '#00a',
    showLabels: true
  }, {
    label: 'axialLoadSp',
    units: 'т',
    xAccessorName: 'axialLoadSp',
    yAccessorName: 'date',
    color: '#00a',
    footer: 'SP',
    dash
  }, {
    label: 'axialLoadLimitMax',
    units: 'т',
    xAccessorName: 'axialLoadLimitMax',
    yAccessorName: 'date',
    color: '#00a',
    footer: true,
    dash
  }, {
    label: 'axialLoadLimits',
    units: 'т',
    xAccessorName: 'axialLoad',
    yAccessorName: 'date',
    color: 'rgba(0,0,170,.1)',
    isShape: true
  }
]

const hookWeightGroup = [
  {
    label: 'Вес на крюке',
    units: 'т',
    xAccessorName: 'hookWeight',
    yAccessorName: 'date',
    color: '#0aa',
    showLabels: true
  }, {
    label: 'hookWeightIdle',
    units: 'т',
    xAccessorName: 'hookWeightIdle',
    yAccessorName: 'date',
    color: '#0aa',
    footer: 'IDLE',
    dash
  }, {
    label: 'hookWeightLimitMin',
    units: 'т',
    xAccessorName: 'hookWeightLimitMin',
    yAccessorName: 'date',
    color: '#0aa',
    footer: true,
    dash
  }, {
    label: 'hookWeightLimitMax',
    units: 'т',
    xAccessorName: 'hookWeightLimitMax',
    yAccessorName: 'date',
    color: '#0aa',
    footer: true,
    dash
  }, {
    label: 'Обороты ротора',
    units: 'об/мин',
    xAccessorName: 'rotorSpeed',
    yAccessorName: 'date',
    color: '#aa0',
    showLabels: true
  }, {
    label: 'rotorSpeedLimits',
    units: 'об/мин',
    xAccessorName: 'rotorSpeed',
    yAccessorName: 'date',
    color: 'rgba(170,170,0,.1)',
    isShape: true
  }
]

const rotorTorqueGroup = [
  {
    label: 'Момент на роторе',
    units: 'кН·м',
    xAccessorName: 'rotorTorque',
    yAccessorName: 'date',
    color: '#a0a',
    showLabels: true
  }, {
    label: 'План. Момент на роторе',
    units: 'кН·м',
    xAccessorName: 'rotorTorqueSp',
    yAccessorName: 'date',
    color: '#a0a',
    footer: 'SP',
    dash
  }, {
    label: 'Момент на роторе х.х.',
    units: 'кН·м',
    xAccessorName: 'rotorTorqueIdle',
    yAccessorName: 'date',
    color: '#a0a',
    footer: 'IDLE',
    dash
  }, {
    label: 'rotorTorqueLimitMax',
    units: 'кН·м',
    xAccessorName: 'rotorTorqueLimitMax',
    yAccessorName: 'date',
    color: '#a0a',
    footer: true,
    dash
  }, {
    label: 'rotorTorqueLimits',
    units: 'кН·м',
    xAccessorName: 'rotorTorque',
    yAccessorName: 'date',
    color: 'rgba(170,0,170,.1)',
    isShape: true
  }
]

export const paramsGroups = [
  blockHeightGroup,
  blockSpeedGroup,
  pressureGroup,
  axialLoadGroup,
  hookWeightGroup,
  rotorTorqueGroup
]

const getLast = (data) =>
  Array.isArray(data) ? data.slice(-1)[0] : data

const isMseEnabled = (dataSaub) => {
  const lastData = getLast(dataSaub)
  return (lastData?.mseState && 2) > 0
}

const isTorqueStabEnabled = (dataSpin) => {
  const lastData = getLast(dataSpin)
  return lastData?.state === 7
}

const isSpinEnabled = (dataSpin) => {
  const lastData = getLast(dataSpin)
  return lastData?.state > 0 && lastData?.state !== 6
}

const getIndexOfDrillingBy = (dataSaub) => {
  const order = {
    0: -1,
    1: 1, // скорость
    2: 2, // давление
    3: 3, // нагрузка
    4: 5, // момент
  }
  const idFeedRegulator = getLast(dataSaub)?.idFeedRegulator ?? 0
  return order[idFeedRegulator] ?? -1
}

export const normalizeData = (data) => data?.map(item => ({
  ...item,
  rotorSpeed: item.rotorSpeed < 1 ? 0 : item.rotorSpeed,
  rotorTorque: item.rotorTorque < 1 ? 0 : item.rotorTorque,
  blockSpeed: Math.abs(item.blockSpeed)
})) ?? []

export default function TelemetryView({ idWell }) {
  const [dataSaub, setDataSaub] = useState([])
  const [dataSpin, setDataSpin] = useState([])
  const [chartInterval, setChartInterval] = useState(defaultPeriod)
  const [wellData, setWellData] = useState({ idState: 0 })
  const [showLoader, setShowLoader] = useState(false)
  const [flowChartData, setFlowChartData] = useState([])

  const handleDataSaub = (data) => {
    if (data) {
      const dataSaub = normalizeData(data)
      dataSaub.sort(makeDateSorter('date'))
      setDataSaub(dataSaub)
    }
  }

  const handleDataSpin = (data) => {
    if (data) {
      setDataSpin(data)
    }
  }

  useEffect(() => {
    const unsubscribeSaub = Subscribe('hubs/telemetry', 'ReceiveDataSaub', `well_${idWell}`, handleDataSaub)
    const unsubscribeSpin = Subscribe('hubs/telemetry', 'ReceiveDataSpin', `well_${idWell}`, handleDataSpin)
    invokeWebApiWrapperAsync(
      async () => {
        const flowChart = await DrillFlowChartService.get(idWell)
        const dataSaub = await TelemetryDataSaubService.getData(idWell, null, chartInterval)
        const dataSpin = await TelemetryDataSpinService.getData(idWell, null, chartInterval)
        setFlowChartData(flowChart ?? [])
        handleDataSaub(dataSaub)
        handleDataSpin(dataSpin)
      },
      null,
      `Не удалось получить данные по скважине "${idWell}"`,
    )
    return () => {
      unsubscribeSaub()
      unsubscribeSpin()
    }
  }, [idWell, chartInterval])

  useEffect(() => invokeWebApiWrapperAsync(
    async () => {
      const well = await WellService.get(idWell)
      setWellData(well ?? {})
    },
    setShowLoader,
    `Не удалось загрузить данные по скважине "${idWell}"`
  ), [idWell])

  const onStatusChanged = (value) => {
    invokeWebApiWrapperAsync(
      async () => {
        const well = { ...wellData, idState: value }
        await WellService.updateWell(idWell, well)
        setWellData(well)
      },
      setShowLoader,
      `Не удалось задать состояние скважины "${idWell}"`
    )
  }

  return (
    <LoaderPortal show={showLoader}>
      <Grid style={{ gridTemplateColumns: 'auto repeat(6, 1fr)' }}>
        <GridItem col={'1'} row={'1'} colSpan={'8'} style={{ marginBottom: '0.5rem' }}>
          <Flex>
            <ModeDisplay data={dataSaub} />
            <div style={{ marginLeft: '1rem' }}>
              Интервал:&nbsp;
              <PeriodPicker onChange={setChartInterval} />
            </div>
            <div style={{ marginLeft: '1rem' }}>
              Статус:&nbsp;
              <Select value={wellData.idState ?? 0} onChange={onStatusChanged}>
                <Option value={0} disabled>Неизвестно</Option>
                <Option value={1}>В работе</Option>
                <Option value={2}>Завершено</Option>
              </Select>
            </div>
            <span style={{ flexGrow: 20 }}>&nbsp;</span>
            <img src={isTorqueStabEnabled(dataSpin) ? MomentStabPicEnabled : MomentStabPicDisabled} style={{ marginRight: '15px' }} alt={'TorqueMaster'} />
            <img src={isSpinEnabled(dataSpin) ? SpinPicEnabled : SpinPicDisabled} style={{ marginRight: '15px' }} alt={'SpinMaster'} />
            <h2 style={{ marginBottom: 0, marginRight: '15px', fontWeight: 'bold', color: isMseEnabled(dataSaub) ? 'green' : 'lightgrey' }}>MSE</h2>
            <UserOfWell data={dataSaub} />
          </Flex>
        </GridItem>
        <GridItem col={'1'} row={'2'} rowSpan={'3'} style={{ minWidth: '260px', width: '0.142fr' }}>
          <CustomColumn data={dataSaub} />
        </GridItem>
        {paramsGroups.map((group, index) =>
          <GridItem col={2 + index} row={'2'} className={'border_small'} key={`${group.label}${index}`} style={{padding:0}}>
            <MonitoringColumn
              showLastValues
              style={{ width: '13vw' }}
              data={dataSaub}
              flowChartData={flowChartData}
              lineGroup={group}
              interval={chartInterval * 1000}
              headerHeight={'50px'}
              showBorder={getIndexOfDrillingBy(dataSaub) === index}
            />
          </GridItem>
        )}
        <GridItem col={'2'} row={'3'} colSpan={'7'}>
          <ActiveMessagesOnline idWell={idWell} />
        </GridItem>
      </Grid>
    </LoaderPortal>
  )
}