import { memo, useMemo } from "react"
import { CommApi, Control, ControlData, ControlFactory, CreateJsDesignerContext, DesignerContextProps } from "../types"
import { ImgManager } from "./ImgManager"
import { EmptyControl } from "../internal-controls/EmptyControl"
import { groupControlFactory } from "../internal-controls/GroupControl"
import { containerControlFactory } from "../internal-controls/ContainerControl"

export type CreateJsDesignerConfig = {
  getImageBlob: (imageId: string) => Promise<Blob>
  controlFactories: ControlFactory[]
}

export const CreateJsDesignerProvider = memo(
  ({ config, children }: { config: CreateJsDesignerConfig; children: JSX.Element | JSX.Element[] }) => {
    const props = useMemo(() => buildDesignerContextProps(config), [config])

    return <CreateJsDesignerContext.Provider value={props}>{children}</CreateJsDesignerContext.Provider>
  },
)

const internalControlFactories: ControlFactory[] = [
  groupControlFactory,
  containerControlFactory
]

function buildDesignerContextProps(config: CreateJsDesignerConfig): DesignerContextProps {
  const controlTypeDict: {
    [index: string]: ControlFactory
  } = {}
  internalControlFactories.forEach(f => (controlTypeDict[f.typeName] = f))
  config.controlFactories.forEach(f => (controlTypeDict[f.typeName] = f))

  const { getImg } = new ImgManager(config.getImageBlob)
  const createControl = (args: string | ControlData): Control => {
    const controlType = typeof args === "string" ? args : args.controlType
    const controlData = typeof args === "string" ? undefined : args
    const factory = controlTypeDict[controlType]
    if (factory) {
      return factory.create(controlData)
    } else {
      return new EmptyControl()
    }
  }
  const commApi: CommApi = {
    getImg,
    createControl,
  }
  return {
    getCommApi: () => commApi,
  }
}
