import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _regeneratorRuntime from "@babel/runtime/regenerator";
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import React, { useCallback, useEffect, useState } from 'react';
import { unstable_batchedUpdates } from 'react-dom';
import { extractLink } from '@atlaskit/link-extractors';
import { useSmartLinkContext } from '@atlaskit/link-provider';
import { useAnalyticsEvents } from '../../common/analytics/generated/use-analytics-events';
import useIncomingOutgoingAri from '../../state/hooks/use-incoming-outgoing-links';
import useResponse from '../../state/hooks/use-response';
import RelatedLinksBaseModal from './components/RelatedLinksBaseModal';
import RelatedLinksErroredView from './views/errored';
import RelatedLinksResolvedView from './views/resolved';
import RelatedLinksResolvingView from './views/resolving';
import RelatedLinksUnavailableView from './views/unavailable';
var isGrantedResponse = function isGrantedResponse(response) {
  var _response$body$meta;
  return 'body' in response && ((_response$body$meta = response.body.meta) === null || _response$body$meta === void 0 ? void 0 : _response$body$meta.access) === 'granted';
};
var RelatedLinksModal = function RelatedLinksModal(_ref) {
  var onClose = _ref.onClose,
    showModal = _ref.showModal,
    ari = _ref.ari,
    baseUriWithNoTrailingSlash = _ref.baseUriWithNoTrailingSlash;
  var RELATED_LINKS_LENGTH = 5;
  var _useIncomingOutgoingA = useIncomingOutgoingAri(baseUriWithNoTrailingSlash),
    getIncomingOutgoingAris = _useIncomingOutgoingA.getIncomingOutgoingAris;
  var _useSmartLinkContext = useSmartLinkContext(),
    connections = _useSmartLinkContext.connections;
  var _useResponse = useResponse(),
    handleResolvedLinkResponse = _useResponse.handleResolvedLinkResponse;
  var _useAnalyticsEvents = useAnalyticsEvents(),
    fireEvent = _useAnalyticsEvents.fireEvent;
  var _useState = useState([]),
    _useState2 = _slicedToArray(_useState, 2),
    incomingLinks = _useState2[0],
    setIncomingLinks = _useState2[1];
  var _useState3 = useState([]),
    _useState4 = _slicedToArray(_useState3, 2),
    outgoingLinks = _useState4[0],
    setOutgoingLinks = _useState4[1];
  var _useState5 = useState('loading'),
    _useState6 = _slicedToArray(_useState5, 2),
    modalStatus = _useState6[0],
    setModalStatus = _useState6[1];

  /**
   * resolves the given ARIs to JSONLD and stores in store using the url present in the JSONLD
   * on successful resolve, it takes the url from the response and dispatches a resolve action
   * on a fail resolve, it is ignored as dispatch error takes in an url that we do not have
   */
  var resolveAris = useCallback( /*#__PURE__*/function () {
    var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(aris) {
      var urlArray, batchResponse, _iterator, _step, res, url, _t;
      return _regeneratorRuntime.wrap(function (_context) {
        while (1) switch (_context.prev = _context.next) {
          case 0:
            if (!(aris.length === 0)) {
              _context.next = 1;
              break;
            }
            return _context.abrupt("return", []);
          case 1:
            urlArray = [];
            _context.next = 2;
            return connections.client.fetchDataAris(aris);
          case 2:
            batchResponse = _context.sent;
            _iterator = _createForOfIteratorHelper(batchResponse);
            _context.prev = 3;
            _iterator.s();
          case 4:
            if ((_step = _iterator.n()).done) {
              _context.next = 9;
              break;
            }
            res = _step.value;
            if (isGrantedResponse(res)) {
              _context.next = 5;
              break;
            }
            return _context.abrupt("continue", 8);
          case 5:
            if (res.body.data) {
              _context.next = 6;
              break;
            }
            return _context.abrupt("continue", 8);
          case 6:
            url = 'url' in res.body.data && extractLink(res.body.data);
            if (url) {
              _context.next = 7;
              break;
            }
            return _context.abrupt("continue", 8);
          case 7:
            handleResolvedLinkResponse(url, res.body, false, false);
            urlArray.push(url);
          case 8:
            _context.next = 4;
            break;
          case 9:
            _context.next = 11;
            break;
          case 10:
            _context.prev = 10;
            _t = _context["catch"](3);
            _iterator.e(_t);
          case 11:
            _context.prev = 11;
            _iterator.f();
            return _context.finish(11);
          case 12:
            return _context.abrupt("return", urlArray);
          case 13:
          case "end":
            return _context.stop();
        }
      }, _callee, null, [[3, 10, 11, 12]]);
    }));
    return function (_x) {
      return _ref2.apply(this, arguments);
    };
  }(), [connections.client, handleResolvedLinkResponse]);

  /**
   * Gets incoming outgoing ARI's for the given ARI and resolves them to JSONLD
   * throws when request to both incoming and outgoing requests error out
   */
  var fetchIncomingOutgoingData = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
    var _yield$getIncomingOut, incomingAris, outgoingAris, incomingRejected, outGoingRejected, _yield$Promise$all, _yield$Promise$all2, incomingUrls, outgoingUrls;
    return _regeneratorRuntime.wrap(function (_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          _context2.next = 1;
          return getIncomingOutgoingAris(ari);
        case 1:
          _yield$getIncomingOut = _context2.sent;
          incomingAris = _yield$getIncomingOut.incomingAris;
          outgoingAris = _yield$getIncomingOut.outgoingAris;
          incomingRejected = false;
          outGoingRejected = false;
          _context2.next = 2;
          return Promise.all([resolveAris(incomingAris).catch(function () {
            incomingRejected = true;
          }), resolveAris(outgoingAris).catch(function () {
            outGoingRejected = true;
          })]);
        case 2:
          _yield$Promise$all = _context2.sent;
          _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
          incomingUrls = _yield$Promise$all2[0];
          outgoingUrls = _yield$Promise$all2[1];
          if (!(incomingRejected && outGoingRejected)) {
            _context2.next = 3;
            break;
          }
          throw new Error('both incoming and outgoing resolve request were rejected');
        case 3:
          return _context2.abrupt("return", {
            incomingUrls: incomingUrls !== null && incomingUrls !== void 0 ? incomingUrls : [],
            outgoingUrls: outgoingUrls !== null && outgoingUrls !== void 0 ? outgoingUrls : []
          });
        case 4:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  })), [ari, getIncomingOutgoingAris, resolveAris]);
  useEffect(function () {
    if (!ari) {
      setModalStatus('error');
      fireEvent('operational.relatedLinks.failed', {
        reason: 'ARI empty'
      });
      return;
    }
    fetchIncomingOutgoingData().then(function (_ref4) {
      var incomingUrls = _ref4.incomingUrls,
        outgoingUrls = _ref4.outgoingUrls;
      //Need either one of incoming/outgoing to have item(s) to be resolved
      if (incomingUrls.length + outgoingUrls.length) {
        // we are only rendering the first 5 links that are returned from our request
        unstable_batchedUpdates(function () {
          setIncomingLinks(incomingUrls.slice(0, RELATED_LINKS_LENGTH));
          setOutgoingLinks(outgoingUrls.slice(0, RELATED_LINKS_LENGTH));
        });
        setModalStatus('resolved');
      } else {
        // if no links are found then render unavailable view
        setModalStatus('unavailable');
      }
      fireEvent('operational.relatedLinks.success', {
        incomingCount: incomingUrls.length,
        outgoingCount: outgoingUrls.length
      });
    }).catch(function (_error) {
      setModalStatus('error');
      fireEvent('operational.relatedLinks.failed', {
        reason: 'Failed to fetch related links'
      });
    });
  }, [ari, connections.client, fetchIncomingOutgoingData, fireEvent, getIncomingOutgoingAris, handleResolvedLinkResponse]);
  var renderView = function renderView() {
    switch (modalStatus) {
      case 'error':
        return /*#__PURE__*/React.createElement(RelatedLinksErroredView, null);
      case 'resolved':
        return /*#__PURE__*/React.createElement(RelatedLinksResolvedView, {
          incomingLinks: incomingLinks,
          outgoingLinks: outgoingLinks
        });
      case 'unavailable':
        return /*#__PURE__*/React.createElement(RelatedLinksUnavailableView, null);
      default:
        return /*#__PURE__*/React.createElement(RelatedLinksResolvingView, null);
    }
  };
  return /*#__PURE__*/React.createElement(RelatedLinksBaseModal, {
    onClose: onClose,
    showModal: showModal
  }, renderView());
};
export default RelatedLinksModal;