;(() => {
  interface SmetaItem {
    id: string
    name: string
    nameCustom: string
    address: string
    size: number
    type: 'area' | 'line'
    price: number
  }

  interface ObjectTemplate {
    name: string
    type: 'area' | 'line'
  }

  function SmetaEditor (props: {
    template: SmetaItem[]
    onChange: (value: SmetaItem[]) => void
    objects: ObjectTemplate[]
  }) {
    const [template, setTemplate] = window.React.useState(props.template)

    const setItem = (item: SmetaItem) => {
      setTemplate((old) =>
        old.map((f) => {
          if (f.id === item.id) return item
          return f
        })
      )
    }

    const addItem = (item: SmetaItem) => {
      item.id = uuid()
      setTemplate([...template, item])
    }

    const deleteItem = (id: string) => {
      setTemplate(template.filter((t) => t.id !== id))
    }

    window.React.useEffect(() => {
      props.onChange && props.onChange(template)
    }, [template])

    return (
      <>
        <div className="table-responsive">
          <table
            className="table table-striped"
            style={{ margin: 0, minWidth: '940px' }}
          >
            <thead>
              <tr>
                <td style={{ width: '315px' }}>Наименование объекта</td>
                <td style={{ width: '141px' }}>Тип</td>
                <td style={{ width: '340px' }}>Адрес</td>
                <td style={{ width: '150px' }}>Площадь / Протяжённость</td>
                <td></td>
              </tr>
            </thead>
            <tbody>
              {template.map((item, i) => {
                if (!item.id) {
                  item.id = uuid()
                }

                return (
                  <tr key={item.id}>
                    <SmetaItemEditor
                      template={item}
                      onChange={(item) => setItem(item)}
                      objects={props.objects}
                    />
                    <td>
                      {template.length > 1 && (
                        <button
                          type="button"
                          className="btn btn-outline-danger"
                          onClick={(e) => {
                            if (confirm('Удалить объект?')) {
                              deleteItem(item.id)
                            }
                          }}
                        >
                          <i className="bi bi-trash"></i>
                        </button>
                      )}
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        </div>{' '}
        <br />
        <div className="editor__controls">
          <button
            type="button"
            className="btn btn-success"
            onClick={() => addItem({} as SmetaItem)}
          >
            <i className="bi bi-plus"></i> Добавить объект
          </button>
        </div>
      </>
    )
  }

  function SmetaItemEditor (props: {
    template: SmetaItem
    onChange: (template: SmetaItem) => any
    objects: ObjectTemplate[]
  }) {
    const types = {
      area: {
        type: 'area',
        name: 'Здание',
        measure: (
          <>
            м<sup>2</sup>
          </>
        ),
        measureName: 'Площадь'
      },
      line: {
        type: 'line',
        name: 'Линейный',
        measure: 'км',
        measureName: 'Протяжённость'
      }
    }

    const [template, setTemplate] = window.React.useState(
      Object.assign(
        {
          name: props.objects[0].name,
          type: props.objects[0].type
        },
        props.template ?? {}
      )
    )

    const setField = (key: string, value: any) => {
      setTemplate({
        ...template,
        [key]: value
      })
    }

    window.React.useEffect(() => {
      props.onChange && props.onChange(template)
    }, [template])

    return (
      <>
        <td>
          <div
            style={{ display: 'flex', flexDirection: 'column', gap: '10px;' }}
          >
            <select
              className="form-control"
              value={template.name ?? props.objects[0].name}
              onChange={(e) => setField('name', e.target.value)}
            >
              {props.objects.map((object, i) => (
                <>
                  <option value={object.name}>{object.name}</option>
                </>
              ))}
              <option value="">Другое...</option>
            </select>
            {!template.name && (
              <input
                type="text"
                className="form-control"
                value={template.nameCustom}
                onChange={(e) => setField('nameCustom', e.target.value)}
                placeholder="Наименование *"
                required={true}
              />
            )}
          </div>
        </td>
        <td style={{}}>
          {!template.name && (
            <select
              className="form-control"
              value={template.type}
              onChange={(e) => setField('type', e.target.value)}
            >
              {Object.values(types).map((object, i) => (
                <>
                  <option value={object.type}>{object.name}</option>
                </>
              ))}
            </select>
          )}
          <div style={{ padding: '8px 0' }}>
            {template.name && types[template.type].name}
          </div>
        </td>
        <td>
          <input
            type="text"
            className="form-control"
            value={template.address}
            onChange={(e) => setField('address', e.target.value.replace(/^[\t\s]*$/, ''))}
            placeholder="Адрес *"
            required={true}
          />
        </td>
        <td>
          <div className="input-group">
            <input
              type="text"
              className="form-control"
              value={template.size}
              onChange={(e) => {
                setField(
                  'size',
                  e.target.value.replace(/[^\d,.]/, '').replace(',', '.')
                )
              }}
              placeholder={types[template.type].measureName}
              required={true}
            />
            <div className="input-group-addon">
              {types[template.type].measure}
            </div>
          </div>
        </td>
      </>
    )
  }

  const domContainer = document.querySelector('#js-smeta-editor')
  const field = document.querySelector('.js-smeta-form') as
    | HTMLInputElement
    | undefined

  if (domContainer && field) {
    const fieldsStr = domContainer.getAttribute('data-types')
    const types = JSON.parse(fieldsStr || '{}')

    let template = JSON.parse(field.value ?? '[]')
    if (!template) template = {}
    if (typeof template === 'object') template = Object.values(template)

    window.ReactDOM.render(
      <SmetaEditor
        template={template}
        onChange={(value) => {
          field.value = JSON.stringify(value)
        }}
        objects={types}
      />,
      domContainer
    )
  }

  function uuid () {
    return URL.createObjectURL(new Blob([])).slice(-36)
  }
})()
