import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
  Box,
  Grid,
  Dialog,
  Typography,
  Paper,
  ListItemButton,
  ListItemText,
  ListItemAvatar,
  useTheme,
  CircularProgress,
  LinearProgress,
  IconButton,
  Tooltip,
  type LinearProgressProps,
  styled,
} from '@mui/material';
import {
  DataGrid,
  type GridColumnVisibilityModel,
  GridPagination,
  type GridPaginationModel,
  type GridColDef,
  type GridValidRowModel,
  GridSlotsComponent,
} from '@mui/x-data-grid';
import currencyDict from '../../../static/assets/currencies.json';
import { type PublicOrder } from '../../models';
import { filterOrders, hexToRgb, statusBadgeColor, pn, amountToString } from '../../utils';
import BookControl from './BookControl';

import { FlagWithProps } from '../Icons';
import { PaymentStringAsIcons } from '../PaymentMethods';
import RobotAvatar from '../RobotAvatar';

// Icons
import { Fullscreen, FullscreenExit, Refresh } from '@mui/icons-material';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
import headerStyleFix from '../DataGrid/HeaderFix';

const ClickThroughDataGrid = styled(DataGrid)({
  '& .MuiDataGrid-overlayWrapperInner': {
    pointerEvents: 'none',
  },
  ...{ headerStyleFix },
});

const premiumColor = function (baseColor: string, accentColor: string, point: number): string {
  const baseRGB = hexToRgb(baseColor);
  const accentRGB = hexToRgb(accentColor);
  const redDiff = accentRGB[0] - baseRGB[0];
  const red = Number(baseRGB[0]) + redDiff * point;
  const greenDiff = accentRGB[1] - baseRGB[1];
  const green = Number(baseRGB[1]) + greenDiff * point;
  const blueDiff = accentRGB[2] - baseRGB[2];
  const blue = Number(baseRGB[2]) + blueDiff * point;
  return `rgb(${Math.round(red)}, ${Math.round(green)}, ${Math.round(blue)}, ${0.7 + point * 0.3})`;
};

interface BookTableProps {
  orderList?: PublicOrder[];
  maxWidth: number;
  maxHeight: number;
  fullWidth?: number;
  fullHeight?: number;
  elevation?: number;
  defaultFullscreen?: boolean;
  fillContainer?: boolean;
  showControls?: boolean;
  showFooter?: boolean;
  showNoResults?: boolean;
  onOrderClicked?: (id: number, shortAlias: string) => void;
}

const BookTable = ({
  orderList,
  maxWidth = 100,
  maxHeight = 70,
  fullWidth = 100,
  fullHeight = 70,
  defaultFullscreen = false,
  elevation = 6,
  fillContainer = false,
  showControls = true,
  showFooter = true,
  showNoResults = true,
  onOrderClicked = () => null,
}: BookTableProps): JSX.Element => {
  const { fav, setOpen } = useContext<UseAppStoreType>(AppContext);
  const { federation, coordinatorUpdatedAt } =
    useContext<UseFederationStoreType>(FederationContext);

  const { t } = useTranslation();
  const theme = useTheme();
  const orders = orderList ?? federation.book;

  const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
    pageSize: 0,
    page: 0,
  });
  const [columnVisibilityModel, setColumnVisibilityModel] = useState<GridColumnVisibilityModel>({});
  const [fullscreen, setFullscreen] = useState(defaultFullscreen);
  const [paymentMethods, setPaymentMethods] = useState<string[]>([]);

  // all sizes in 'em'
  const [fontSize, defaultPageSize, height] = useMemo(() => {
    const fontSize = theme.typography.fontSize;
    const verticalHeightFrame = 3.25 + (showControls ? 3.7 : 0.35) + (showFooter ? 2.35 : 0);
    const verticalHeightRow = 3.25;
    const defaultPageSize = Math.max(
      Math.floor(
        ((fullscreen ? fullHeight * 0.9 : maxHeight) - verticalHeightFrame) / verticalHeightRow,
      ),
      1,
    );
    const height = defaultPageSize * verticalHeightRow + verticalHeightFrame;
    return [fontSize, defaultPageSize, height];
  }, [theme.typography.fontSize, maxHeight, fullscreen, fullHeight, showControls, showFooter]);

  useEffect(() => {
    setPaginationModel({
      pageSize: federation.loading && orders.length === 0 ? 0 : defaultPageSize,
      page: paginationModel.page,
    });
  }, [coordinatorUpdatedAt, orders, defaultPageSize]);

  const localeText = useMemo(() => {
    return {
      MuiTablePagination: { labelRowsPerPage: t('Orders per page:') },
      noResultsOverlayLabel: t('No results found.'),
      errorOverlayDefaultLabel: t('An error occurred.'),
      toolbarColumns: t('Columns'),
      toolbarColumnsLabel: t('Select columns'),
      columnsPanelTextFieldLabel: t('Find column'),
      columnsPanelTextFieldPlaceholder: t('Column title'),
      columnsPanelDragIconLabel: t('Reorder column'),
      columnsPanelShowAllButton: t('Show all'),
      columnsPanelHideAllButton: t('Hide all'),
      filterPanelAddFilter: t('Add filter'),
      filterPanelDeleteIconLabel: t('Delete'),
      filterPanelLinkOperator: t('Logic operator'),
      filterPanelOperators: t('Operator'),
      filterPanelOperatorAnd: t('And'),
      filterPanelOperatorOr: t('Or'),
      filterPanelColumns: t('Columns'),
      filterPanelInputLabel: t('Value'),
      filterPanelInputPlaceholder: t('Filter value'),
      filterOperatorContains: t('contains'),
      filterOperatorEquals: t('equals'),
      filterOperatorStartsWith: t('starts with'),
      filterOperatorEndsWith: t('ends with'),
      filterOperatorIs: t('is'),
      filterOperatorNot: t('is not'),
      filterOperatorAfter: t('is after'),
      filterOperatorOnOrAfter: t('is on or after'),
      filterOperatorBefore: t('is before'),
      filterOperatorOnOrBefore: t('is on or before'),
      filterOperatorIsEmpty: t('is empty'),
      filterOperatorIsNotEmpty: t('is not empty'),
      filterOperatorIsAnyOf: t('is any of'),
      filterValueAny: t('any'),
      filterValueTrue: t('true'),
      filterValueFalse: t('false'),
      columnMenuLabel: t('Menu'),
      columnMenuShowColumns: t('Show columns'),
      columnMenuManageColumns: t('Manage columns'),
      columnMenuFilter: t('Filter'),
      columnMenuHideColumn: t('Hide'),
      columnMenuUnsort: t('Unsort'),
      columnMenuSortAsc: t('Sort by ASC'),
      columnMenuSortDesc: t('Sort by DESC'),
      columnHeaderFiltersLabel: t('Show filters'),
      columnHeaderSortIconLabel: t('Sort'),
      booleanCellTrueLabel: t('yes'),
      booleanCellFalseLabel: t('no'),
    };
  }, []);

  const robotObj = useCallback((width: number) => {
    return {
      field: 'maker_nick',
      headerName: t('Robot'),
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <ListItemButton
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            <ListItemAvatar sx={{ position: 'relative', left: '-1.3em', bottom: '0.6em' }}>
              <RobotAvatar
                hashId={params.row.maker_hash_id}
                style={{ width: '3.215em', height: '3.215em' }}
                smooth={true}
                flipHorizontally={true}
                orderType={params.row.type}
                statusColor={statusBadgeColor(params.row.maker_status)}
                tooltip={t(params.row.maker_status)}
                small={true}
              />
            </ListItemAvatar>
            <ListItemText
              primary={params.row.maker_nick}
              sx={{ position: 'relative', left: '-1.3em', bottom: '0.6em' }}
            />
          </ListItemButton>
        );
      },
    };
  }, []);

  const robotSmallObj = useCallback((width: number) => {
    return {
      field: 'maker_nick',
      headerName: t('Robot'),
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <div
            style={{ position: 'relative', left: '-0.34em', cursor: 'pointer', bottom: '0.2em' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            <RobotAvatar
              hashId={params.row.maker_hash_id}
              smooth={true}
              flipHorizontally={true}
              style={{ width: '3.215em', height: '3.215em' }}
              orderType={params.row.type}
              statusColor={statusBadgeColor(params.row.maker_status)}
              tooltip={t(params.row.maker_status)}
            />
          </div>
        );
      },
    };
  }, []);

  const onClickCoordinator = function (shortAlias: string): void {
    setOpen((open) => {
      return { ...open, coordinator: shortAlias };
    });
  };

  const coordinatorObj = useCallback((width: number) => {
    return {
      field: 'coordinatorShortAlias',
      headerName: t('Host'),
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <ListItemButton
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onClickCoordinator(params.row.coordinatorShortAlias);
            }}
          >
            <ListItemAvatar sx={{ position: 'relative', left: '-1.54em', bottom: '0.4em' }}>
              <RobotAvatar
                shortAlias={params.row.coordinatorShortAlias}
                style={{ width: '3.215em', height: '3.215em' }}
                smooth={true}
                small={true}
              />
            </ListItemAvatar>
          </ListItemButton>
        );
      },
    };
  }, []);

  const typeObj = useCallback(
    (width: number) => {
      return {
        field: 'type',
        headerName: t('Is'),
        width: width * fontSize,
        renderCell: (params: any) => {
          return (
            <div
              style={{ cursor: 'pointer' }}
              onClick={() => {
                onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
              }}
            >
              {params.row.type === 1
                ? t(fav.mode === 'fiat' ? 'Seller' : 'Swapping Out')
                : t(fav.mode === 'fiat' ? 'Buyer' : 'Swapping In')}
            </div>
          );
        },
      };
    },
    [fav.mode],
  );

  const amountObj = useCallback(
    (width: number) => {
      return {
        field: 'amount',
        headerName: t('Amount'),
        type: 'number',
        width: width * fontSize,
        renderCell: (params: any) => {
          const amount = fav.mode === 'swap' ? params.row.amount * 100 : params.row.amount;
          const minAmount =
            fav.mode === 'swap' ? params.row.min_amount * 100 : params.row.min_amount;
          const maxAmount =
            fav.mode === 'swap' ? params.row.max_amount * 100 : params.row.max_amount;
          return (
            <div
              style={{ cursor: 'pointer' }}
              onClick={() => {
                onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
              }}
            >
              {amountToString(amount, params.row.has_range, minAmount, maxAmount) +
                (fav.mode === 'swap' ? 'M Sats' : '')}
            </div>
          );
        },
      };
    },
    [fav.mode],
  );

  const currencyObj = useCallback((width: number) => {
    return {
      field: 'currency',
      headerName: t('Currency'),
      width: width * fontSize,
      renderCell: (params: any) => {
        const currencyCode = String(currencyDict[params.row.currency.toString()]);
        return (
          <div
            style={{
              cursor: 'pointer',
              display: 'flex',
              alignItems: 'center',
              flexWrap: 'wrap',
            }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            {currencyCode}
            <div style={{ position: 'relative', left: '0.3em', bottom: '0.7em' }}>
              <FlagWithProps code={currencyCode} />
            </div>
          </div>
        );
      },
    };
  }, []);

  const paymentObj = useCallback(
    (width: number) => {
      return {
        field: 'payment_method',
        headerName: fav.mode === 'fiat' ? t('Payment Method') : t('Destination'),
        width: width * fontSize,
        renderCell: (params: any) => {
          return (
            <div
              style={{ cursor: 'pointer' }}
              onClick={() => {
                onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
              }}
            >
              <div style={{ position: 'relative', top: '0.4em' }}>
                <PaymentStringAsIcons
                  othersText={t('Others')}
                  verbose={true}
                  size={1.7 * fontSize}
                  text={params.row.payment_method}
                />
              </div>
            </div>
          );
        },
      };
    },
    [fav.mode],
  );

  const paymentSmallObj = useCallback((width: number) => {
    return {
      field: 'payment_method',
      headerName: t('Pay'),
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <div
            style={{
              position: 'relative',
              left: '-0.25em',
              top: '0.3em',
              cursor: 'pointer',
            }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            <PaymentStringAsIcons
              othersText={t('Others')}
              size={1.3 * fontSize}
              text={params.row.payment_method}
            />
          </div>
        );
      },
    };
  }, []);

  const priceObj = useCallback((width: number) => {
    return {
      field: 'price',
      headerName: t('Price'),
      type: 'number',
      width: width * fontSize,
      renderCell: (params: any) => {
        const currencyCode = String(currencyDict[params.row.currency.toString()]);
        return (
          <div
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            {`${pn(params.row.price)} ${currencyCode}/BTC`}
          </div>
        );
      },
    };
  }, []);

  const premiumObj = useCallback(
    (width: number) => {
      // coloring premium texts based on 4 params:
      // Hardcoded: a sell order at 0% is an outstanding premium
      // Hardcoded: a buy order at 10% is an outstanding premium
      const sellStandardPremium = 10;
      const buyOutstandingPremium = 10;
      return {
        field: 'premium',
        headerName: t('Premium'),
        type: 'number',
        width: width * fontSize,
        renderCell: (params: any) => {
          const currencyCode = String(currencyDict[params.row.currency.toString()]);
          let fontColor = `rgb(0,0,0)`;
          let premiumPoint = 0;
          if (params.row.type === 0) {
            premiumPoint = params.row.premium / buyOutstandingPremium;
            premiumPoint = premiumPoint < 0 ? 0 : premiumPoint > 1 ? 1 : premiumPoint;
            fontColor = premiumColor(
              theme.palette.text.primary,
              theme.palette.secondary.dark,
              premiumPoint,
            );
          } else {
            premiumPoint = (sellStandardPremium - params.row.premium) / sellStandardPremium;
            premiumPoint = premiumPoint < 0 ? 0 : premiumPoint > 1 ? 1 : premiumPoint;
            fontColor = premiumColor(
              theme.palette.text.primary,
              theme.palette.primary.dark,
              premiumPoint,
            );
          }
          const fontWeight = 400 + Math.round(premiumPoint * 5) * 100;
          return (
            <Tooltip
              placement='left'
              enterTouchDelay={0}
              title={`${pn(params.row.price)} ${currencyCode}/BTC`}
            >
              <div
                style={{ cursor: 'pointer' }}
                onClick={() => {
                  onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
                }}
              >
                <Typography variant='inherit' color={fontColor} sx={{ fontWeight }}>
                  {`${parseFloat(parseFloat(params.row.premium).toFixed(4))}%`}
                </Typography>
              </div>
            </Tooltip>
          );
        },
      };
    },
    [theme],
  );

  const timerObj = useCallback((width: number) => {
    return {
      field: 'escrow_duration',
      headerName: t('Timer'),
      type: 'number',
      width: width * fontSize,
      renderCell: (params: any) => {
        const hours = Math.round(params.row.escrow_duration / 3600);
        const minutes = Math.round((params.row.escrow_duration - hours * 3600) / 60);
        return (
          <div
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            {hours > 0 ? `${hours}h` : `${minutes}m`}
          </div>
        );
      },
    };
  }, []);

  const expiryObj = useCallback((width: number) => {
    return {
      field: 'expires_at',
      headerName: t('Expiry'),
      type: 'string',
      width: width * fontSize,
      renderCell: (params: any) => {
        const expiresAt: Date = new Date(params.row.expires_at);
        const timeToExpiry: number = Math.abs(expiresAt - new Date());
        const percent = Math.round((timeToExpiry / (24 * 60 * 60 * 1000)) * 100);
        const hours = Math.round(timeToExpiry / (3600 * 1000));
        const minutes = Math.round((timeToExpiry - hours * (3600 * 1000)) / 60000);
        return (
          <Box
            sx={{ position: 'relative', display: 'inline-flex', left: '0.3em', top: '0.5em' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            <CircularProgress
              value={percent}
              color={percent < 15 ? 'error' : percent < 30 ? 'warning' : 'success'}
              thickness={0.35 * fontSize}
              size={2.5 * fontSize}
              variant='determinate'
            />
            <Box
              sx={{
                top: 0,
                left: 0,
                bottom: 0,
                right: 0,
                position: 'absolute',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <Typography variant='caption' component='div' color='text.secondary'>
                {hours > 0 ? `${hours}h` : `${minutes}m`}
              </Typography>
            </Box>
          </Box>
        );
      },
    };
  }, []);

  const satoshisObj = useCallback((width: number) => {
    return {
      field: 'satoshis_now',
      headerName: t('Sats now'),
      type: 'number',
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <div
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            {params.row.satoshis_now > 1000000
              ? `${pn(Math.round(params.row.satoshis_now / 10000) / 100)} M`
              : `${pn(Math.round(params.row.satoshis_now / 1000))} K`}
          </div>
        );
      },
    };
  }, []);

  const idObj = useCallback((width: number) => {
    return {
      field: 'id',
      headerName: 'Order ID',
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <div
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >
            <Typography variant='caption' color='text.secondary'>
              {`#${String(params.row.id)}`}
            </Typography>
          </div>
        );
      },
    };
  }, []);

  const bondObj = useCallback((width: number) => {
    return {
      field: 'bond_size',
      headerName: t('Bond'),
      type: 'number',
      width: width * fontSize,
      renderCell: (params: any) => {
        return (
          <div
            style={{ cursor: 'pointer' }}
            onClick={() => {
              onOrderClicked(params.row.id, params.row.coordinatorShortAlias);
            }}
          >{`${Number(params.row.bond_size)}%`}</div>
        );
      },
    };
  }, []);

  const columnSpecs = useMemo(() => {
    return {
      amount: {
        priority: 1,
        order: 5,
        normal: {
          width: fav.mode === 'swap' ? 9.5 : 6.5,
          object: amountObj,
        },
      },
      currency: {
        priority: 2,
        order: 6,
        normal: {
          width: fav.mode === 'swap' ? 0 : 5.9,
          object: currencyObj,
        },
      },
      premium: {
        priority: 3,
        order: 12,
        normal: {
          width: 6,
          object: premiumObj,
        },
      },
      payment_method: {
        priority: 4,
        order: 7,
        normal: {
          width: 12.85,
          object: paymentObj,
        },
        small: {
          width: 4.4,
          object: paymentSmallObj,
        },
      },
      maker_nick: {
        priority: 5,
        order: 1,
        normal: {
          width: 17.14,
          object: robotObj,
        },
        small: {
          width: 4.1,
          object: robotSmallObj,
        },
      },
      coordinatorShortAlias: {
        priority: 5,
        order: 3,
        normal: {
          width: 4.1,
          object: coordinatorObj,
        },
      },
      price: {
        priority: 6,
        order: 11,
        normal: {
          width: 10,
          object: priceObj,
        },
      },
      expires_at: {
        priority: 7,
        order: 8,
        normal: {
          width: 5,
          object: expiryObj,
        },
      },
      escrow_duration: {
        priority: 8,
        order: 9,
        normal: {
          width: 4.8,
          object: timerObj,
        },
      },
      satoshis_now: {
        priority: 9,
        order: 10,
        normal: {
          width: 6,
          object: satoshisObj,
        },
      },
      type: {
        priority: 10,
        order: 2,
        normal: {
          width: fav.mode === 'swap' ? 7 : 4.3,
          object: typeObj,
        },
      },
      bond_size: {
        priority: 11,
        order: 11,
        normal: {
          width: 4.2,
          object: bondObj,
        },
      },
      id: {
        priority: 12,
        order: 13,
        normal: {
          width: 4.8,
          object: idObj,
        },
      },
    };
  }, [fav.mode]);

  const filteredColumns = function (maxWidth: number): {
    columns: Array<GridColDef<GridValidRowModel>>;
    width: number;
  } {
    const useSmall = maxWidth < 70;
    const selectedColumns: object[] = [];
    const columnVisibilityModel: GridColumnVisibilityModel = {};
    let width: number = 0;

    for (const [key, value] of Object.entries(columnSpecs)) {
      // do not use col currency on swaps
      if (fav.mode === 'swap' && key === 'currency') {
        continue;
      }

      const colWidth = Number(
        useSmall && Boolean(value.small) ? value.small.width : value.normal.width,
      );
      const colObject = useSmall && Boolean(value.small) ? value.small.object : value.normal.object;

      if (width + colWidth < maxWidth || selectedColumns.length < 2) {
        width = width + colWidth;
        selectedColumns.push([colObject(colWidth), value.order]);
        columnVisibilityModel[key] = true;
      } else {
        selectedColumns.push([colObject(colWidth), value.order]);
        columnVisibilityModel[key] = false;
      }
    }

    // sort columns by column.order value
    selectedColumns.sort(function (first, second) {
      return first[1] - second[1];
    });

    const columns: Array<GridColDef<GridValidRowModel>> = selectedColumns.map(function (item) {
      return item[0];
    });

    setColumnVisibilityModel(columnVisibilityModel);
    return { columns, width: width * 0.875 + 0.15 };
  };

  const { columns, width } = useMemo(() => {
    return filteredColumns(fullscreen ? fullWidth : maxWidth);
  }, [maxWidth, fullscreen, fullWidth, fav.mode]);

  const Footer = function (): JSX.Element {
    return (
      <Grid container alignItems='center' direction='row' justifyContent='space-between'>
        <Grid item>
          <Grid container alignItems='center' direction='row'>
            <Grid item xs={6}>
              <IconButton
                onClick={() => {
                  setFullscreen(!fullscreen);
                }}
              >
                {fullscreen ? <FullscreenExit /> : <Fullscreen />}
              </IconButton>
            </Grid>
            <Grid item xs={6}>
              <IconButton
                onClick={() => {
                  void federation.updateBook();
                }}
              >
                <Refresh />
              </IconButton>
            </Grid>
          </Grid>
        </Grid>

        <Grid item>
          <GridPagination />
        </Grid>
      </Grid>
    );
  };

  interface GridComponentProps {
    LoadingOverlay: (props: LinearProgressProps) => JSX.Element;
    NoResultsOverlay?: (props: any) => JSX.Element;
    NoRowsOverlay?: (props: any) => JSX.Element;
    Footer?: (props: any) => JSX.Element;
    Toolbar?: (props: any) => JSX.Element;
  }

  const NoResultsOverlay = function (): JSX.Element {
    return (
      <Grid
        container
        direction='column'
        justifyContent='center'
        alignItems='center'
        sx={{ width: '100%', height: '100%' }}
      >
        <Grid item>
          <Typography align='center' component='h5' variant='h5'>
            {fav.type === 0
              ? t('No orders found to sell BTC for {{currencyCode}}', {
                  currencyCode:
                    fav.currency === 0 ? t('ANY') : currencyDict[fav.currency.toString()],
                })
              : t('No orders found to buy BTC for {{currencyCode}}', {
                  currencyCode:
                    fav.currency === 0 ? t('ANY') : currencyDict[fav.currency.toString()],
                })}
          </Typography>
        </Grid>
        <Grid item>
          <Typography align='center' color='primary' variant='h6'>
            {t('Be the first one to create an order')}
          </Typography>
        </Grid>
      </Grid>
    );
  };

  const gridComponents = useMemo(() => {
    const components: GridSlotsComponent = {
      loadingOverlay: LinearProgress,
    };

    if (showNoResults) {
      components.noResultsOverlay = NoResultsOverlay;
      components.noRowsOverlay = NoResultsOverlay;
    }
    if (showFooter) {
      components.footer = Footer;
    }
    if (showControls) {
      components.toolbar = BookControl;
    }
    return components;
  }, [showNoResults, showFooter, showControls, fullscreen]);

  const filteredOrders = useMemo(() => {
    return showControls
      ? filterOrders({
          orders,
          baseFilter: fav,
          paymentMethods,
        })
      : orders;
  }, [showControls, orders, fav, paymentMethods]);

  if (!fullscreen) {
    return (
      <Paper
        elevation={elevation}
        style={
          fillContainer
            ? { width: '100%', height: '100%' }
            : { width: `${width}em`, height: `${height}em`, overflow: 'auto' }
        }
      >
        <ClickThroughDataGrid
          localeText={localeText}
          rowHeight={3.714 * theme.typography.fontSize}
          headerHeight={3.25 * theme.typography.fontSize}
          rows={filteredOrders}
          getRowId={(params: PublicOrder) => `${String(params.coordinatorShortAlias)}/${params.id}`}
          loading={federation.loading}
          columns={columns}
          columnVisibilityModel={columnVisibilityModel}
          onColumnVisibilityModelChange={(newColumnVisibilityModel) => {
            setColumnVisibilityModel(newColumnVisibilityModel);
          }}
          hideFooter={!showFooter}
          slots={gridComponents}
          slotProps={{
            toolbar: {
              width,
              paymentMethod: paymentMethods,
              setPaymentMethods,
            },
            loadingOverlay: {
              variant: 'determinate',
              value:
                ((federation.exchange.enabledCoordinators -
                  federation.exchange.loadingCoordinators) /
                  federation.exchange.enabledCoordinators) *
                100,
            },
          }}
          paginationModel={paginationModel}
          pageSizeOptions={width < 22 ? [] : [0, defaultPageSize, defaultPageSize * 2, 50, 100]}
          onPaginationModelChange={(newPaginationModel) => {
            setPaginationModel(newPaginationModel);
          }}
        />
      </Paper>
    );
  } else {
    return (
      <Dialog open={fullscreen} fullScreen={true}>
        <Paper style={{ width: '100%', height: '100%', overflow: 'auto' }}>
          <ClickThroughDataGrid
            localeText={localeText}
            rowHeight={3.714 * theme.typography.fontSize}
            headerHeight={3.25 * theme.typography.fontSize}
            rows={filteredOrders}
            loading={federation.loading}
            columns={columns}
            hideFooter={!showFooter}
            slots={gridComponents}
            columnVisibilityModel={columnVisibilityModel}
            onColumnVisibilityModelChange={(newColumnVisibilityModel) => {
              setColumnVisibilityModel(newColumnVisibilityModel);
            }}
            slotProps={{
              toolbar: {
                width,
                paymentMethod: paymentMethods,
                setPaymentMethods,
              },
            }}
            paginationModel={paginationModel}
            pageSizeOptions={width < 22 ? [] : [0, defaultPageSize, defaultPageSize * 2, 50, 100]}
            onPaginationModelChange={(newPaginationModel) => {
              setPaginationModel(newPaginationModel);
            }}
          />
        </Paper>
      </Dialog>
    );
  }
};

export default BookTable;
