import {
  expose,
  Renderer,
  Metadata,
  ExposerEvent,
} from '@aptpod/data-viz-visual-parts-sdk'
import React from 'react'
import { createRoot, Root } from 'react-dom/client'

// Shadow DOM に適用するStyle
import { StyledShadowStyle } from '../../../styles/shadow'
// Styled Components を Shadow DOM 以下で適用するための Utility
import { StyleSheetManagerWrapper } from '../../../utils/components/style/stylesheet-manager-wrapper'
// React Profiler から描画処理に要した時間を取得するための Utility
import { ReactProfilerWrapper } from '../../../utils/components/profiler/react-profiler-wrapper'

import { BIND_DATA_COUNT_MAX } from './constant'
import { HorizontalBarsContainer } from './container'
import { EXTENSION_CONFIGS, defaultExtension } from './extension'
import thumbnailSrc from 'src/assets/images/samples/horizontal-bars/thumbnail.svg'

/**
 * Metadata 作成
 */
const metadata: Metadata = {
  partsType: '@sample/horizontal-bars',
  partsName: 'Horizontal Bars',
  groupName: 'Sample',
  panelTagName: 'x-sample-horizontal-bars',
  getThumbnailURL: (baseURL: string) => `${baseURL}${thumbnailSrc}`,
  panelViewConfig: {
    displayTitleWhenMouseOver: true,
    displayTimestamp: true,
  },
  panelOptionConfig: {
    rangeAtMost: BIND_DATA_COUNT_MAX,
    canEditColor: false,
    bindDataCountMax: BIND_DATA_COUNT_MAX,
    extensionConfigs: EXTENSION_CONFIGS,
  },
  defaultExtension,
}

/**
 * Renderer クラスを継承したPluginRendererを定義します。
 */
class PluginRenderer extends Renderer {
  private root: Root | undefined

  /**
   * 描画を実行します。 1回だけコールします。
   * 状態を変更する場合は、 ExposerEvent のイベントを利用し、 element のDOMを再描画します。
   */
  render(el: HTMLElement, comm: ExposerEvent) {
    this.root = createRoot(el)
    this.root.render(
      <StyleSheetManagerWrapper>
        {/* comm.renderingProfile は Data Visualizer v3.3.0 以降で利用可能です。 */}
        <ReactProfilerWrapper onProfile={comm.renderingProfile?.emit}>
          <>
            <StyledShadowStyle />
            <HorizontalBarsContainer comm={comm} />
          </>
        </ReactProfilerWrapper>
      </StyleSheetManagerWrapper>,
    )
  }
  /**
   * render メソッドで指定した element に紐づく子要素のDOMや子要素のイベントハンドラを解放します。
   *
   * ※ 引数の _el は React v18 に更新したことで、引数 el は使用しなくなりましたが、互換性を維持するため引数の定義は現状維持となっています。
   */
  dispose(_el: HTMLElement) {
    this.root?.unmount()
    this.root = undefined
  }
}

/**
 * 作成した metadata, renderer を公開します。
 */
expose({
  metadata,
  renderer: PluginRenderer,
})
