"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.MacroSelectable = void 0;

var _preact = require("preact");

var _classnames = _interopRequireDefault(require("classnames"));

var _sinks = require("sinks");

var _button = require("../button");

var _object = require("../utils/object");

var _vitalTypes = require("../utils/vital-types");

var _airwayTypes = require("../utils/airway-types");

var _macro = require("../utils/macro");

var _inputs = require("../inputs");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

class EditableText extends _preact.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
    this.blur = this.blur.bind(this);
    this.state = {
      editing: false
    };
  }

  blur() {
    this.setState({
      editing: false
    });
  }

  focus() {
    this.setState({
      editing: true
    });
  }

  render() {
    const {
      matchType,
      value,
      path,
      onChange
    } = this.props;
    const {
      editing
    } = this.state;
    const className = (0, _classnames.default)(_inputs.inputOutlineClasses, 'w-100 transition-bg', editing && 'bg-white', !editing && 'bg-white-50');
    const props = {
      'data-e2e': "input|".concat(path),
      className,
      onChange,
      onFocus: this.focus,
      onBlur: this.blur,
      name: path,
      value
    };
    return (0, _preact.h)("div", {
      className: "w-100 mr2"
    }, matchType === 'text' && (0, _preact.h)("input", props), matchType === 'longText' && (0, _preact.h)("textarea", _extends({}, props, {
      rows: editing ? 5 : 1
    })));
  }

}

const CategoryEntry = ({
  name,
  path,
  skippedArray,
  skipped,
  onClick,
  onChange,
  items
}) => {
  const parentSkipped = skipped;
  return (0, _preact.h)("div", {
    className: "pa2 bg-light-blue br2 mb2"
  }, (0, _preact.h)("label", null, (0, _preact.h)("h4", {
    className: "mv1"
  }, (0, _preact.h)("input", {
    type: "checkbox",
    key: path,
    className: "mr2",
    name: path,
    checked: !skipped,
    onChange: onClick
  }), (0, _preact.h)("span", {
    className: (0, _classnames.default)(skipped && 'strike')
  }, name))), (0, _preact.h)("div", null, items.map(item => (0, _preact.h)(ItemEntry, {
    key: item.path,
    item: item,
    onChange: onChange,
    skipped: parentSkipped || skippedArray.includes(item.path),
    onClick: onClick
  }))));
};

const noOp = () => {};

const ItemEntry = ({
  item,
  skipped,
  onClick,
  onChange = noOp
}) => {
  const match = (0, _macro.getMacroFieldType)(item.path);
  return (0, _preact.h)("label", {
    className: (0, _classnames.default)('db mv2 br2 pa2 flex items-center', skipped ? 'bg-light-blue' : 'bg-lightest-blue'),
    key: item.path
  }, (0, _preact.h)("input", {
    type: "checkbox",
    className: "mr2",
    name: item.path,
    checked: !skipped,
    onChange: onClick
  }), (0, _preact.h)("span", {
    className: "nowrap mr2"
  }, item.label, ":"), (!match || skipped) && (0, _preact.h)("span", {
    className: (0, _classnames.default)(skipped && 'strike')
  }, item.value), match && !skipped && (0, _preact.h)(EditableText, {
    value: item.value,
    matchType: match,
    path: item.path,
    onChange: onChange
  }));
};

const Title = ({
  children
}) => (0, _preact.h)("h4", {
  className: "mb1 mt2"
}, children);

const DrugCategory = ({
  title,
  drugs,
  baseProp,
  skippedArray,
  onClick,
  itemsToHide
}) => (0, _preact.h)("div", null, (0, _preact.h)(Title, null, title), drugs.map((drug, index) => {
  const {
    name
  } = drug,
        rest = _objectWithoutProperties(drug, ["name"]);

  const basePath = "".concat(baseProp, ".[").concat(index, "]");
  const array = (0, _macro.macroToItemArrayBase)((0, _object.omit)(rest, ['id', ...itemsToHide]), basePath, _macro.macroDrugLabelMap);
  return (0, _preact.h)(CategoryEntry, {
    key: "dg_".concat(index),
    path: basePath,
    name: name,
    items: array,
    skipped: skippedArray.includes(basePath),
    skippedArray: skippedArray,
    onClick: onClick
  });
}));

class MacroSelectable extends _preact.Component {
  constructor(props) {
    super(props);

    this.checkboxClick = e => {
      e.preventDefault();
      this.toggle(e.target.name);
    };

    this.reportChanged = this.reportChanged.bind(this);
    this.onItemValueChange = this.onItemValueChange.bind(this);
    this.state = {
      skipped: props.skipped || [],
      overrideValues: {}
    };
    this.skipAll = this.skipAll.bind(this);
    this.reportChanged();
  }

  isSkipped(path) {
    return this.state.skipped.includes(path);
  }

  toggle(path) {
    this.isSkipped(path) ? this.unSkip(path) : this.skip(path);
  }

  unSkip(path) {
    if (this.isSkipped(path)) {
      this.updateSkipped(this.state.skipped.filter(name => name !== path));
    }
  }

  skipAll() {
    if (this.state.skipped.length > 0) {
      this.updateSkipped([]);
    } else {
      const skipped = [];

      for (const key in this.props.macro) {
        const entry = this.props.macro[key];
        const isArray = Array.isArray(entry);

        for (const secondLevel in entry) {
          skipped.push(isArray ? "".concat(key, ".[").concat(secondLevel, "]") : "".concat(key, ".").concat(secondLevel));
        }
      }

      this.updateSkipped(skipped);
    }
  }

  updateSkipped(skipped) {
    this.setState({
      skipped
    }, this.reportChanged);
  }

  selectAll() {
    this.setState({
      skipped: []
    });
  }

  skip(path) {
    this.updateSkipped([...this.state.skipped, path]);
  }

  onItemValueChange(event) {
    const {
      target
    } = event;
    const {
      name,
      value
    } = target;
    this.setState({
      overrideValues: _objectSpread(_objectSpread({}, this.state.overrideValues), {}, {
        [name]: value
      })
    }, this.reportChanged);
  }

  reportChanged() {
    this.props.onChange(this.getSaveableMacro(), this.state.skipped);
  }

  applyOverrideValues(macro) {
    const {
      overrideValues
    } = this.state;
    const updates = {};

    for (const key in overrideValues) {
      updates[key] = overrideValues[key];
    }

    return (0, _sinks.updateObject)(macro, updates);
  }

  getSaveableMacro() {
    /** @type {{ macro: Macro }} */
    const {
      macro
    } = this.props; // because we use arrays for some of these items, if we don't reverse keys first
    // we will start deleting from beginning of array, changes array indexes

    const updates = [...this.state.skipped].sort().reverse().reduce((acc, path) => {
      acc[path] = null;
      return acc;
    }, {});
    const withUpdatedValues = this.applyOverrideValues(macro);
    return (0, _sinks.updateObject)(withUpdatedValues, updates);
  }

  render() {
    /** @type {{ macro: Macro }} */
    const {
      macro: startingMacro,
      buttons
    } = this.props;

    if (!startingMacro) {
      return null;
    }

    const macro = this.applyOverrideValues(startingMacro);
    const {
      skipped: skippedArray
    } = this.state;
    const items = (0, _macro.macroToItemArrayBase)(macro.copied, 'copied', _macro.macroLabelMap);
    const vitalItems = (0, _macro.macroToItemArrayBase)(macro.vitalTypes || {}, 'vitalTypes', _vitalTypes.vitalsNameMap);
    return (0, _preact.h)("div", null, (0, _preact.h)("div", {
      className: "flex items-center mb3"
    }, buttons, (0, _preact.h)(_button.Button, {
      "data-e2e": "allButton",
      onClick: this.skipAll
    }, skippedArray.length ? 'Select All' : 'Deselect All')), items.map(item => (0, _preact.h)(ItemEntry, {
      key: item.path,
      item: item,
      onClick: this.checkboxClick,
      onChange: this.onItemValueChange,
      skipped: this.state.skipped.includes(item.path)
    })), macro.airways && (0, _preact.h)("div", null, (0, _preact.h)(Title, null, "Airways"), macro.airways.map((airway, index) => {
      const {
        type
      } = airway,
            rest = _objectWithoutProperties(airway, ["type"]);

      const basePath = "airways.[".concat(index, "]");
      const array = (0, _macro.macroToItemArrayBase)(rest, basePath, _macro.macroAirwayLabelMap);
      return (0, _preact.h)(CategoryEntry, {
        path: basePath,
        name: _airwayTypes.airwayTypeLookup[type].name,
        key: "aw_".concat(index),
        items: array,
        skipped: skippedArray.includes(basePath),
        skippedArray: skippedArray,
        onChange: this.onItemValueChange,
        onClick: this.checkboxClick
      });
    })), macro.vitalTypes && (0, _preact.h)("div", null, (0, _preact.h)(Title, null, "Vital Types"), vitalItems.map(item => (0, _preact.h)(ItemEntry, {
      key: item.path,
      item: item,
      onClick: this.checkboxClick,
      onChange: this.onItemValueChange,
      skipped: this.state.skipped.includes(item.path)
    }))), macro.localDrugs && (0, _preact.h)(DrugCategory, {
      title: "Local Anesthetics",
      drugs: macro.localDrugs,
      baseProp: "localDrugs",
      skippedArray: skippedArray,
      onClick: this.checkboxClick,
      itemsToHide: ['rxcui', 'percent', 'epi']
    }), macro.parenDrugs && (0, _preact.h)(DrugCategory, {
      title: "Parenteral Drugs",
      drugs: macro.parenDrugs,
      baseProp: "parenDrugs",
      skippedArray: skippedArray,
      onClick: this.checkboxClick,
      itemsToHide: ['unit']
    }), macro.oralSedatives && (0, _preact.h)(DrugCategory, {
      title: "Oral Sedatives",
      drugs: macro.oralSedatives,
      baseProp: "oralSedatives",
      skippedArray: skippedArray,
      onClick: this.checkboxClick,
      itemsToHide: ['unit']
    }), macro.infusionDrugs && (0, _preact.h)(DrugCategory, {
      title: "Infusion Drugs",
      drugs: macro.infusionDrugs,
      baseProp: "infusionDrugs",
      skippedArray: skippedArray,
      onClick: this.checkboxClick,
      itemsToHide: []
    }), buttons && (0, _preact.h)("div", {
      className: "mt3"
    }, buttons));
  }

}

exports.MacroSelectable = MacroSelectable;