import { isArray } from "lodash";
import React, { createContext, useCallback, useMemo, useState } from "react";

export type ProgressBarUnit = { key: string | null; acting: boolean };

type ProgressBarContextPayload = {
  progress: boolean;
  actions: {
    add: (key: string) => void;
    remove: (key: string) => void;
    observe: (unit?: ProgressBarUnit | ProgressBarUnit[]) => void;
  };
};

const initialContext: ProgressBarContextPayload = {
  progress: false,
  actions: {
    add: () => undefined,
    remove: () => undefined,
    observe: () => undefined
  }
};

const ProgressBarContext = createContext<ProgressBarContextPayload>(initialContext);

type Props = { children: React.ReactNode };
const ProgressBarProvider: React.FC<Props> = ({ children }) => {
  const [network, setNetwork] = useState<string[]>([]);
  const handleAdd = useCallback((key: string) => setNetwork(prev => [...prev, key]), []);
  const handleRemove = useCallback((key: string) => setNetwork(prev => prev.filter(z => z !== key)), []);

  const handleObserve = useCallback(
    (unit?: ProgressBarUnit | ProgressBarUnit[]) => {
      const items: ProgressBarUnit[] = [];

      if (unit) {
        if (isArray(unit)) {
          items.push(...unit);
        } else {
          items.push(unit);
        }
      }

      for (const z of items) {
        if (!z.key) continue;
        if (z.acting) {
          handleAdd(z.key);
        } else {
          handleRemove(z.key);
        }
      }
    },
    [handleAdd, handleRemove]
  );

  const progress = useMemo(() => network.length > 0, [network.length]);
  const payload = useMemo(
    () => ({ progress, actions: { add: handleAdd, remove: handleRemove, observe: handleObserve } }),
    [progress, handleAdd, handleRemove, handleObserve]
  );
  return <ProgressBarContext.Provider value={payload}>{children}</ProgressBarContext.Provider>;
};

export { ProgressBarContext };
export default ProgressBarProvider;
