Source: app/util/convertWeightValue/convertWeightValue.js

import React, { Fragment } from 'react';
import Configuration from '../../config/Configuration';
import { kilogramsToPounds, poundsToStones } from '../conversionUtils';
import getFraction from '../getFraction';

import MeasureUnit from '../../data/enum/MeasureUnit';

export const ReturnType = {
  WEIGHT_ARRAY: 'weightArray',
  COMPLETE_STRING: 'completeString',
};

/**
 * Takes a kilogram weight and returns as constituent units, with labels.
 * @param {weight (kilos), precision (decimal points), imperialWeightUseStones, customFormat}
 * @param asCompleteString, return as JSX (default) or a string
 * @example
 * {weight: 115, weightUnit: MeasureUnit.IMPERIAL, imperialWeightUseStones: true} returns
 * 18st 1lb ½
 */

const convertWeightValue = (
  {
    weight,
    precision = 2,
    weightUnit,
    imperialWeightUseStones = Configuration.imperialWeightUseStones,
    customFormat,
    returnFormat = [ReturnType.WEIGHT_ARRAY],
  },
  getMessage,
) => {
  const weightArray = [];
  const formatFraction = (displayPounds, poundFraction) =>
    customFormat
      ? {
          label: 'general.measureUnit.weight.pounds.abbreviation',
          value: (
            <Fragment>
              {displayPounds !== 0 && <span data-testid="pounds">{`${displayPounds}`}</span>}
              <span data-testid="pound-fraction">{poundFraction}</span>
            </Fragment>
          ),
        }
      : {
          label: 'general.measureUnit.weight.pounds.abbreviation',
          value: `${displayPounds === 0 ? '' : displayPounds} ${poundFraction}`,
        };

  if (weight == null) {
    return weightArray;
  }

  if (weightUnit === MeasureUnit.METRIC) {
    weightArray.push({
      label: 'general.measureUnit.weight.kilogram.abbreviation',
      value: +weight.toFixed(precision),
    });
  }

  if (weightUnit === MeasureUnit.IMPERIAL) {
    if (imperialWeightUseStones) {
      const [stones, poundsRemainder] = poundsToStones(kilogramsToPounds(weight));
      const [pounds, poundFraction] = getFraction(poundsRemainder, 2);

      let displayStones = stones;
      let displayPounds = pounds;

      if (pounds === 14) {
        displayStones = stones + 1;
        displayPounds = 0;
      }

      if (displayStones !== 0 || (displayStones === 0 && displayPounds === 7)) {
        if (displayPounds === 7) {
          displayPounds = 0;
          weightArray.push({
            label: 'general.measureUnit.weight.stone.labelAbbreviation',
            value: displayStones > 0 ? `${displayStones} ½` : `½`,
            withFraction: true,
          });
        } else {
          weightArray.push({
            label: 'general.measureUnit.weight.stone.labelAbbreviation',
            value: `${displayStones}`,
          });
        }
      }
      if (displayPounds || poundFraction) {
        weightArray.push(formatFraction(displayPounds, poundFraction));
      }
      if (weight === 0) {
        weightArray.push({
          label: 'general.measureUnit.weight.pounds.abbreviation',
          value: 0,
        });
      }
    } else {
      weightArray.push({
        label: 'general.measureUnit.weight.pounds.abbreviation',
        value: +kilogramsToPounds(weight).toFixed(precision),
      });
    }
  }

  if (
    returnFormat.length === 1 &&
    returnFormat.every(element => element === ReturnType.WEIGHT_ARRAY)
  ) {
    return weightArray;
  }

  const deconstructedSections = weightArray.map(item => `${item.value} ${getMessage(item.label)} `);
  const completeString = `${deconstructedSections[0]}${deconstructedSections[1] || ''}`.trim();

  if (
    returnFormat.length === 1 &&
    returnFormat.every(element => element === ReturnType.COMPLETE_STRING)
  ) {
    return completeString;
  }

  return { completeString, weightArray };
};

export default convertWeightValue;