import { createEffect, createMemo, createSignal } from "solid-js";
import ValidatedTextInput from "../modules/validated-text-input.jsx";
import EventEmitter from "../tools/event-emitter.js";
import ModalHandler from "./modal-handler.js";
import Modal from "./modal.jsx";
import RemotesService from "../services/remotes-service.js";
import Command from "../data/command.js";

const eventEmitter = new EventEmitter();
const COMMAND_CREATED_EVENT = "success";
const MIN_TITLE_LENGTH = 3;

function CreateCommandModal(props) {
  const [protocol, setProtocol] = createSignal("");
  const [commandNumber, setCommandNumber] = createSignal("");
  const [device, setDevice] = createSignal("");
  const [commandType, setCommandType] = createSignal("");
  const [title, setTitle] = createSignal("");
  const [error, setError] = createSignal("");

  const isProtocolValid = createMemo(() => protocol() !== "");
  const isCommandNumberValid = createMemo(
    () => commandNumber() !== "" && !isNaN(commandNumber())
  );
  const isDeviceValid = createMemo(() => device() !== "" && !isNaN(device()));
  const isCommandTypeValid = createMemo(() => commandType() !== "");
  const isTitleValid = createMemo(() => title().length >= MIN_TITLE_LENGTH);

  createEffect(() => {
    let commandString = commandType() ? Command.CommandTypes[commandType()] : "";
    let protocolString = protocol() ? Command.Protocols[protocol()] : "";
    setTitle(commandString + " " + protocolString);
  });

  const isFormValid = createMemo(
    () =>
      isProtocolValid() &&
      isCommandNumberValid() &&
      isDeviceValid() &&
      isCommandTypeValid() &&
      isTitleValid()
  );

  async function handleCreateCommand() {
    let command;
    try {
      command = await RemotesService.createCommand({
        protocol: protocol(),
        commandNumber: commandNumber(),
        device: device(),
        commandType: commandType(),
        title: title(),
      });
    } catch (e) {
      setError(e.message);
      return;
    }
    resetFields();
    CreateCommandModal.Handler.hide();
    eventEmitter.dispatchEvent(COMMAND_CREATED_EVENT, command);
  }

  function resetFields() {
    setProtocol("");
    setCommandNumber("");
    setDevice("");
    setCommandType("");
    setTitle("");
    setError("");
  }

  return (
    <Modal
      ref={props.ref}
      id="createCommandModal"
      modalTitle="New Command"
      centered={true}
    >
      <div class="modal-body" style="overflow-y:inherit !important;">
        <Show when={error() !== ""}>
          <div class="alert alert-danger" role="alert">
            {error()}
          </div>
        </Show>
        <div class="mb-3 row">
          <label for="new_command_protocol" class="col-form-label col-sm-3">
            Protocol
          </label>
          <div class="col-sm-9">
            <div class="btn-group">
              <button
                type="button"
                class="btn btn-secondary dropdown-toggle"
                data-bs-toggle="dropdown"
                aria-expanded="false"
              >
                {protocol() ? Command.Protocols[protocol()] : "Please select"}
              </button>
              <ul
                class="dropdown-menu"
                style="max-height: 10em; overflow-y: auto;"
              >
                {Object.keys(Command.Protocols).map((protocol) => (
                  <li>
                    <a
                      class="dropdown-item pe-auto"
                      onClick={() => setProtocol(protocol)}
                    >
                      {Command.Protocols[protocol]}
                    </a>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>
        <div class="mb-3 row">
          <label for="new_command_number" class="col-form-label col-sm-3">
            Command Number
          </label>
          <ValidatedTextInput
            class="col-sm-9"
            id="new_command_number"
            valid={isCommandNumberValid()}
            value={commandNumber()}
            onInput={(e) => setCommandNumber(e.target.value)}
            errorText={"Command number must be a number"}
          />
        </div>
        <div class="mb-3 row">
          <label
            for="new_command_device_number"
            class="col-form-label col-sm-3"
          >
            Device Number
          </label>
          <ValidatedTextInput
            class="col-sm-9"
            id="new_command_device_number"
            valid={isDeviceValid()}
            value={device()}
            onInput={(e) => setDevice(e.target.value)}
            errorText={"Device number must be a number"}
          />
        </div>
        <div class="mb-3 row">
          <label for="new_command_protocol" class="col-form-label col-sm-3">
            Command Type
          </label>
          <div class="col-sm-9">
            <div class="btn-group">
              <button
                type="button"
                class="btn btn-secondary dropdown-toggle"
                data-bs-toggle="dropdown"
                aria-expanded="false"
              >
                {commandType()
                  ? Command.CommandTypes[commandType()]
                  : "Please select"}
              </button>
              <ul
                class="dropdown-menu"
                style="max-height: 10em; overflow-y: auto;"
              >
                {Object.keys(Command.CommandTypes).map((commandType) => (
                  <li>
                    <a
                      class="dropdown-item pe-auto"
                      onClick={() => setCommandType(commandType)}
                    >
                      {Command.CommandTypes[commandType]}
                    </a>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>
        <div class="mb-3 row">
          <label for="new_command_title" class="col-form-label col-sm-3">
            Title
          </label>
          <ValidatedTextInput
            class="col-sm-9"
            id="new_command_title"
            valid={isTitleValid()}
            value={title()}
            onInput={(e) => setTitle(e.target.value)}
            errorText={`Title must be at least ${MIN_TITLE_LENGTH} characters long`}
          />
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          Cancel
        </button>
        <button
          type="button"
          onClick={handleCreateCommand}
          class="btn btn-primary"
          disabled={!isFormValid()}
        >
          Create
        </button>
      </div>
    </Modal>
  );
}

CreateCommandModal.Handler = new ModalHandler();
CreateCommandModal.onCommandCreated = (callback) =>
  eventEmitter.on(COMMAND_CREATED_EVENT, callback);

export default CreateCommandModal;
