import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import _regeneratorRuntime from "@babel/runtime/regenerator";
import React, { useMemo, useState } from 'react';
import { di } from 'react-magnetic-di';
import { ModalTransition } from '@atlaskit/modal-dialog';
import UserInputForm from './manual-triggers-form/main';
import { invokeManuallyTriggeredRule, searchManuallyTriggeredRules } from './services';

/**
 * React hook that implements the fetch and invoke actions for manual triggers.
 * Can be used standalone or in the HOC provided below.
 * @param site - The site to filter on. We map this to just a cloudId to resolve the manual rules API path
 * @param query - Query object containing filter props (container, object(s))
 */
export var useManualRules = function useManualRules(site, query) {
  var _useState = useState(false),
    _useState2 = _slicedToArray(_useState, 2),
    initialised = _useState2[0],
    setInitialised = _useState2[1];
  var _useState3 = useState(null),
    _useState4 = _slicedToArray(_useState3, 2),
    error = _useState4[0],
    setError = _useState4[1];
  var _useState5 = useState([]),
    _useState6 = _slicedToArray(_useState5, 2),
    rules = _useState6[0],
    setRules = _useState6[1];
  var transformRules = function transformRules(ruleResponse) {
    var rulesUnsorted = Object.values(ruleResponse);
    return rulesUnsorted.sort(function (rule1, rule2) {
      return rule1.name.localeCompare(rule2.name);
    });
  };
  var triggerFetch = /*#__PURE__*/function () {
    var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
      var fetchedRules;
      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) switch (_context.prev = _context.next) {
          case 0:
            setInitialised(false);
            _context.prev = 1;
            _context.next = 4;
            return searchManuallyTriggeredRules(site, query);
          case 4:
            fetchedRules = _context.sent;
            setError(null);
            setRules(transformRules(fetchedRules));
            _context.next = 13;
            break;
          case 9:
            _context.prev = 9;
            _context.t0 = _context["catch"](1);
            setError(_context.t0);
            setRules([]);
          case 13:
            _context.prev = 13;
            setInitialised(true);
            return _context.finish(13);
          case 16:
          case "end":
            return _context.stop();
        }
      }, _callee, null, [[1, 9, 13, 16]]);
    }));
    return function triggerFetch() {
      return _ref.apply(this, arguments);
    };
  }();
  return [triggerFetch, initialised, error, rules];
};
/**
 *
 * Container HOC that implements the above hook and behaviours.
 *
 * This HOC uses rendered props to allow the use of any render instructions
 * for manual rules, while still maintaining the behaviour of invoking rules.
 *
 * The HOC also appends a dialog that is displayed when the {@code invokeRuleOrShowDialog}
 * prop is called, if the underlying rule has user inputs.
 *
 * The component exposes the "invokingRuleId" property to the child hierarchy,
 * because the children might care about the invocation state. It does not expose
 * the "selected" state, or any information about the dialog, as the children
 * should not care about this, only how to trigger invocation and understand
 * the invocation lifecycle.
 *
 * @param props - cloudId, projectId, children
 */
export var ManualRulesContainer = function ManualRulesContainer(props) {
  var site = props.site,
    query = props.query,
    children = props.children,
    onInputsModalOpened = props.onInputsModalOpened,
    onInputsModalClosed = props.onInputsModalClosed,
    onRuleInvocationLifecycleStarted = props.onRuleInvocationLifecycleStarted,
    onRuleInvocationSuccess = props.onRuleInvocationSuccess,
    onRuleInvocationFailure = props.onRuleInvocationFailure,
    onRuleInvocationLifecycleDone = props.onRuleInvocationLifecycleDone;
  // Initial data loading state
  var _useManualRules = useManualRules(site, query),
    _useManualRules2 = _slicedToArray(_useManualRules, 4),
    triggerFetch = _useManualRules2[0],
    initialised = _useManualRules2[1],
    error = _useManualRules2[2],
    rules = _useManualRules2[3];
  // We store a rule in state here if and only if a rule has user inputs, and thus
  // we need to preserve state while the input dialog is open.
  var _useState7 = useState(null),
    _useState8 = _slicedToArray(_useState7, 2),
    selectedRule = _useState8[0],
    setSelectedRule = _useState8[1];
  var clearSelectedRule = function clearSelectedRule() {
    setSelectedRule(null);
  };
  // Value set when a rule is invoking, either from the dialog or without dialog
  var _useState9 = useState(null),
    _useState0 = _slicedToArray(_useState9, 2),
    invokingRuleId = _useState0[0],
    setInvokingRuleId = _useState0[1];

  // Memoized projection of rules by id
  var rulesById = useMemo(function () {
    return rules.reduce(function (acc, rule) {
      return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, rule.id, rule));
    }, {});
  }, [rules]);
  var getRule = function getRule(id) {
    return rulesById[id];
  };
  var ruleHasInputs = function ruleHasInputs(rule) {
    var _rule$userInputPrompt;
    return (rule === null || rule === void 0 || (_rule$userInputPrompt = rule.userInputPrompts) === null || _rule$userInputPrompt === void 0 ? void 0 : _rule$userInputPrompt.length) > 0;
  };
  var getFailedObjects = function getFailedObjects(response) {
    return Object.keys(response).filter(function (object) {
      return response[object] !== 'SUCCESS';
    });
  };
  var getSuccessfulObjects = function getSuccessfulObjects(response) {
    return Object.keys(response).filter(function (object) {
      return response[object] === 'SUCCESS';
    });
  };
  var handleInvocationFailure = function handleInvocationFailure(ruleId, successfulObjects, failedObjects) {
    if (onRuleInvocationFailure) {
      onRuleInvocationFailure(ruleId, successfulObjects, failedObjects);
    }
  };
  var invokeRule = /*#__PURE__*/function () {
    var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(ruleId, objects, userInputs) {
      var rule, response, failedObjects, successfulObjects;
      return _regeneratorRuntime.wrap(function _callee2$(_context2) {
        while (1) switch (_context2.prev = _context2.next) {
          case 0:
            rule = getRule(ruleId);
            if (!rule) {
              _context2.next = 19;
              break;
            }
            setInvokingRuleId(ruleId);
            _context2.prev = 3;
            if (onRuleInvocationLifecycleStarted) {
              onRuleInvocationLifecycleStarted(ruleId, objects, userInputs);
            }
            _context2.next = 7;
            return invokeManuallyTriggeredRule(site, ruleId, objects, userInputs);
          case 7:
            response = _context2.sent;
            failedObjects = getFailedObjects(response);
            setInvokingRuleId(null);
            if (failedObjects.length === 0) {
              if (onRuleInvocationSuccess) {
                onRuleInvocationSuccess(ruleId, objects);
              }
            } else {
              successfulObjects = getSuccessfulObjects(response);
              handleInvocationFailure(ruleId, successfulObjects, failedObjects);
            }
            _context2.next = 17;
            break;
          case 13:
            _context2.prev = 13;
            _context2.t0 = _context2["catch"](3);
            handleInvocationFailure(ruleId, [], objects);
            setInvokingRuleId(null);
          case 17:
            _context2.next = 20;
            break;
          case 19:
            handleInvocationFailure(ruleId, [], objects);
          case 20:
            clearSelectedRule();
            if (onRuleInvocationLifecycleDone) {
              onRuleInvocationLifecycleDone(ruleId, objects);
            }
          case 22:
          case "end":
            return _context2.stop();
        }
      }, _callee2, null, [[3, 13]]);
    }));
    return function invokeRule(_x, _x2, _x3) {
      return _ref2.apply(this, arguments);
    };
  }();
  var invokeRuleOrShowDialog = function invokeRuleOrShowDialog(ruleId, objects) {
    var rule = getRule(ruleId);
    if (!rule) {
      return handleInvocationFailure(ruleId, [], objects);
    }
    if (ruleHasInputs(rule)) {
      setSelectedRule({
        rule: rule,
        objects: objects
      });
    } else {
      invokeRule(ruleId, objects);
    }
  };
  return /*#__PURE__*/React.createElement(React.Fragment, null, children({
    triggerFetch: triggerFetch,
    initialised: initialised,
    error: error,
    rules: rules,
    invokingRuleId: invokingRuleId,
    invokeRuleOrShowDialog: invokeRuleOrShowDialog
  }), /*#__PURE__*/React.createElement(ModalTransition, null, selectedRule && /*#__PURE__*/React.createElement(UserInputForm, {
    onInputsModalOpened: onInputsModalOpened,
    onInputsModalClosed: onInputsModalClosed,
    clearSelectedRule: clearSelectedRule,
    selectedRule: selectedRule,
    invokeRule: invokeRule
  })));
};