import React, { createContext, useMemo } from 'react';

const ScreenContext = createContext<{
  getComponentData?: () => void;
  emitCallback?: () => void;
  isDefaultHide?: boolean;
  emitEvent?: () => void;
  switchPanelState?: (id: number) => void;
  updateConfig?: () => void;
  updateAction?: () => void;
  updateData?: () => void;
  updateTrigger?: () => void;
  tenantId?: number;
}>({});
const PanelDataContext = createContext<{
  panelsById?: {
    [x: number]: any;
  };
}>({});

const DataContainerContext = createContext<{
  dataFilterResult?: {
    [x: number]: any;
  };
}>({});

const ScreenDataContext = createContext<{
  screensById?: {
    [x: number]: any;
  };
}>({});

const ComponentDataContext = createContext<{
  componentsById?: {
    [x: number]: any;
  };
}>({});
const PanelStateContext = createContext({});
const FilterDataContext = createContext<{
  filters?: any[];
}>({});
const CallbackContext = createContext<{
  callbackKeys?: any;
  callbackValues?: any;
}>({});
const InteractionContext = createContext<{
  interactions?: any[];
}>({});
const LoadingContext = createContext({});
const DraggableContext = createContext<{ focusLayers?: any }>({});

function DraggableProvider({ focusLayers, ...props }) {
  const value = useMemo(() => {
    return {
      focusLayers,
    };
  }, [focusLayers]);
  return <DraggableContext.Provider value={value} {...props} />;
}

function DataContainerProvider({ dataFilterResult, ...props }) {
  const value = useMemo(() => {
    return {
      dataFilterResult,
    };
  }, [dataFilterResult]);
  return <DataContainerContext.Provider value={value} {...props} />;
}

function ScreenProvider({
  getComponentData,
  emitCallback,
  emitEvent,
  switchPanelState,
  updateConfig,
  updateAction,
  updateData,
  updateTrigger,
  tenantId,
  isDefaultHide,
  ...props
}: {
  [x: string]: any;
}) {
  const value = useMemo(() => {
    return {
      getComponentData,
      emitCallback,
      emitEvent,
      switchPanelState,
      updateConfig,
      updateAction,
      updateData,
      updateTrigger,
      tenantId,
      isDefaultHide,
    };
  }, [tenantId, isDefaultHide]);

  return <ScreenContext.Provider value={value} {...props} />;
}

function PanelDataProvider({ panelsById, ...props }) {
  const value = useMemo(() => {
    return {
      panelsById,
    };
  }, [panelsById]);

  return <PanelDataContext.Provider value={value} {...props} />;
}

function ScreenDataProvider({ screensById, ...props }) {
  const value = useMemo(() => {
    return {
      screensById,
    };
  }, [screensById]);

  return <ScreenDataContext.Provider value={value} {...props} />;
}

function ComponentDataProvider({ componentsById, ...props }) {
  const value = useMemo(() => {
    return {
      componentsById,
    };
  }, [componentsById]);

  return <ComponentDataContext.Provider value={value} {...props} />;
}

function PanelStateProvider({ panelsStateById, ...props }) {
  const value = useMemo(() => {
    return {
      panelsStateById,
    };
  }, [panelsStateById]);

  return <PanelStateContext.Provider value={value} {...props} />;
}

function FilterDataProvider({ filters, ...props }) {
  const value = useMemo(() => {
    return {
      filters,
    };
  }, [filters]);

  return <FilterDataContext.Provider value={value} {...props} />;
}

function CallbackProvider({ callbackValues, callbackKeys, ...props }) {
  const value = useMemo(() => {
    return {
      callbackValues,
      callbackKeys,
    };
  }, [callbackKeys, callbackValues]);

  return <CallbackContext.Provider value={value} {...props} />;
}

function InteractionProvider({ interactions, ...props }) {
  const value = useMemo(() => {
    return {
      interactions,
    };
  }, [interactions]);

  return <InteractionContext.Provider value={value} {...props} />;
}

function LoadingProvider({ finish, ...props }) {
  return <LoadingContext.Provider value={finish} {...props} />;
}

export {
  ScreenContext,
  ScreenProvider,
  PanelDataContext,
  PanelDataProvider,
  ScreenDataContext,
  ScreenDataProvider,
  ComponentDataContext,
  ComponentDataProvider,
  PanelStateContext,
  PanelStateProvider,
  FilterDataContext,
  FilterDataProvider,
  DataContainerContext,
  DataContainerProvider,
  CallbackContext,
  CallbackProvider,
  InteractionContext,
  InteractionProvider,
  LoadingContext,
  LoadingProvider,
  DraggableContext,
  DraggableProvider,
};
