text: import { change, untouch, reset } from 'redux-form';
  import apex from '../../apex';
  import BigNumber from 'bignumber.js';
  import { getFormValuesForSubmittingOrder } from '../../helpers/placeOrderHelper';
  import {
    buyValue,
    sellValue,
    orderTypes,
  } from '../../constants/sendOrder/orderEntryFormConstants';
  import { MODAL_TYPES, openModal } from './modalActions';
  import { orderFormTypes } from '../../constants/sendOrder/orderFormTypes';
  import {
    syncQuantityWithPrice,
    syncPriceWithQuantity,
  } from '../../helpers/orderHelper';
  import {
    selectedInstrumentSelector,
    selectedInstrumentDecimalPlacesSelector,
  } from '../selectors/instrumentPositionSelectors';
  import { accountIdSelector } from '../selectors/marginSelectors';
  import { truncateToDecimals } from '../../helpers/numberFormatter';
  import { baseCurrencyPriceSelector } from '../selectors/baseCurrenciesSelectors';
  import i18next from 'zipmex-v2/src/i18n';
  
  export const placeOrderWithChecks =
    (orderFormType, form) => async (dispatch, getState) => {
      const { level1, instrument } = getState();
      if (
        form.orderType === orderTypes.limit.displayName &&
        form.side === sellValue
      ) {
        const limitPrice = new BigNumber(form.limitPrice);
        const marketPrice = new BigNumber(
          level1[instrument.selectedInstrumentId.toString()].BestOffer
        );
        if (limitPrice.lt(marketPrice)) {
          return dispatch(
            openModal(MODAL_TYPES.SUBMIT_SELL_LIMIT_ORDER, { orderFormType })
          );
        }
      }
  
      dispatch(placeOrder(orderFormType, form));
    };
  
  export const placeOrder =
    (orderFormType, form) => async (dispatch, getState) => {
      const state = getState();
  
      const selectedAccountId = accountIdSelector(state);
      const {
        user: { userInfo },
        level1,
        level2,
      } = getState();
      const selectedInstrument = selectedInstrumentSelector(getState());
      const decimalPlaces = selectedInstrumentDecimalPlacesSelector(getState());
      const priceDecimalPlaces =
        decimalPlaces[selectedInstrument.Product2Symbol.toString()];
      const options = getFormValuesForSubmittingOrder(orderFormType, {
        state: getState(),
        decimalPlaces,
        instrument: { selectedInstrumentId: selectedInstrument.InstrumentId },
        form,
        userInfo,
        selectedAccountId,
        priceDecimalPlaces,
        level1,
        level2,
      });
      let response;
      if (orderFormType === orderFormTypes.block) {
        response = await apex.connection.SubmitBlockTrade(options);
      } else {
        response = await apex.connection.SendOrder(options);
      }
  
      //GTM TRACKING CODE
      if (response.status === 'Accepted') {
        try {
          window.dataLayer.push(
            {
              event: 'order.placed',
              'order.placed': {
                details: {
                  value: form.price,
                  currency: selectedInstrument.Product2Symbol,
                  orderId: response.OrderId,
                },
              },
            },
            {
              event: 'trade.complete',
            }
          );
        } catch {
          console.log('Error in GTM tracking');
        }
      }
      //END GTM TRACKING CODE
  
      return response;
    };
  
  export const buyPriceClicked = (price) => (dispatch, getState) => {
    const selectedOrderType = getState().form.orderEntry.values.orderType;
    const isStopOrder = selectedOrderType === orderTypes.stopMarket.displayName;
  
    dispatch(clearFeeAndTotalAmountValues('buyForm'));
    dispatch(clearFeeAndTotalAmountValues('sellForm'));
  
    if (!isStopOrder) {
      dispatch(checkAndSwitchToLimitOrderType());
    }
  
    dispatch(change('buyForm', isStopOrder ? 'stopPrice' : 'limitPrice', price));
    dispatch(change('sellForm', isStopOrder ? 'stopPrice' : 'limitPrice', price));
    onLimitPriceChange(price)(dispatch, getState);
    dispatch(change('orderEntry', 'side', sellValue));
  };
  
  export const onLimitPriceChange = (value, formName) => (dispatch, getState) => {
    const state = getState();
    const { form } = state;
    const { decimalPlaces } = state.product;
    const selectedInstrument = selectedInstrumentSelector(state);
    let baseProduct =
      baseCurrencyPriceSelector(state, selectedInstrument.Product2) || {};
    if (!baseProduct.value) {
      baseProduct = {
        value: 1,
        Product: selectedInstrument.Product2Symbol,
      };
    }
    const forms = [
      { name: 'buyForm', form: form.buyForm },
      { name: 'sellForm', form: form.sellForm },
    ];
  
    const updateValues = (name, form) => {
      dispatch(
        change(
          name,
          'basePrice',
          truncateToDecimals(
            value * baseProduct.value,
            decimalPlaces[baseProduct.Product]
          )
        )
      );
      dispatch(
        change(
          name,
          'orderTotal',
          truncateToDecimals(
            value * form.values.quantity,
            decimalPlaces[selectedInstrument.Product2Symbol]
          )
        )
      );
    };
    if (formName) {
      updateValues(formName, form[formName]);
    } else {
      forms.forEach(({ name, form }) => {
        updateValues(name, form);
      });
    }
  };
  
  export const buyQuantityClicked = (quantity, index, buy) => (dispatch) => {
    dispatch(clearFeeAndTotalAmountValues('orderEntry'));
    const overalQuantity = calculateQuantity(quantity, buy, index);
    dispatch(change('buyForm', 'quantity', overalQuantity));
    dispatch(change('sellForm', 'quantity', overalQuantity));
    dispatch(change('orderEntry', 'orderType', orderTypes.market.displayName));
  };
  
  export const sellPriceClicked = (price) => (dispatch, getState) => {
    const selectedOrderType = getState().form.orderEntry.values.orderType;
    const isStopOrder = selectedOrderType === orderTypes.stopMarket.displayName;
  
    dispatch(clearFeeAndTotalAmountValues('buyForm'));
    dispatch(clearFeeAndTotalAmountValues('sellForm'));
  
    if (!isStopOrder) {
      dispatch(checkAndSwitchToLimitOrderType());
    }
  
    dispatch(change('buyForm', isStopOrder ? 'stopPrice' : 'limitPrice', price));
    dispatch(change('sellForm', isStopOrder ? 'stopPrice' : 'limitPrice', price));
    onLimitPriceChange(price)(dispatch, getState);
    dispatch(change('orderEntry', 'side', buyValue));
  };
  
  export const sellQuantityClicked = (quantity, index, sell) => (dispatch) => {
    dispatch(clearFeeAndTotalAmountValues('orderEntry'));
    const overalQuantity = calculateQuantity(quantity, sell, index, false);
    dispatch(change('buyForm', 'quantity', overalQuantity));
    dispatch(change('sellForm', 'quantity', overalQuantity));
    dispatch(change('orderEntry', 'side', buyValue));
    dispatch(change('orderEntry', 'orderType', orderTypes.market.displayName));
  };
  
  export const clearOrderForm = (formName) => (dispatch) => {
    dispatch(clearFeeAndTotalAmountValues(formName));
    dispatch(reset(formName));
  };
  
  export const clearBuySellForm = () => (dispatch) => {
    const form = 'buySell';
    dispatch(clearField(form, 'quantity', ''));
    dispatch(clearField(form, 'price', ''));
    dispatch(clearField(form, 'amountRadio', 'custom'));
    dispatch(clearField(form, 'limitPrice', ''));
    dispatch(clearField(form, 'fee', '0'));
    dispatch(clearField(form, 'responseMessage', ''));
  };
  
  export const showBuySellSuccessMessage = () => (dispatch) => {
    dispatch(
      change(
        'buySell',
        'responseMessage',
        i18next.extractT('Your order was filled successfully!')
      )
    );
  };
  
  export const showBuySellFailMessage = () => (dispatch) => {
    dispatch(
      change(
        'buySell',
        'responseMessage',
        i18next.extractT('Your order failed, please try again')
      )
    );
  };
  
  export const synchronizeQuantityWithPrice =
    (price, form, field, formObj) => (dispatch, getState) => {
      const state = getState();
      const { side } = formObj.values;
      const selectedInstrument = selectedInstrumentSelector(state);
      let quantity;
  
      const { level2 } = state;
  
      const decimalPlaces = selectedInstrumentDecimalPlacesSelector(state);
  
      quantity = syncQuantityWithPrice(price, {
        level2,
        selectedInstrument,
        side,
        decimalPlaces,
      });
  
      dispatch(change(form, field, quantity));
    };
  
  export const synchronizePriceWithQuantity =
    (quantity, form, field, formObj) => (dispatch, getState) => {
      const state = getState();
      const { side } = formObj.values;
      const selectedInstrument = selectedInstrumentSelector(state);
      let price;
  
      const {
        level2,
        product: { decimalPlaces },
      } = state;
      price = syncPriceWithQuantity(quantity, {
        level2,
        selectedInstrument,
        side,
        decimalPlaces,
      });
  
      dispatch(change(form, field, price));
    };
  
  const calculateQuantity = (initValue, orders, quantityIndex, buy = true) => {
    const init = new BigNumber(initValue);
  
    const quantity = orders
      .filter((data, index) =>
        buy ? index < quantityIndex : index > quantityIndex
      )
      .reduce((prev, current) => prev.plus(current.Quantity), init);
  
    return quantity.toString();
  };
  
  /**
   * Switch order type to 'Limit' if 'Market' is selected before
   */
  const checkAndSwitchToLimitOrderType = () => (dispatch, getState) => {
    const selectedOrderType = getState().form.orderEntry.values.orderType;
  
    if (selectedOrderType === orderTypes.market.displayName) {
      dispatch(change('orderEntry', 'orderType', orderTypes.limit.displayName));
    }
  };
  
  const clearFeeAndTotalAmountValues = (form) => (dispatch) => {
    dispatch(clearField(form, 'fee', '0'));
    dispatch(clearField(form, 'totalAmount', '0'));
  };
  
  const clearField = (form, field, initialValue) => (dispatch) => {
    dispatch(change(form, field, initialValue));
    dispatch(untouch(form, field));
  };
  