import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import {
  ChecklistEditor,
  EditorPktEl,
  MediaEditor,
  PktEl,
  PktExternalEditor,
  PktListEditor,
  PktTimeEditor,
  PktGpsEditor,
  PktLovibondEditor,
  SignatureEditor,
} from './PktEl';
import { FormEditorState } from './reducer';
import {
  FormEditorAction,
  loadPktJson,
  loadEmptyForm,
  toggleEditMode,
  toggleDebugInfo,
  toggleTimeControl,
  savePkt,
  Path,
} from './types';
import { bindActionCreators, Dispatch, Store } from 'redux';
import PktElWithActions from './PktElWithActions';
import SpinnerEl from './SpinnerEl';
import TextField from './TextField';
import CloseIcon from '@mui/icons-material/Close';
import PreviewIcon from '@mui/icons-material/Pageview';
import EditIcon from '@mui/icons-material/Edit';
import SaveIcon from '@mui/icons-material/Save';
import ShowDebugInfoIcon from '@mui/icons-material/Visibility';
import HideDebugInfoIcon from '@mui/icons-material/VisibilityOff';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';
import Tooltip from '@mui/material/Tooltip';
// The store is directly imported in order to access it in 'beforeunload'
import { store } from './index';
import TimeControlModal from './TimeControlModel';
import { setTime } from '~t/DataPage/editTimeDialogSlice';

type FormEditorProps = ReturnType<typeof mapDispatchToProps> &
  ReturnType<typeof mapStateToProps> & {
    openedPktFile?: PktEl;
    pktName?: string;
    pktId?: number;
  };

const blueIconButtonStyle = {
  backgroundColor: 'rgb(0,123,255)',
  color: 'white',
  '&:hover': {
    backgroundColor: 'rgb(0,105,217)',
  },
  padding: '6px 12px 6px 12px'
};

const greyIconButtonStyle = {
  backgroundColor: 'rgb(108,117,125)',
  color: 'white',
  '&:hover': {
    backgroundColor: 'rgb(91,98,104)',
  },
  padding: '6px 12px 6px 12px'
};

const FormEditor: React.FC<FormEditorProps> = (props) => {
  const {
    state,
    loadPktJson,
    loadEmptyForm,
    toggleEditMode,
    toggleDebugInfo,
    savePkt,
  } = props;
  const { isEditMode, topLevelEl, saveStatus, showDebugInfo } = state;

  //create a state to show the popup to control the time
  const [EditTime, setEditTime] = useState(false);
  useEffect(() => {
    // if the prop loadedPktJson is defined, import it; otherwise load an empty form.
    // The empty form is not loaded by default, because that would lead to flickering
    // when the page is loaded.
    if (props.openedPktFile && props.pktName && props.pktId) {
      loadPktJson(props.openedPktFile, props.pktName, props.pktId);
    } else {
      loadEmptyForm();
    }

    // Register a listener to prevent accidentally leaving the page with unsaved
    // changes.
    window.onbeforeunload = function (event) {
      const theStore = store as any as Store<FormEditorState>;
      const unsavedChanges =
        theStore.getState().saveStatus.state === 'unsavedChanges';
      if (unsavedChanges) {
        return (
          'It looks like there are unsaved changes to the PKT. ' +
          'If you leave before saving, your changes will be lost.'
        );
      } else {
        return undefined;
      }
    };
  }, []);

  function onClickSave() {
    let name: string;
    if (state.pktName) {
      name = state.pktName;
    } else {
      name = prompt('Please enter a name for this PKT.');
      if (name === '' || name === null) {
        alert('Please enter a non-empty name.');
        return;
      }
    }
    const pktJson = exportJson(topLevelEl);
    savePkt(name, pktJson);
  }

  const setTime = (timeControlConfig) => {
    topLevelEl['time'] = timeControlConfig;
  };

  return !state.loaded ? (
    <div />
  ) : (
    <div style={{ margin: '1rem' }} id='form-control'>
      <div
        style={{
          display: 'flex',
          flexDirection: 'row',
          position: 'relative',
        }}
      >
        {showDebugInfo && (
          <div
            className='debug-pane'
            style={{
              flexGrow: showDebugInfo ? 1 : 0,
              flexShrink: 1,
            }}
          >
            <div className='debug-info-buttons'></div>
            {JSON.stringify(exportJson(topLevelEl), null, 2)}
          </div>
        )}

        <div
          className={
            isEditMode
              ? 'pkt-top-level edit-mode'
              : 'pkt-top-level preview-mode'
          }
          style={{ flexGrow: 1, flexShrink: 0, position: 'relative' }}
        >
          <div className='top-level-el'>
            <span className='pkt-name'>
              {state.pktName ? (
                <>
                  Name: <strong>{state.pktName}</strong>
                </>
              ) : (
                'New PKT'
              )}
            </span>
            <PktElWithActions el={topLevelEl} path={[]} />
          </div>
        </div>

        <div className='top-level-buttons'>
          <Stack spacing={1}>
            <Tooltip placement='left' title='Close'>
              <Button id='closeButton' title='close' href='/system/forms' sx={blueIconButtonStyle}>
                <CloseIcon />
              </Button>
            </Tooltip>
            <Tooltip placement='left' title={isEditMode ? 'Preview' : 'Edit'}>
              <Button id='toggleEditModeButton' title='Toggle edit mode' onClick={toggleEditMode} sx={blueIconButtonStyle}>
                {isEditMode ? <PreviewIcon /> : <EditIcon />}
              </Button>
            </Tooltip>
            <Tooltip placement='left' title={showDebugInfo ? 'Hide debug info' : 'Show debug info'}>
              <Button id='toggleDebugInfoButton' title={showDebugInfo ? 'Hide debug info' : 'Show debug info'}
                      onClick={toggleDebugInfo} sx={greyIconButtonStyle}>
                {showDebugInfo ? <HideDebugInfoIcon /> : <ShowDebugInfoIcon />}
              </Button>
            </Tooltip>
            {/** */}

            {/** */}
            <Tooltip placement='left' title='Save'>
              <Button id='saveButton' title='Save' onClick={onClickSave} sx={blueIconButtonStyle}>
                <SaveIcon />
              </Button>
            </Tooltip>
          {saveStatus.state !== 'unmodified' && (
            <div className='save-status'>
              {saveStateText(saveStatus.state)}
              {saveStatus.state === 'error' && (
                <span className='save-status-tooltip'>
                  Error: {saveStatus.error.request.responseText}
                </span>
              )}
            </div>
          )}
          </Stack>
        </div>
      </div>
    </div>
  );
};
function saveStateText(saveState: FormEditorState['saveStatus']['state']) {
  switch (saveState) {
    case 'error':
      return 'Error';
    case 'saved':
      return 'Saved';
    case 'saving':
      return 'Saving';
    case 'unmodified':
      return 'Unmodified';
    case 'unsavedChanges':
      return 'Modified';
  }
}
// Remove 'uuid' and 'editing' props from all elements in the tree
function exportJson(el: EditorPktEl): PktEl {
  switch (el.typ) {
    case 'form': {
      const { uuid, editing, items, tmp, ...newEl } = el;
      return {
        ...newEl,
        items: (items ?? []).map(exportJson),
        tmp: (tmp ?? []).map(exportJson),
      };
    }
    case 'spin':
    case 'chk': {
      const { uuid, editing, items, ...newEl } = el;
      return {
        ...newEl,
        items: items.map((item) => {
          {
            // Remove the uuid from each spinner item
            const { uuid, ...newItem } = item;
            return newItem;
          }
        }),
      };
    }
    default: {
      const { uuid, editing, ...newEl } = el;
      return newEl;
    }
  }
}

type MediaElProps = {
  el: MediaEditor;
  path: Path;
  children: React.ReactNode;
};

export const MediaEl: React.FC<MediaElProps> = (props) => {
  const { el, children } = props;
  return (
    <div className='pkt-el pkt-media'>
      {children && <div className='children'>{children}</div>}
      <input type='file' />
    </div>
  );
};

type SignatureElProps = {
  el: SignatureEditor;
  path: Path;
  children: React.ReactNode;
};

export const SignatureEl: React.FC<SignatureElProps> = (props) => {
  const { el, children } = props;
  return (
    <div className='pkt-el pkt-signature'>
      {children && <div className='children'>{children}</div>}
      <div>(Signatur)</div>
    </div>
  );
};

type ExternalElProps = {
  el: PktExternalEditor;
  path: Path;
  children: React.ReactNode;
};

export const ExternalEl: React.FC<ExternalElProps> = (props) => {
  const { el, children } = props;
  return (
    <div className='pkt-el pkt-external'>
      {children && <div className='children'>{children}</div>}
      <div>(External)</div>
    </div>
  );
};

type TimeElProps = {
  el: PktTimeEditor;
  path: Path;
  children: React.ReactNode;
};

export const TimeEl: React.FC<TimeElProps> = (props) => {
  const { el, children } = props;
  return (
    <div className='pkt-el pkt-time'>
      {children && <div className='children'>{children}</div>}
      <TextField
        label={el.editing ? 'Uhrzeit' : ''}
        validate={() => true}
        setValue={() => {}}
        currentValue='HH:MM'
        disabled={true}
      />
    </div>
  );
};

type GpsElProps = {
  el: PktGpsEditor;
  path: Path;
  children: React.ReactNode;
};
type LovibondElProps = {
  el: PktLovibondEditor;
  path: Path;
  children: React.ReactNode;
};

export const GpsEl: React.FC<GpsElProps> = (props) => {
  const { el, children } = props;
  // el["gps"]="ellop";
  return (
    <div className='pkt-el pkt-time'>
      {children && <div className='children'>{children}</div>}
      {/* <TextField
        label={el.editing ? 'Location' : ''}
        validate={() => true}
        setValue={() => {}}
        currentValue={el["gps"] !== "" ? el["gps"] : "empty"}
        disabled={true}
      /> */}
    </div>
  );
};
export const LovibondEl: React.FC<LovibondElProps> = (props) => {
  const { el, children } = props;
  // el["gps"]="ellop";
  return (
    <div className='pkt-el pkt-time'>
      {children && <div className='children'>{children}</div>}
      {/* <TextField
        label={el.editing ? 'Location' : ''}
        validate={() => true}
        setValue={() => {}}
        currentValue={el["gps"] !== "" ? el["gps"] : "empty"}
        disabled={true}
      /> */}
    </div>
  );
};

type ChecklistElProps = {
  setElementState: (el: SpinnerEditor | ChecklistEditor) => void;
  el: ChecklistEditor;
  path: Path;
  children: React.ReactNode;
};

export const ChecklistEl: React.FC<ChecklistElProps> = (props) => {
  const { el, children, path, setElementState } = props;
  return (
    <SpinnerEl
      el={el}
      children={children}
      path={path}
      setElementState={setElementState}
      previewElement={
        <ul className='checklist-preview'>
          {el.items.map((item) => {
            const inputId = 'checkbox-id-' + item.uuid;
            return (
              <li>
                <input
                  id={inputId}
                  type='checkbox'
                  checked={false}
                  disabled={true}
                />
                <label
                  className={item.required ? 'required-asterisk' : ''}
                  htmlFor={inputId}
                >
                  {item.text}
                </label>
              </li>
            );
          })}
        </ul>
      }
    />
  );
};

const mapStateToProps = (state: FormEditorState) => {
  return { state };
};

const mapDispatchToProps = (dispatch: Dispatch<FormEditorAction>) =>
  bindActionCreators(
    {
      loadPktJson,
      loadEmptyForm,
      toggleEditMode,
      toggleDebugInfo,
      savePkt,
    },
    dispatch
  );

export default connect(mapStateToProps, mapDispatchToProps)(FormEditor);
