text: import { createSelector } from 'reselect';
  import { currency } from '../../helpers/numberFormatter';
  import { dateFilter } from '../../helpers/orderHistoryFilters';
  import { formValueSelector } from 'redux-form';
  import { selectedInstrumentSelector } from './instrumentPositionSelectors';
  
  const formSelector = formValueSelector('order-history-filter');
  const isNonEmptyObject = o => Object.keys(o).length > 0;
  let memo = {};
  const meomizedFormSelector = (...args) => {
    const result = formSelector(...args);
    if (JSON.stringify(result) !== JSON.stringify(memo)) {
      memo = result;
      return result;
    }
    return memo;
  };
  
  const openOrdersCurrencySelector = createSelector(
    [
      state => state.orderHistory.openOrders,
      state => state.instrument.instruments,
      state => state.orderHistory.tradeReports
    ],
    convertOrderNumbersToCurrency
  );
  
  const trailingOrdersSelectorFactory = ordersSelector =>
    createSelector(ordersSelector, orders => {
      return orders.map(order => {
        if (
          order.OrderType === 'TrailingStopLimit' ||
          order.OrderType === 'TrailingStopMarket'
        ) {
          return {
            ...order,
            trailingPrice: 'TRL'
          };
        }
  
        return order;
      });
    });
  
  export const openOrdersSelector = createSelector(
    openOrdersCurrencySelector,
    orders => {
      return orders
        .filter(
          order =>
            order.OrderState !== 'FullyExecuted' && order.OrderState === 'Working'
        )
        .sort((a, b) => b.ReceiveTime - a.ReceiveTime);
    }
  );
  
  export const openOrdersSelectorFactory = () =>
    createSelector(
      [
        trailingOrdersSelectorFactory(openOrdersSelector),
        state => state.position.selectedProductId,
        selectedInstrumentSelector,
        state => state.instrument.instruments,
        state => meomizedFormSelector(state, 'startDate', 'endDate'),
        (state, props) => props.filterMode
      ],
      (
        orders,
        selectedProductId,
        selectedInstrument,
        instruments,
        formValues,
        filterMode
      ) => {
        const selectedInstrumentId = selectedInstrument.InstrumentId;
        let filteredOrders = [...orders];
        if (filterMode === 'all') {
          return filteredOrders.filter(isNonEmptyObject);
        } else if (filterMode === 'selectedProduct') {
          if (selectedProductId) {
            filteredOrders = filterOrdersByProductId(
              orders,
              selectedProductId,
              instruments
            );
          }
          if (formValues) {
            filteredOrders = filterOrdersByDate(
              filteredOrders,
              formValues,
              'ReceiveTime'
            );
          }
        } else {
          // else filterMode == 'selectedInstrument'
          return orders.filter(
            order => order.Instrument === selectedInstrumentId
          );
        }
      }
    );
  
  export const buyOpenOrdersSelector = createSelector(
    openOrdersSelectorFactory(),
    orders => {
      return orders.filter(
        order => order.Side === 'Buy' && order.OrderType !== 'BlockTrade'
      );
    }
  );
  
  export const sellOpenOrdersSelector = createSelector(
    openOrdersSelectorFactory(),
    orders => {
      return orders.filter(
        order => order.Side === 'Sell' && order.OrderType !== 'BlockTrade'
      );
    }
  );
  
  const accountTradesCurrencySelector = createSelector(
    [
      state => state,
      state => state.orderHistory.accountTrades,
      state => state.instrument.instruments,
      state => state.product.products,
      state => state.user.accountFees
    ],
    (state, trades, instruments, products, fees) => {
      return trades.map(trade => {
        const instrument = instruments.find(
          item => item.InstrumentId === trade.InstrumentId
        );
        if (!instrument) return {};
        const { Product1Symbol, Product2Symbol } = instrument;
        const quantity = currency(trade.Quantity, Product1Symbol);
        const price = currency(trade.Price, Product2Symbol);
        const symbol = trade.Side === 'Buy' ? Product1Symbol : Product2Symbol;
        const value = currency(trade.Value, symbol);
        const feeProduct = products.find(p => p.ProductId === trade.FeeProductId);
        const fee = currency(trade.Fee, feeProduct?.Product ?? symbol);
  
        return {
          ...trade,
          Quantity: quantity,
          Price: price,
          Value: value,
          Fee: fee
        };
      });
    }
  );
  
  const filledOrdersSelector = createSelector(
    accountTradesCurrencySelector,
    trades =>
      trades
        .sort((a, b) => {
          if (a.TradeTime < b.TradeTime) return 1;
          if (a.TradeTime > b.TradeTime) return -1;
          return 0;
        })
        .filter(trade => !trade.IsBlockTrade)
  );
  
  export const filledOrdersSelectorFactory = () =>
    createSelector(
      [
        trailingOrdersSelectorFactory(filledOrdersSelector),
        state => state.position.selectedProductId,
        selectedInstrumentSelector,
        state => state.instrument.instruments,
        state => meomizedFormSelector(state, 'startDate', 'endDate'),
        (state, props) => props.filterMode
      ],
      (
        orders,
        selectedProductId,
        selectedInstrument,
        instruments,
        formValues,
        filterMode
      ) => {
        const selectedInstrumentId = selectedInstrument.InstrumentId;
        if (filterMode === 'all') {
          return orders.filter(isNonEmptyObject);
        } else if (filterMode === 'selectedProduct') {
          let filteredOrders = orders;
          if (selectedProductId) {
            filteredOrders = filterOrdersByProductId(
              orders,
              selectedProductId,
              instruments
            );
          }
          return filterOrdersByDate(filteredOrders, formValues, 'TradeTimeMS');
        } else {
          // else filterMode == 'selectedInstrument'
          return orders.filter(
            order => order.InstrumentId === selectedInstrumentId
          );
        }
      }
    );
  
  const inactiveOrdersCurrencySelector = createSelector(
    [
      state => state.orderHistory.inactiveOrders,
      state => state.instrument.instruments
    ],
    convertOrderNumbersToCurrency
  );
  
  const inactiveOrdersSelector = createSelector(
    inactiveOrdersCurrencySelector,
    orders => {
      return orders
        .filter(
          order =>
            order.OrderState !== 'FullyExecuted' && order.OrderState !== 'Working'
        )
        .sort((a, b) => b.ReceiveTime - a.ReceiveTime);
    }
  );
  
  export const inactiveOrdersSelectorFactory = () =>
    createSelector(
      [
        trailingOrdersSelectorFactory(inactiveOrdersSelector),
        state => state.position.selectedProductId,
        selectedInstrumentSelector,
        state => state.instrument.instruments,
        state => meomizedFormSelector(state, 'startDate', 'endDate'),
        (state, props) => props.filterMode
      ],
      (
        orders,
        selectedProductId,
        selectedInstrument,
        instruments,
        formValues,
        filterMode
      ) => {
        const selectedInstrumentId = selectedInstrument.InstrumentId;
        if (filterMode === 'selectedProduct') {
          let filteredOrders = orders;
          if (selectedProductId) {
            filteredOrders = filterOrdersByProductId(
              orders,
              selectedProductId,
              instruments
            );
          }
          return filterOrdersByDate(filteredOrders, formValues, 'ReceiveTime');
        } else {
          // else filterMode == 'selectedInstrument'
          return orders.filter(
            order => order.Instrument === selectedInstrumentId
          );
        }
      }
    );
  
  function convertOrderNumbersToCurrency(orders, instruments, tradeReports = []) {
    const allOrders = [...orders, ...tradeReports];
  
    return allOrders.map(order => {
      const instrument = instruments.find(
        item => item.InstrumentId === order.Instrument
      );
  
      if (!instrument) {
        return order;
      }
  
      const { Product1Symbol, Product2Symbol } = instrument;
      const quantity = currency(order.Quantity, Product1Symbol);
      const origQuantity = currency(order.OrigQuantity, Product1Symbol);
      const price = currency(order.Price, Product2Symbol);
  
      return {
        ...order,
        quantity,
        OrigQuantity: origQuantity,
        Price: price
      };
    });
  }
  
  const tradeReportsCurrecnySelector = createSelector(
    [
      state => state.orderHistory.tradeReports,
      state => state.instrument.instruments
    ],
    (tradeReports, instruments) => {
      const trades = tradeReports.filter(order => order.OrderState !== 'Working');
      trades.map(order => {
        const instrument = instruments.find(
          item => item.InstrumentId === order.InstrumentId || order.Instrument
        );
        const { Product1Symbol, Product2Symbol } = instrument;
        const quantity = currency(order.Quantity, Product1Symbol);
        const price = currency(order.Price, Product2Symbol);
        const symbol = order.Side === 'Buy' ? Product1Symbol : Product2Symbol;
        const fee = currency(order.Fee, symbol);
  
        return {
          ...order,
          Quantity: quantity,
          Price: price,
          Fee: fee
        };
      });
  
      return trades;
    }
  );
  
  const tradeReportsSelector = createSelector(
    [tradeReportsCurrecnySelector, accountTradesCurrencySelector],
    (tradeReports, accountTrades) => {
      const blockTrades = accountTrades.filter(trade => trade.IsBlockTrade);
  
      return tradeReports
        .concat(blockTrades)
        .map(order => ({
          ...order,
          SortingTime: order.ReceiveTimeTicks
            ? order.ReceiveTimeTicks
            : order.TradeTime
        }))
        .sort((a, b) => {
          if (a.SortingTime < b.SortingTime) return 1;
          if (a.SortingTime > b.SortingTime) return -1;
          return 0;
        });
    }
  );
  
  export const tradeReportsSelectorFactory = () =>
    createSelector(
      [
        trailingOrdersSelectorFactory(tradeReportsSelector),
        state => state.position.selectedProductId,
        selectedInstrumentSelector,
        state => state.instrument.instruments,
        state => meomizedFormSelector(state, 'startDate', 'endDate'),
        (state, props) => props.filterMode
      ],
      (
        orders,
        selectedProductId,
        selectedInstrument,
        instruments,
        formValues,
        filterMode
      ) => {
        const selectedInstrumentId = selectedInstrument.InstrumentId;
        if (filterMode === 'selectedProduct') {
          let filteredOrders = orders;
          if (selectedProductId) {
            filteredOrders = filterOrdersByProductId(
              orders,
              selectedProductId,
              instruments
            );
          }
          return filterOrdersByDate(filteredOrders, formValues, 'TradeTimeMS');
        } else {
          // else filterMode == 'selectedInstrument'
          return orders.filter(
            order =>
              order.InstrumentId === selectedInstrumentId ||
              order.Instrument === selectedInstrumentId
          );
        }
      }
    );
  
  function filterOrdersByProductId(orders, selectedProductId, instruments) {
    const ordersWithProductIds = orders.map(order => {
      const instrument = instruments.find(
        item =>
          item.InstrumentId === order.Instrument ||
          item.InstrumentId === order.InstrumentId
      );
  
      return {
        ...order,
        product1Id: instrument?.Product1 ?? null,
        product2Id: instrument?.Product2 ?? null
      };
    });
  
    return ordersWithProductIds.filter(
      order =>
        order.product1Id === selectedProductId ||
        order.product2Id === selectedProductId
    );
  }
  
  export function filterPositionsByProductId(
    positions,
    selectedProductId,
    instruments
  ) {
    const ordersWithProductIds = positions.map(position => {
      const instrument = instruments.find(
        item =>
          item.InstrumentId === position.InstrumentId ||
          item.InstrumentId === position.InstrumentId
      );
  
      return {
        ...position,
        product1Id: instrument?.Product1 ?? null,
        product2Id: instrument?.Product2 ?? null
      };
    });
  
    return ordersWithProductIds.filter(
      position =>
        position.product1Id === selectedProductId ||
        position.product2Id === selectedProductId
    );
  }
  
  function filterOrdersByDate(orders, formValues, timeStamp) {
    return orders.filter(item =>
      dateFilter(item, formValues.startDate, formValues.endDate, timeStamp)
    );
  }
  