import { Box, Button, Checkbox, FormControlLabel, Grid2, MenuItem, Radio, RadioGroup, TextField, Tooltip, Typography } from "@mui/material";
import { Component } from "models";
import { getAddressTypes, getFriendlyName, GetSecondaryComponents, getSubtypes, Subtype } from "pbHelpers/ComponentType";
import { ComponentAvailabilityMap, DevicePositions } from "pbHelpers/DeviceAvailability";
import { GetProductAvailability } from "products/DeviceProduct";
import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/quack";
import React, { useEffect, useState } from "react";

interface Props {
  addressData: quack.AddressData
  deviceProduct: pond.DeviceProduct
  componentSelectionCallback: (component: Component[], checked: boolean) => void
  availablePositions: DevicePositions
  sensorNum?: number
}

export default function ScannedI2C(props: Props){
  const {addressData, deviceProduct, componentSelectionCallback, availablePositions, sensorNum} = props
  const [types, setTypes] = useState<quack.ComponentType[]>([])
  const [subtypeOptions, setSubtypeOptions] = useState<Array<Subtype>>([])
  const [selectedPrimaryType, setSelectedPrimaryType] = useState<quack.ComponentType>(quack.ComponentType.COMPONENT_TYPE_INVALID)
  const [selectedPrimarySubtype, setSelectedPrimarySubtype] = useState(0)
  const [added, setAdded] = useState(false)
  const [addressInUse, setAddressInUse] = useState(false)

  useEffect(()=>{
    let types: quack.ComponentType[] = []
    //find what component types use that address, this is different than the available positions passed in
    //this is meant to get all possibilities according to product type and the given address, availablePositions is the restriction of what is available
    let productAvailability = GetProductAvailability(deviceProduct)
    if(productAvailability){
      let i2cMap = productAvailability.get(quack.AddressType.ADDRESS_TYPE_I2C)
      if(i2cMap){
        i2cMap.forEach((val, key) => {
          let addresses = val as number[] ?? []
          if(addresses.length > 0 && addresses.includes(addressData.address)){
            types.push(key)
          }
        })
      }
    }
    //this if can be taken out if we dont want to select the first component type by default
    if(types.length > 0) {
      setSelectedPrimaryType(types[0])
      buildSubtypeOptions(types[0])
      checkAddressAvailable(types[0])
    }
    setTypes(types)
  },[addressData, deviceProduct])

  const buildSubtypeOptions = (compType: quack.ComponentType) => {
    let subtypes = getSubtypes(compType)
    let validSub: Subtype[] = []
    //have to exclude subtypes that are not I2C
    subtypes.forEach((sub,i) => {
      let addrTypes = getAddressTypes(compType, sub.key)
      if (addrTypes.includes(quack.AddressType.ADDRESS_TYPE_I2C)){
        validSub.push(sub)
      }
    })
    //set the selected on to be the first in the valid selection
    if(validSub.length > 0){
      setSelectedPrimarySubtype(validSub[0].key)
    }
    setSubtypeOptions(validSub)
  }

  const checkAddressAvailable = (compType: quack.ComponentType) => {
    let i2cMap = availablePositions as ComponentAvailabilityMap
    let compAddresses = i2cMap.get(compType) ?? []
    if (!compAddresses.includes(addressData.address)){
      setAddressInUse(true)
    }else{
      setAddressInUse(false)
    }
  }



  const componentSelected = (event: React.ChangeEvent<HTMLInputElement>, checked: boolean) => {
    let toAdd: Component[] = []
    setAdded(checked)
    //build a component with given information and defaults for the rest
    let primaryComponent = Component.create()
    primaryComponent.settings.type = selectedPrimaryType
    primaryComponent.settings.subtype = selectedPrimarySubtype
    primaryComponent.settings.addressType = quack.AddressType.ADDRESS_TYPE_I2C
    primaryComponent.settings.address = addressData.address
    primaryComponent.settings.expansionLine = addressData.expansionLine
    primaryComponent.settings.muxLine = addressData.muxLine

    primaryComponent.settings.name = getFriendlyName(selectedPrimaryType, selectedPrimarySubtype)
    toAdd.push(primaryComponent)

    GetSecondaryComponents(selectedPrimaryType, selectedPrimarySubtype).forEach(secComp => {
      let component = Component.create()
      component.settings = secComp
      toAdd.push(component)
    })

    //return the component and the checked status to the parent
    componentSelectionCallback(toAdd, checked)
  }


  return (
    <Box sx={{marginY: 1}}>
      {sensorNum && <Typography>Sensor {sensorNum}</Typography>}
      {types.length > 0 ?
      <React.Fragment>
        <Grid2 container direction="row" alignItems="center" justifyContent="space-between">
          <Grid2 size={3}>
            <RadioGroup
              value={selectedPrimaryType}
              onChange={(_, value) => {
                let v = parseInt(value)
                if (!isNaN(v)){
                  buildSubtypeOptions(v)
                  checkAddressAvailable(v)
                }
                }}>
              {types.map((type, i) => {
                return (
                  <FormControlLabel
                    disabled={added}
                    key={i}
                    value={type}
                    control={<Radio />}
                    label={getFriendlyName(type)}
                  />
                )
              })}
            </RadioGroup>
          </Grid2>
          <Grid2 size={8}>
            {subtypeOptions.length > 0 &&
              <TextField
              disabled={added}
              value={selectedPrimarySubtype}
              fullWidth
              onChange={(event)=>{
                let val = +event.target.value
                setSelectedPrimarySubtype(val)
              }}
              select>
                {subtypeOptions.map(s => (
                  <MenuItem value={s.key}>{s.friendlyName}</MenuItem>
                ))}
              </TextField>
            }
          </Grid2>
          <Grid2 size={1}>
            <Tooltip 
              title="Add to list to be added to the device"
              children={
                <Checkbox 
                  value={added}
                  onChange={componentSelected}
                  disabled={addressInUse}
                />
              }
            />
            
          </Grid2>
        </Grid2>
      </React.Fragment>
      :
      <Typography>Sensor Not Supported By Product</Typography>
      }
    </Box>
  )
}