import { i18next } from '@operato/i18n'

export const SMALLVALUE = 10e-6

const UNIT_SYSTEMS: { [unit: string]: { [unit: string]: number | ((v: number) => number)[] } } = {
  kg: {
    mg: 1000000,
    g: 1000,
    ton: 0.001
  },
  rad: {
    degree: 180 / Math.PI
  },
  sec: {
    msec: 1000,
    min: 1 / 60,
    hr: 1 / 3600,
    day: 1 / (3600 * 24),
    year: 1 / (3600 * 24 * 365)
  },
  m: {
    mm: 1000,
    cm: 100,
    inch: 39.37008
  },
  'g/mol': {
    'kg/kmol': 1,
    'g/kmol': 1000
  },
  m2: {
    mm2: 1000000,
    cm2: 1000
  },
  m3: {
    cm3: 1000000,
    L: 1000,
    mL: 1000000
  },
  'kg/m3': {
    'g/m3': 1000,
    'g/L': 1,
    'g/cm3': 0.001,
    'kg/L': 0.001,
    'g/mL': 0.001
  },
  'm/sec': {
    'm/min': 60,
    'm/hr': 3600,
    'cm/sec': 100,
    'cm/min': 6000,
    'cm/hr': 360000
  },
  N: {
    kN: 0.001,
    kgf: 0.101971621
  },
  Pa: {
    atm: 1 / 101325,
    bar: 1 / 100000,
    'kgf/cm2': 1 / 9.80665 / 10000,
    MPa: 1 / 1000000,
    kPa: 1 / 1000,
    psi: 1 / 6894.76,
    mmH2O: 1 / 9.80665,
    mmHg: 1 / 133.32
  },
  'kg/sec': {
    'kg/min': 60,
    'kg/hr': 3600,
    'ton/hr': 3.6,
    'ton/year': (60 * 60 * 24 * 365) / 1000
  },
  'kg/m2/sec': {
    'kg/m2/min': 60,
    'kg/m2/hr': 3600
  },
  'mol/sec': {
    'kmol/sec': 1 / 1000
  },
  'mol/m2/sec': {
    'kmol/m2/sec': 1 / 1000
  },
  'Sm3/sec': {
    'Sm3/hr': 3600,
    'Sm3/min': 60,
    'SL/min': 60000,
    'SL/sec': 1000,
    'Scm3/min': 60000000,
    'Scm3/sec': 1000000
  },
  'Nm3/sec': {
    'Nm3/hr': 3600,
    'Nm3/min': 60,
    'NL/min': 60000,
    'NL/sec': 1000,
    'Ncm3/min': 60000000,
    'Ncm3/sec': 1000000
  },
  'Am3/sec': {
    'Am3/hr': 3600,
    'Am3/min': 60,
    'AL/min': 60000,
    'AL/sec': 1000,
    'Acm3/min': 60000000,
    'Acm3/sec': 1000000
  },
  J: {
    kJ: 1 / 1000,
    MJ: 1 / 1000000,
    cal: 1 / 4.184,
    kcal: 1 / 4.184 / 1000
  },
  W: {
    kW: 1 / 1000,
    MW: 1 / 1000000,
    'kcal/hr': 859.85 / 1000,
    hp: 1 / 745.7
  },
  'W/m2': {
    'kW/m2': 1 / 1000,
    'W/cm2': 1 / 10000,
    'kW/cm2': 1 / 10000000
  },
  'J/kg': {
    'kJ/kg': 1 / 1000,
    'cal/g': 1 / 4.184 / 1000,
    'cal/kg': 1 / 4.184,
    'kcal/kg': 1 / 4.184 / 1000
  },
  'J/kg/K': {
    'kJ/kg/K': 1 / 1000,
    'cal/kg/K': 1 / 4.184,
    'kcal/kg/K': 1 / 4.184 / 1000,
    'cal/g/K': 1 / 4.184 / 1000
  },
  'W/m/K': {
    'kW/m/K': 1 / 1000,
    'W/cm/K': 1 / 100,
    'kW/cm/K': 1 / 100 / 1000
  },
  'W/m2/K': {
    'kW/m2/K': 1 / 1000,
    'kcal/hr/m2/oC': 1 / 1.163
  },
  'N sec/m2': {
    'Pa sec': 1,
    'mPa sec': 1000,
    'kg/m/sec': 1,
    'g/cm/sec': 10,
    P: 10,
    cP: 1000
  },
  'm2 oC/W': {
    'm2 oC/kW': 1000
  },
  '%': {},
  ppm: {},
  K: {
    '°C': [(v: number) => v - 273.15, (v: number) => v + 273.15]
  }
}

function _toUserUnitByRate(stdValue: string | number | undefined, converterRate: number) {
  return Number(stdValue) * converterRate
}

function _toUserUnitByFunction(stdValue: string | number | undefined, converterFunctions: ((v: number) => number)[]) {
  return converterFunctions[0](Number(stdValue))
}

export function convertByUserUnit(
  stdValue: number,
  stdUnit: string | number | undefined,
  userUnit: string | number | undefined
) {
  if (!userUnit || userUnit === stdUnit) {
    return stdValue
  }

  const converterValue = UNIT_SYSTEMS[stdUnit!][userUnit]

  if (!converterValue) {
    return stdValue
  }

  if (typeof converterValue === 'number') {
    return _toUserUnitByRate(stdValue, converterValue || 1)
  } /* should be converter function array */ else {
    return _toUserUnitByFunction(stdValue, converterValue as ((v: number) => number)[])
  }
}

export function formatValueWithPrecision(inputValue: string | number, precision: number = 5): number | string {
  if (typeof inputValue === undefined || inputValue === null) {
    return '-'
  }

  let inputValueNumber = typeof inputValue === 'string' ? parseFloat(inputValue) : inputValue
  inputValueNumber = isNaN(inputValueNumber) ? 0 : inputValueNumber <= SMALLVALUE ? 0 : inputValueNumber
  return inputValueNumber.toPrecision(precision)
}

export function changeStreamTypeString(type: string): string {
  switch (type) {
    case 'fluid':
      return i18next.t('label.fluid-type')
    case 'solid':
      return i18next.t('label.solid-type')
    case 'gas':
      return i18next.t('label.gas-type')
    default:
      return i18next.t('label.wrong-type') + `(${type})`
  }
}
