"use strict";

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

var _generateBundle = require("../utils/generate-bundle");

var _reduxBundler = require("redux-bundler");

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

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; }

const ORG_FETCH_STARTED = 'ORG_FETCH_STARTED';
const ORG_FETCH_FINISHED = 'ORG_FETCH_FINISHED';
const ORG_FETCH_FAILED = 'ORG_FETCH_FAILED';
const ORG_FEATURE_OVERRIDE = 'ORG_FEATURE_OVERRIDE';

const subscriptionTransform = sub => Object.assign({}, sub, {
  cancelledAt: Number(sub.cancelledAt),
  currentPeriodEnd: Number(sub.currentPeriodEnd),
  currentPeriodStart: Number(sub.currentPeriodStart),
  start: Number(sub.start),
  trialEnd: Number(sub.trialEnd),
  trialStart: Number(sub.trialStart)
});

const getOrgsBundle = (_ref) => {
  let {
    orgResponseSnippet,
    activeOrgSelectorName
  } = _ref,
      rest = _objectWithoutProperties(_ref, ["orgResponseSnippet", "activeOrgSelectorName"]);

  return (0, _generateBundle.generateBundle)(_objectSpread({
    name: 'orgs',
    initialState: {
      featureOverrides: {}
    },
    actionTypes: {
      [ORG_FETCH_STARTED]: {
        handler: (state, payload) => _objectSpread(_objectSpread({}, state), {}, {
          [payload]: _objectSpread(_objectSpread({}, state[payload]), {}, {
            loading: true
          })
        })
      },
      [ORG_FETCH_FINISHED]: {
        handler: (state, payload) => _objectSpread(_objectSpread({}, state), {}, {
          [payload.id]: _objectSpread(_objectSpread({}, state[payload.id]), {}, {
            loading: false,
            data: payload.data
          })
        })
      },
      [ORG_FETCH_FAILED]: {
        handler: (state, payload) => _objectSpread(_objectSpread({}, state), {}, {
          [payload.id]: _objectSpread(_objectSpread({}, state[payload.id]), {}, {
            loading: false,
            error: payload.error
          })
        })
      },
      [ORG_FEATURE_OVERRIDE]: {
        handler: (state, {
          orgId,
          name,
          value
        }) => {
          const existing = state.featureOverrides[orgId] || {}; // treat null as delete

          if (value === null) {
            return _objectSpread(_objectSpread({}, state), {}, {
              featureOverrides: _objectSpread(_objectSpread({}, state.featureOverrides), {}, {
                [orgId]: (0, _object.omit)(existing, [name])
              })
            });
          }

          return _objectSpread(_objectSpread({}, state), {}, {
            featureOverrides: _objectSpread(_objectSpread({}, state.featureOverrides), {}, {
              [orgId]: _objectSpread(_objectSpread({}, existing), {}, {
                [name]: value
              })
            })
          });
        }
      }
    },
    selectOrgsRaw: state => state.orgs,
    selectActiveOrgData: (0, _reduxBundler.createSelector)(activeOrgSelectorName, 'selectOrgsRaw', (activeId, raw) => activeId && raw[activeId] && raw[activeId].data),
    selectHasActiveOrgData: (0, _reduxBundler.createSelector)('selectActiveOrgData', Boolean),
    selectOrgs: (0, _reduxBundler.createSelector)(activeOrgSelectorName, 'selectSessionOrgs', 'selectActiveOrgData', 'selectOrgsRaw', 'selectIsXchartUberUser', (activeId, sessionOrgs, activeOrgData, orgsRaw, isXchartUber) => {
      const shouldAddOrgId = isXchartUber && activeId && sessionOrgs && !sessionOrgs.find(org => org.id === activeId);
      const modifiedSessionOrgs = shouldAddOrgId ? [...sessionOrgs, {
        id: activeId
      }] : sessionOrgs || [];
      return modifiedSessionOrgs.map(({
        id,
        type
      }) => {
        const active = id === activeId;
        let name;

        if (active) {
          name = activeOrgData && activeOrgData.name;
        }

        const matchingOrg = orgsRaw[id] || {};
        const matchingOrgData = matchingOrg.data || {};
        const features = matchingOrgData.featuresJSON ? JSON.parse(matchingOrgData.featuresJSON) : {};
        const featureOverrides = (orgsRaw.featureOverrides || {})[id] || {};
        return _objectSpread({
          id,
          name: name || id,
          type,
          active,
          loading: matchingOrg.loading,
          features: _objectSpread(_objectSpread({}, features), featureOverrides)
        }, (0, _object.pluck)(matchingOrgData, ['addressLine1', 'addressLine2', 'city', 'state', 'postalCode', 'country', 'visionType', 'taxStatus']));
      });
    }),
    selectActiveOrg: (0, _reduxBundler.createSelector)('selectOrgs', orgs => orgs.find(org => org.active)),
    selectOrgFeatures: (0, _reduxBundler.createSelector)('selectActiveOrg', activeOrg => activeOrg && activeOrg.features || {}),
    selectActiveOrgName: (0, _reduxBundler.createSelector)('selectActiveOrg', org => org && org.name),
    doOrgFeatureOverride: ({
      feature,
      value = true,
      orgId
    }) => ({
      store,
      dispatch
    }) => {
      dispatch({
        type: ORG_FEATURE_OVERRIDE,
        payload: {
          orgId: orgId || store[activeOrgSelectorName](),
          name: feature,
          value
        }
      });
    },
    doReceiveOrg: (orgId, data) => {
      const payloadData = _objectSpread({}, data);

      if (data.subscription) {
        payloadData.subscription = subscriptionTransform(data.subscription);
      }

      return {
        type: ORG_FETCH_FINISHED,
        payload: {
          id: orgId,
          data: payloadData
        }
      };
    },
    doFetchOrg: orgId => ({
      gqlFetch,
      dispatch,
      store
    }) => {
      if (!orgId) {
        orgId = store[activeOrgSelectorName]();
      }

      dispatch({
        type: ORG_FETCH_STARTED,
        payload: orgId
      });
      return gqlFetch("{ org(orgId: \"".concat(orgId, "\") ").concat(orgResponseSnippet, "}")).then(res => store.doReceiveOrg(orgId, res.data.org));
    },
    reactFetchOrgs: (0, _reduxBundler.createSelector)(activeOrgSelectorName, 'selectIsSignedIn', 'selectSessionOrgIds', 'selectOrgsRaw', 'selectIsXchartUberUser', (activeOrgId, isSignedIn, sessionOrgIds, orgsMetadata, isXchartUber) => {
      if (!activeOrgId || !isSignedIn || !sessionOrgIds.length) {
        return;
      }

      const isInOrg = sessionOrgIds.includes(activeOrgId);

      if (!isInOrg && !isXchartUber) {
        return;
      }

      const meta = orgsMetadata[activeOrgId];

      if (meta) {
        const {
          data,
          loading,
          error
        } = meta;

        if (data || loading || error) {
          return;
        }
      }

      return {
        actionCreator: 'doFetchOrg',
        args: [activeOrgId]
      };
    })
  }, rest));
};

exports.getOrgsBundle = getOrgsBundle;