import { EditorProperty } from "@iplusplus/y-model"
import React, { useCallback, useContext } from "react"
import { DataGrid, DataGridProps, GridColDef, GridRenderEditCellParams, GridRowModel } from "@mui/x-data-grid"
import { Tooltip, Typography } from "@mui/material"
import { EditorContextProps } from "../editor-context/types"
import { PropertyGridValues } from "./types"
import { EditorContext } from "../editor-context/EditorContext"

// function createProcessRowUpdate(onNewValueSubmit: (prop: EditorProperty, newValue: unknown) => void) {
//   return (newRow: GridRowModel, oldRow: GridRowModel) =>
//     new Promise<GridRowModel>((resolve) => {
//       const p = oldRow.v.property as EditorProperty;
//       const v = p.valueType;
//       if (v.dataTypeName === "number") {
//         const newValue = parseFloat(newRow.value);
//         if (isNaN(newValue)) {
//           resolve(oldRow)
//         }
//         else {
//           onNewValueSubmit(p, newValue)
//           resolve({ ...oldRow, value: newValue })
//         }
//       } else {
//         onNewValueSubmit(p, newRow.value)
//         resolve(newRow)

//       }
//     })
// }

function processRowUpdate2(
  onNewValueSubmit: (prop: EditorProperty, newValue: unknown) => void,
  newRow: GridRowModel,
  oldRow: GridRowModel,
) {
  return new Promise<GridRowModel>(resolve => {
    const p = oldRow.v.property as EditorProperty
    const v = p.valueType
    if (v.dataTypeName === "number") {
      const newValue = parseFloat(newRow.value)
      if (isNaN(newValue)) {
        resolve(oldRow)
      } else {
        onNewValueSubmit(p, newValue)
        resolve({ ...oldRow, value: newValue })
      }
    } else {
      onNewValueSubmit(p, newRow.value)
      resolve(newRow)
    }
  })
}

function getColumns(context: EditorContextProps): GridColDef[] {
  const renderEditCell = (params: GridRenderEditCellParams) => {
    // console.log("renderEditCell", params)
    const p = params.row.v.property as EditorProperty
    const render = context.editCellRenderBuilder(p)
    return render!(params)
  }

  const renderCell: GridColDef["renderCell"] = params => {
    // console.log("renderEditCell", params)
    //console.log(params.value)
    const p = params.row.v.property as EditorProperty
    const render = context.cellRenderBuilder(p)
    return render!(params)
  }

  const renderNameCell: GridColDef["renderCell"] = params => {
    // console.log("renderEditCell", params)
    const p = params.row.v.property as EditorProperty

    const descr = p.valueType.getDescription()

    const ele = <Typography variant="body2">{p.title}</Typography>
    if (descr) {
      return <Tooltip title={descr}>{ele}</Tooltip>
    }
    return ele
  }

  return [
    {
      field: "name",
      headerName: "属性名",
      //  width: 180,
      display: "flex",
      flex: 2,
      maxWidth: 200,
      sortable: false,
      renderCell: renderNameCell,
    },
    {
      field: "value",
      headerName: "值",
      type: "string",
      editable: true,
      align: "left",
      headerAlign: "left",
      flex: 3,
      maxWidth: 1200,
      sortable: false,
      renderEditCell,
      renderCell,
    },
  ]
}
export type PropertyGridProps = {
  values: PropertyGridValues
  onNewValueSubmit: (prop: EditorProperty, newValue: unknown) => void
  onEditStateNotify?: (isInEdit: boolean) => void
  disableEditFields?: string[]
}

export const PropertyGrid = React.memo(function ({
  values,
  onNewValueSubmit,
  onEditStateNotify,
  disableEditFields,
}: PropertyGridProps) {
  const processRowUpdate = useCallback(
    (newRow: GridRowModel, oldRow: GridRowModel) => processRowUpdate2(onNewValueSubmit, newRow, oldRow),
    [onNewValueSubmit],
  )
  const rows = values.map(v => {
    return {
      v: v,
      id: v.property.name,
      name: v.property.title,
      value: v.value,
    }
  })

  const editorStateNotify = (isInEdit: boolean) => {
    if (onEditStateNotify) {
      onEditStateNotify(isInEdit)
    }
  }

  const context = useContext(EditorContext)
  const columns = getColumns(context)

  const isCellEditable: DataGridProps["isCellEditable"] = params => {
    return disableEditFields === undefined || disableEditFields.indexOf(params.row.v.property.name as string) === -1
  }

  return (
    <DataGrid
      rows={rows}
      columns={columns}
      hideFooter={true}
      processRowUpdate={processRowUpdate}
      onCellEditStart={() => editorStateNotify(true)}
      onCellEditStop={() => editorStateNotify(false)}
      isCellEditable={isCellEditable}
      density="compact"
      showCellVerticalBorder
    ></DataGrid>
  )
})
