'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-cd6fab62.js');
const defaultI18n = require('./default-i18n-072e75d7.js');
require('./index-20b57ec7.js');
const fetch = require('./fetch-a8709225.js');
const formData = require('./form-data-8b4a6451.js');
const index$1 = require('./index-c1a1f929.js');
const checkouts = require('./checkouts-ace88d0b.js');
const addQueryArgs = require('./add-query-args-17c551b6.js');
require('./_commonjsHelpers-537d719a.js');

/**
 * Internal dependencies
 */
/**
 * Removes arguments from the query string of the url
 *
 * @param {string}    url  URL.
 * @param {...string} args Query Args.
 *
 * @example
 * ```js
 * const newUrl = removeQueryArgs( 'https://wordpress.org?foo=bar&bar=baz&baz=foobar', 'foo', 'bar' ); // https://wordpress.org?baz=foobar
 * ```
 *
 * @return {string} Updated URL.
 */

function removeQueryArgs(url) {
  const queryStringIndex = url.indexOf('?');

  if (queryStringIndex === -1) {
    return url;
  }

  const query = addQueryArgs.getQueryArgs(url);
  const baseURL = url.substr(0, queryStringIndex);

  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    args[_key - 1] = arguments[_key];
  }

  args.forEach(arg => delete query[arg]);
  const queryString = addQueryArgs.buildQueryString(query);
  return queryString ? baseURL + '?' + queryString : baseURL;
}

const ScFormComponentsValidator = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
  }
  handleOrderChange() {
    var _a, _b;
    // bail if we don't have address invalid error or disabled.
    if (this.disabled)
      return;
    // make sure to add the address field if it's not there.
    if (((_a = this === null || this === void 0 ? void 0 : this.order) === null || _a === void 0 ? void 0 : _a.tax_status) === 'address_invalid' || ((_b = this === null || this === void 0 ? void 0 : this.order) === null || _b === void 0 ? void 0 : _b.shipping_enabled)) {
      this.addAddressField();
    }
  }
  componentWillLoad() {
    var _a, _b;
    this.hasAddress = !!this.el.querySelector('sc-order-shipping-address');
    this.hasTaxIDField = !!this.el.querySelector('sc-order-tax-id-input');
    // automatically add address field if tax is enabled.
    if ((_a = this.taxProtocol) === null || _a === void 0 ? void 0 : _a.tax_enabled) {
      this.addAddressField();
      // if eu vat is required, add the tax id field.
      if ((_b = this.taxProtocol) === null || _b === void 0 ? void 0 : _b.eu_vat_required) {
        this.addTaxIDField();
      }
    }
    // make sure to check order on load.
    this.handleOrderChange();
  }
  addAddressField() {
    if (this.hasAddress)
      return;
    const payment = this.el.querySelector('sc-payment');
    const address = document.createElement('sc-order-shipping-address');
    address.label = defaultI18n.__('Address', 'surecart');
    payment.parentNode.insertBefore(address, payment);
    this.hasAddress = true;
  }
  addTaxIDField() {
    if (this.hasTaxIDField)
      return;
    const payment = this.el.querySelector('sc-payment');
    const taxInput = document.createElement('sc-order-tax-id-input');
    payment.parentNode.insertBefore(taxInput, payment);
    this.hasTaxIDField = true;
  }
  render() {
    return index.h("slot", null);
  }
  get el() { return index.getElement(this); }
  static get watchers() { return {
    "order": ["handleOrderChange"]
  }; }
};

const ScFormErrorProvider = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.scUpdateError = index.createEvent(this, "scUpdateError", 7);
    this.scSetState = index.createEvent(this, "scSetState", 7);
  }
  /** Trigger the error event when an error happens  */
  handleErrorUpdate(val) {
    this.scUpdateError.emit(val);
  }
  handleOrderChange() {
    this.error = null;
  }
  /** Listen for error events in component. */
  handleErrorEvent(e) {
    this.error = e.detail;
    if (Object.keys((e === null || e === void 0 ? void 0 : e.detail) || {}).length) {
      this.scSetState.emit('REJECT'); // make sure we are rejecting the current state.
    }
  }
  /** Listen for pay errors. */
  handlePayError(e) {
    var _a;
    this.error = ((_a = e.detail) === null || _a === void 0 ? void 0 : _a.message) || {
      code: '',
      message: 'Something went wrong with your payment.',
    };
  }
  /** This filters the error message with some more client friendly error messages. */
  getErrorMessage(error) {
    if (error.code === 'order.line_items.price.blank') {
      return defaultI18n.__('This product is no longer purchasable.', 'surecart');
    }
    return error === null || error === void 0 ? void 0 : error.message;
  }
  /** First will display validation error, then main error if no validation errors. */
  errorMessage() {
    var _a, _b, _c, _d, _e, _f;
    if ((_c = (_b = (_a = this.error) === null || _a === void 0 ? void 0 : _a.additional_errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) {
      return this.getErrorMessage((_e = (_d = this.error) === null || _d === void 0 ? void 0 : _d.additional_errors) === null || _e === void 0 ? void 0 : _e[0]);
    }
    else if ((_f = this === null || this === void 0 ? void 0 : this.error) === null || _f === void 0 ? void 0 : _f.message) {
      return this.getErrorMessage(this === null || this === void 0 ? void 0 : this.error);
    }
    return '';
  }
  render() {
    return (index.h(index.Host, null, !!this.errorMessage() && (index.h("sc-alert", { type: "danger", scrollOnOpen: true, open: !!this.errorMessage() }, index.h("span", { slot: "title" }, this.errorMessage()))), index.h("slot", null)));
  }
  static get watchers() { return {
    "error": ["handleErrorUpdate"],
    "order": ["handleOrderChange"]
  }; }
};

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function t(t,n){var e="function"==typeof Symbol&&t[Symbol.iterator];if(!e)return t;var r,o,i=e.call(t),a=[];try{for(;(void 0===n||n-- >0)&&!(r=i.next()).done;)a.push(r.value);}catch(t){o={error:t};}finally{try{r&&!r.done&&(e=i.return)&&e.call(i);}finally{if(o)throw o.error}}return a}var n;!function(t){t[t.NotStarted=0]="NotStarted",t[t.Running=1]="Running",t[t.Stopped=2]="Stopped";}(n||(n={}));var e={type:"xstate.init"};function r(t){return void 0===t?[]:[].concat(t)}function o(t){return {type:"xstate.assign",assignment:t}}function i(t,n){return "string"==typeof(t="string"==typeof t&&n&&n[t]?n[t]:t)?{type:t}:"function"==typeof t?{type:t.name,exec:t}:t}function a(t){return function(n){return t===n}}function u(t){return "string"==typeof t?{type:t}:t}function c(t,n){return {value:t,context:n,actions:[],changed:!1,matches:a(t)}}function f(t,n,e){var r=n,o=!1;return [t.filter((function(t){if("xstate.assign"===t.type){o=!0;var n=Object.assign({},r);return "function"==typeof t.assignment?n=t.assignment(r,e):Object.keys(t.assignment).forEach((function(o){n[o]="function"==typeof t.assignment[o]?t.assignment[o](r,e):t.assignment[o];})),r=n,!1}return !0})),r,o]}function s(n,o){void 0===o&&(o={});var s=t(f(r(n.states[n.initial].entry).map((function(t){return i(t,o.actions)})),n.context,e),2),l=s[0],v=s[1],y={config:n,_options:o,initialState:{value:n.initial,actions:l,context:v,matches:a(n.initial)},transition:function(e,o){var s,l,v="string"==typeof e?{value:e,context:n.context}:e,p=v.value,g=v.context,d=u(o),x=n.states[p];if(x.on){var m=r(x.on[d.type]);try{for(var h=function(t){var n="function"==typeof Symbol&&Symbol.iterator,e=n&&t[n],r=0;if(e)return e.call(t);if(t&&"number"==typeof t.length)return {next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}};throw new TypeError(n?"Object is not iterable.":"Symbol.iterator is not defined.")}(m),b=h.next();!b.done;b=h.next()){var S=b.value;if(void 0===S)return c(p,g);var w="string"==typeof S?{target:S}:S,j=w.target,E=w.actions,R=void 0===E?[]:E,N=w.cond,O=void 0===N?function(){return !0}:N,_=void 0===j,k=null!=j?j:p,T=n.states[k];if(O(g,d)){var q=t(f((_?r(R):[].concat(x.exit,R,T.entry).filter((function(t){return t}))).map((function(t){return i(t,y._options.actions)})),g,d),3),z=q[0],A=q[1],B=q[2],C=null!=j?j:p;return {value:C,context:A,actions:z,changed:j!==p||z.length>0||B,matches:a(C)}}}}catch(t){s={error:t};}finally{try{b&&!b.done&&(l=h.return)&&l.call(h);}finally{if(s)throw s.error}}}return c(p,g)}};return y}var l=function(t,n){return t.actions.forEach((function(e){var r=e.exec;return r&&r(t.context,n)}))};function v(t){var r=t.initialState,o=n.NotStarted,i=new Set,c={_machine:t,send:function(e){o===n.Running&&(r=t.transition(r,e),l(r,u(e)),i.forEach((function(t){return t(r)})));},subscribe:function(t){return i.add(t),t(r),{unsubscribe:function(){return i.delete(t)}}},start:function(i){if(i){var u="object"==typeof i?i:{context:t.config.context,value:i};r={value:u.value,actions:[],context:u.context,matches:a(u.value)};}return o=n.Running,l(r,e),c},stop:function(){return o=n.Stopped,i.clear(),c},get state(){return r},get status(){return o}};return c}

const checkoutMachine = s({
  id: 'fetch',
  initial: 'idle',
  context: {
    retries: 3,
  },
  states: {
    idle: {
      on: {
        FETCH: 'loading',
      },
    },
    loading: {
      on: {
        RESOLVE: 'draft',
        REJECT: 'failure',
        EXPIRE: 'expired',
        PAID: 'paid',
      },
    },
    draft: {
      on: {
        FINALIZE: 'finalizing',
        FETCH: 'updating',
        REJECT: 'draft',
      },
    },
    updating: {
      on: {
        RESOLVE: 'draft',
        EXPIRE: 'expired',
        REJECT: 'draft',
      },
    },
    finalizing: {
      on: {
        PAID: 'paid',
        REJECT: 'draft',
      },
    },
    paid: {
      on: {
        CONFIRMED: 'confirmed',
        REJECT: 'draft',
      },
    },
    expired: {},
    confirmed: {},
    failure: {
      on: {
        RETRY: {
          target: 'loading',
          actions: o({
            retries: (context) => context.retries + 1,
          }),
        },
      },
    },
  },
});

const ScFormStateProvider = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.scSetCheckoutFormState = index.createEvent(this, "scSetCheckoutFormState", 7);
    /** Holds our state machine service */
    this._stateService = v(checkoutMachine);
    /** Loading states for different parts of the form. */
    this.checkoutState = checkoutMachine.initialState;
  }
  /** Set the state. */
  setState(name) {
    const { send } = this._stateService;
    return send(name);
  }
  /** Watch for checkout state changes and emit to listeners. */
  handleCheckoutStateChange(state) {
    this.scSetCheckoutFormState.emit(state.value);
  }
  /** Init the state service. */
  componentWillLoad() {
    // Start state machine.
    this._stateService.subscribe(state => (this.checkoutState = state));
    this._stateService.start();
  }
  /** Remove state machine on disconnect. */
  disconnectedCallback() {
    this._stateService.stop();
  }
  /** Allow children to set the form state. */
  handleSetStateEvent(e) {
    this.setState(e.detail);
  }
  /** Update the state when the order is paid. */
  async handlePaid() {
    this.setState('PAID');
  }
  /** Update the state when the order is paid. */
  async handleConfirmed() {
    this.setState('CONFIRMED');
  }
  render() {
    // handle expired.
    if (this.checkoutState.value === 'expired') {
      return (index.h("sc-block-ui", null, index.h("div", null, defaultI18n.__('Please refresh the page.', 'surecart'))));
    }
    return index.h("slot", null);
  }
  static get watchers() { return {
    "checkoutState": ["handleCheckoutStateChange"]
  }; }
};

const ScOrderConfirmProvider = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.scConfirmed = index.createEvent(this, "scConfirmed", 7);
    this.scOrderPaid = index.createEvent(this, "scOrderPaid", 7);
    this.scError = index.createEvent(this, "scError", 7);
    /** Are we in test or live mode. */
    this.mode = 'live';
  }
  /** Listen for paid event. This is triggered by Stripe or Paypal elements when payment succeeds. */
  handlePaidEvent() {
    this.confirmOrder();
  }
  /** Confirm the order. */
  async confirmOrder() {
    var _a, _b;
    const json = await this.el.querySelector('sc-form').getFormJson();
    let data = formData.parseFormData(json);
    try {
      const confirmed = (await fetch.apiFetch({
        method: 'PATCH',
        path: addQueryArgs.addQueryArgs(`surecart/v1/checkouts/${(_a = this.order) === null || _a === void 0 ? void 0 : _a.id}/confirm`, [index$1.expand]),
        data,
      }));
      // emit the confirmed event to trigger listeners to redirect to the success url, etc.
      this.scConfirmed.emit();
      // emit the order paid event for tracking scripts.
      this.scOrderPaid.emit(confirmed);
    }
    catch (e) {
      console.error(e);
      this.scError.emit(e);
    }
    finally {
      const order = (_b = this.order) === null || _b === void 0 ? void 0 : _b.id;
      // make sure we clear the order state no matter what.
      checkouts.clearOrder(this.formId, this.mode);
      // we always want to redirect, regardless of the outcome here.
      window.location.assign(addQueryArgs.addQueryArgs(this.successUrl, { order }));
    }
  }
  render() {
    return index.h("slot", null);
  }
  get el() { return index.getElement(this); }
};

const getURLLineItems = () => {
  // check the url query first
  return fetch.getQueryArg(window.location.href, 'line_items');
};
const getURLCoupon = () => {
  // check the url query first
  return (fetch.getQueryArg(window.location.href, 'coupon') || '').toUpperCase();
};
/**
 * Attempt to get the session id
 *
 * @param formId The form id.
 * @param order The order
 * @param refresh Should we refresh?
 *
 * @returns string
 */
const getSessionId = (formId, order, modified) => {
  // if we already have an ID set, return that:
  if (order === null || order === void 0 ? void 0 : order.id) {
    return order.id;
  }
  // check the url query first
  const urlId = fetch.getQueryArg(window.location.href, 'order');
  if (urlId) {
    return urlId;
  }
  const savedModification = localStorage.getItem(`${formId}-modified`);
  // nothing saved.
  if (!savedModification) {
    return window.localStorage.getItem(formId);
  }
  // this has not been modified, so return the saved session id.
  if (modified && savedModification === modified) {
    return window.localStorage.getItem(formId);
  }
  return '';
};
const removeSessionId = formId => {
  // check id in localstorage
  return window.localStorage.removeItem(formId);
};

const ScSessionProvider = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.scUpdateOrderState = index.createEvent(this, "scUpdateOrderState", 7);
    this.scUpdateDraftState = index.createEvent(this, "scUpdateDraftState", 7);
    this.scPaid = index.createEvent(this, "scPaid", 7);
    this.scError = index.createEvent(this, "scError", 7);
    this.scSetState = index.createEvent(this, "scSetState", 7);
    /** Are we in test or live mode. */
    this.mode = 'live';
    /** An array of prices to pre-fill in the form. */
    this.prices = [];
    /** Currency Code */
    this.currencyCode = 'usd';
    /** The processor. */
    this.processor = 'stripe';
  }
  handleUpdateSession(e) {
    const { data, options } = e.detail;
    if (options === null || options === void 0 ? void 0 : options.silent) {
      this.update({ ...this.defaultFormData(), ...data });
    }
    else {
      this.loadUpdate(data);
    }
  }
  handlePricesChange() {
    let line_items = this.addInitialPrices() || [];
    line_items = this.addPriceChoices(line_items);
    if (!(line_items === null || line_items === void 0 ? void 0 : line_items.length)) {
      return;
    }
    return this.loadUpdate({ line_items });
  }
  /**
   * Finalize the order.
   *
   * @returns {Promise<Order>}
   */
  async finalize() {
    return await this.handleFormSubmit();
  }
  /** Get the order from the store. */
  order() {
    return checkouts.getOrder(this === null || this === void 0 ? void 0 : this.formId, this.mode);
  }
  getProcessor() {
    switch (this.processor) {
      case 'paypal':
      case 'paypal-card':
        return 'paypal';
      default:
        return 'stripe';
    }
  }
  getPaymentIntent() {
    var _a;
    const processor_type = this.getProcessor();
    return (_a = this.paymentIntents) === null || _a === void 0 ? void 0 : _a[processor_type];
  }
  /**
   * Handles the form submission.
   * @param e
   */
  async handleFormSubmit() {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j;
    this.scError.emit({});
    const payment_intent = this.getPaymentIntent();
    this.scSetState.emit('FINALIZE');
    // Get current form state.
    const json = await this.el.querySelector('sc-form').getFormJson();
    let data = formData.parseFormData(json);
    // first lets make sure the session is updated before we process it.
    try {
      await this.update({ ...this.defaultFormData(), ...data });
    }
    catch (e) {
      console.error(e);
      this.scSetState.emit('REJECT');
      this.handleErrorResponse(e);
    }
    // Important: Stripe needs a payment intent ahead of time, or the
    // order will not be attached to the payment.
    if (((_a = this.order()) === null || _a === void 0 ? void 0 : _a.total_amount) > 0 && !payment_intent && this.getProcessor() === 'stripe' && this.stripePaymentElement) {
      this.scError.emit({ message: 'Something went wrong. Please try again.' });
      console.error('No payment intent found.');
      return this.scSetState.emit('REJECT');
    }
    // first validate server-side and get key
    try {
      const order = await index$1.finalizeSession({
        id: (_b = this.order()) === null || _b === void 0 ? void 0 : _b.id,
        data,
        query: {
          ...this.defaultFormQuery(),
          ...((payment_intent === null || payment_intent === void 0 ? void 0 : payment_intent.id) ? { payment_intent_id: payment_intent === null || payment_intent === void 0 ? void 0 : payment_intent.id } : {}),
        },
        processor: this.getProcessor(),
      });
      // payment intent must match what we sent to make sure it's attached to an order.
      if (((_c = this.order()) === null || _c === void 0 ? void 0 : _c.total_amount) > 0 && (payment_intent === null || payment_intent === void 0 ? void 0 : payment_intent.id) && ((_d = order === null || order === void 0 ? void 0 : order.payment_intent) === null || _d === void 0 ? void 0 : _d.id) !== (payment_intent === null || payment_intent === void 0 ? void 0 : payment_intent.id)) {
        console.error('Payment intent mismatch', payment_intent === null || payment_intent === void 0 ? void 0 : payment_intent.id, (_e = order === null || order === void 0 ? void 0 : order.payment_intent) === null || _e === void 0 ? void 0 : _e.id);
        this.scError.emit({ message: 'Something went wrong. Please try again.' });
        return this.scSetState.emit('REJECT');
      }
      // the order is paid
      if ((order === null || order === void 0 ? void 0 : order.status) === 'paid') {
        this.scPaid.emit();
      }
      checkouts.setOrder(order, this.formId);
      return this.order();
    }
    catch (e) {
      // handle old price versions by refreshing.
      if (((_g = (_f = e === null || e === void 0 ? void 0 : e.additional_errors) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.code) === 'order.line_items.old_price_versions') {
        await this.loadUpdate({
          id: (_h = this.order()) === null || _h === void 0 ? void 0 : _h.id,
          data: {
            status: 'draft',
            refresh_price_versions: true,
          },
        });
        return;
      }
      // make it a draft again and resubmit if status is incorrect.
      if (['order.invalid_status_transition'].includes(e === null || e === void 0 ? void 0 : e.code)) {
        await this.loadUpdate({
          id: (_j = this.order()) === null || _j === void 0 ? void 0 : _j.id,
          data: {
            status: 'draft',
          },
        });
        this.handleFormSubmit();
        return;
      }
      this.handleErrorResponse(e);
    }
  }
  /**
   * Handle paid event and update the
   */
  async handlePaid() {
    this.scSetState.emit('PAID');
  }
  async handlePayError() {
    this.scSetState.emit('REJECT');
  }
  /** Handles coupon updates. */
  async handleCouponApply(e) {
    const promotion_code = e.detail;
    this.scError.emit({});
    this.loadUpdate({
      discount: {
        ...(promotion_code ? { promotion_code } : {}),
      },
    });
  }
  /** Handle the error response. */
  handleErrorResponse(e) {
    // expired
    if ((e === null || e === void 0 ? void 0 : e.code) === 'rest_cookie_invalid_nonce') {
      this.scSetState.emit('EXPIRE');
      return;
    }
    // paid
    if ((e === null || e === void 0 ? void 0 : e.code) === 'readonly') {
      removeSessionId(this.groupId);
      window.location.assign(removeQueryArgs(window.location.href, 'order'));
      return;
    }
    // something went wrong
    if (e === null || e === void 0 ? void 0 : e.message) {
      this.scError.emit(e);
    }
    // handle curl timeout errors.
    if ((e === null || e === void 0 ? void 0 : e.code) === 'http_request_failed') {
      this.scError.emit({ message: 'Something went wrong. Please reload the page and try again.' });
    }
    this.scSetState.emit('REJECT');
  }
  /** Default data always sent with the session. */
  defaultFormData() {
    var _a;
    return {
      return_url: window.top.location.href,
      currency: ((_a = this.order()) === null || _a === void 0 ? void 0 : _a.currency) || this.currencyCode,
      live_mode: this.mode !== 'test',
      group_key: this.groupId,
    };
  }
  defaultFormQuery() {
    return {
      form_id: this.formId,
    };
  }
  /** Find or create session on load. */
  componentDidLoad() {
    this.findOrCreateOrder();
  }
  /** Find or create an order */
  findOrCreateOrder() {
    var _a, _b, _c;
    // get initial data from the url
    const initial_data = this.getInitialDataFromUrl();
    // remove discount from window.
    if ((_a = initial_data === null || initial_data === void 0 ? void 0 : initial_data.discount) === null || _a === void 0 ? void 0 : _a.promotion_code) {
      window.history.replaceState({}, document.title, removeQueryArgs(window.location.href, 'coupon'));
    }
    // remove line items from window.
    if ((_b = initial_data === null || initial_data === void 0 ? void 0 : initial_data.line_items) === null || _b === void 0 ? void 0 : _b.length) {
      window.history.replaceState({}, document.title, removeQueryArgs(window.location.href, 'line_items'));
    }
    // we have line items, don't load any existing session (overwrite)
    if ((_c = initial_data === null || initial_data === void 0 ? void 0 : initial_data.line_items) === null || _c === void 0 ? void 0 : _c.length) {
      checkouts.clearOrder(this.formId, this.mode);
      return this.fetch(initial_data);
    }
    // check if we have an existing session.
    const id = getSessionId(this.groupId, this.order, this.modified);
    // fetch or initialize a session.
    return id && this.persist ? this.fetch(initial_data) : this.initialize(initial_data);
  }
  getInitialDataFromUrl() {
    let initial_data = {};
    // Coupon code.
    const promotion_code = getURLCoupon();
    initial_data = {
      ...initial_data,
      ...(promotion_code ? { discount: { promotion_code } } : {}),
    };
    // Line items.
    const line_items = getURLLineItems();
    initial_data = {
      ...initial_data,
      ...(line_items && (line_items === null || line_items === void 0 ? void 0 : line_items.length) ? { line_items } : {}),
    };
    return initial_data;
  }
  /** Looks through children and finds items needed for initial session. */
  async initialize(args = {}) {
    let line_items = this.addInitialPrices() || [];
    line_items = this.addPriceChoices(line_items);
    if (line_items === null || line_items === void 0 ? void 0 : line_items.length) {
      return this.loadUpdate({ line_items, ...args });
    }
    else {
      return this.loadUpdate({ ...args });
    }
  }
  /** Add prices that are passed into the component. */
  addInitialPrices() {
    var _a;
    if (!((_a = this === null || this === void 0 ? void 0 : this.prices) === null || _a === void 0 ? void 0 : _a.length))
      return [];
    // check for id
    if (this.prices.some(p => !(p === null || p === void 0 ? void 0 : p.id))) {
      return;
    }
    // add prices that are passed into this component.
    return this.prices.map(price => {
      return {
        price_id: price.id,
        quantity: price.quantity,
      };
    });
  }
  /** Add default prices that may be selected in form. */
  addPriceChoices(line_items = []) {
    const elements = this.el.querySelectorAll('[price-id]');
    elements.forEach(el => {
      // handle price choices.
      if (el.checked) {
        line_items.push({
          quantity: el.quantity || 1,
          price_id: el.priceId,
          ...(el.defaultAmount ? { ad_hoc_amount: el.defaultAmount } : {}),
        });
      }
      // handle donation default amount.
      if (el.defaultAmount) {
        line_items.push({
          quantity: el.quantity || 1,
          price_id: el.priceId,
          ad_hoc_amount: el.defaultAmount,
        });
      }
    });
    return line_items;
  }
  getSessionId() {
    var _a, _b;
    if ((_a = this.order()) === null || _a === void 0 ? void 0 : _a.id) {
      return (_b = this.order()) === null || _b === void 0 ? void 0 : _b.id;
    }
    const id = getSessionId(this.groupId, this.order, this.modified);
    if (this.persist) {
      return id;
    }
  }
  /** Fetch a session. */
  async fetch(args = {}) {
    this.loadUpdate({ status: 'draft', ...args });
  }
  /** Update a session */
  async update(data = {}, query = {}) {
    try {
      const order = (await index$1.createOrUpdateOrder({
        id: this.getSessionId(),
        data: {
          ...this.defaultFormData(),
          ...data,
        },
        query: {
          ...this.defaultFormQuery(),
          ...query,
        },
      }));
      checkouts.setOrder(order, this.formId);
    }
    catch (e) {
      // reinitalize if order not found.
      if (['order.not_found'].includes(e === null || e === void 0 ? void 0 : e.code)) {
        checkouts.clearOrder(this.formId, this.mode);
        return this.initialize();
      }
      console.error(e);
      throw e;
    }
  }
  /** Updates a session with loading status changes. */
  async loadUpdate(data = {}) {
    try {
      this.scSetState.emit('FETCH');
      await this.update({ ...this.defaultFormData(), ...data });
      this.scSetState.emit('RESOLVE');
    }
    catch (e) {
      this.handleErrorResponse(e);
    }
  }
  render() {
    return (index.h("sc-line-items-provider", { order: this.order(), onScUpdateLineItems: e => this.loadUpdate({ line_items: e.detail }) }, index.h("slot", null)));
  }
  get el() { return index.getElement(this); }
  static get watchers() { return {
    "prices": ["handlePricesChange"]
  }; }
};

exports.sc_form_components_validator = ScFormComponentsValidator;
exports.sc_form_error_provider = ScFormErrorProvider;
exports.sc_form_state_provider = ScFormStateProvider;
exports.sc_order_confirm_provider = ScOrderConfirmProvider;
exports.sc_session_provider = ScSessionProvider;
