import React, { useEffect, useRef, useState } from "react";
import {
  Row,
  Col,
  ButtonGroup,
  Button,
  Modal,
  ModalHeader,
  ModalBody,
  ModalFooter,
  Input,
} from "reactstrap";

import dayjs from "core/date";

import s from "./Calendar.module.scss";
import Widget from "../../../components/Widget";

import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin, { Draggable } from "@fullcalendar/interaction";

const Calendar = () => {
  const fullCalendarRef = useRef(null);
  const externalEventsRef = useRef(null);

  const [state, setComponentState] = useState(() => {
    const date = new Date();
    const d = date.getDate();
    const m = date.getMonth();
    const y = date.getFullYear();

    return {
      event: {},
      modal: false,
      modalEvent: false,
      calendarView: "dayGridMonth",
      currentMonth: dayjs().format("MMM YYYY"),
      currentDay: dayjs().format("dddd"),
      calendarOptions: {
        headerToolbar: {
          left: "",
          center: "title",
          right: "",
        },
        events: [
          {
            title: "All Day Event",
            start: new Date(y, m, 1),
            color: "#F45722",
            textColor: "#fff",
            description: "Will be busy throughout the whole day",
          },
          {
            title: "Long Event",
            start: new Date(y, m, d + 5),
            end: new Date(y, m, d + 7),
            color: "#58D777",
            textColor: "#f4f4f5",
            description: "This conference should be worse visiting",
          },
          {
            id: 999,
            title: "Blah Blah Car",
            start: new Date(y, m, d - 3, 16, 0),
            allDay: false,
            color: "#f0af03",
            textColor: "#f4f4f5",
            description: "Agree with this guy on arrival time",
          },
          {
            id: 1000,
            title: "Buy this template",
            start: new Date(y, m, d + 3, 12, 0),
            allDay: false,
            color: "#4ebfbb",
            textColor: "#f4f4f5",
            description: "Make sure everything is consistent first",
          },
          {
            title: "Got to school",
            start: new Date(y, m, d + 16, 12, 0),
            end: new Date(y, m, d + 16, 13, 0),
            color: "#64bd63",
            textColor: "#fff",
            description: "Time to go back",
          },
          {
            title: "Study some Node",
            start: new Date(y, m, d + 18, 12, 0),
            end: new Date(y, m, d + 18, 13, 0),
            color: "#79A5F0",
            textColor: "#fff",
            description:
              "Node.js is a platform built " +
              "on Chrome's JavaScript runtime for easily" +
              " building fast, scalable network applications." +
              " Node.js uses an event-driven, non-blocking" +
              " I/O model that makes it lightweight and" +
              " efficient, perfect for data-intensive real-time" +
              " applications that run across distributed devices.",
          },
          {
            title: "Click for Flatlogic",
            start: new Date(y, m, 28),
            end: new Date(y, m, 29),
            url: "http://flatlogic.com/",
            backgroundColor: "#e5603b",
            textColor: "#fff",
            description: "Creative solutions",
          },
        ],
        selectable: true,
        selectHelper: true,
        editable: true,
        droppable: true,
      },
      calendarPlugins: [
        dayGridPlugin,
        timeGridPlugin,
        interactionPlugin,
        listPlugin,
      ],
      dragOptions: { zIndex: 999, revert: true, revertDuration: 0 },
    };
  });

  const setState = (value) => {
    if (typeof value === "function") {
      setComponentState((prevState) => ({
        ...prevState,
        ...value(prevState),
      }));
      return;
    }

    setComponentState((prevState) => ({
      ...prevState,
      ...value,
    }));
  };

  const getCalendarApi = () => {
    return fullCalendarRef.current && fullCalendarRef.current.getApi();
  };

  useEffect(() => {
    if (!externalEventsRef.current) {
      return undefined;
    }

    const draggable = new Draggable(externalEventsRef.current, {
      itemSelector: ".external-event",
    });

    return () => {
      if (typeof draggable.destroy === "function") {
        draggable.destroy();
      }
    };
  }, []);

  const drop = (info) => {
    info.draggedEl.parentNode.removeChild(info.draggedEl);
  };

  const handleChange = (e) => {
    setState({ event: { ...state.event, title: e.target.value } });
  };

  const toggleModal = () => {
    setState({ modal: !state.modal });
  };

  const toggleModalEvent = () => {
    setState({ modalEvent: !state.modalEvent });
  };

  const createEvent = () => {
    const api = getCalendarApi();
    if (!api) {
      return;
    }

    api.addEvent(state.event);
    api.unselect();
    toggleModal();
  };

  const select = ({ start, end, allDay }) => {
    setState({
      event: {
        start,
        end,
        allDay,
        backgroundColor: "#64bd63",
        textColor: "#fff",
        editable: true,
      },
    });
    toggleModal();
  };

  const eventClick = (e) => {
    setState({ event: e.event });
    toggleModalEvent();
  };

  const prev = () => {
    const api = getCalendarApi();
    if (api) {
      api.prev();
    }
  };

  const next = () => {
    const api = getCalendarApi();
    if (api) {
      api.next();
    }
  };

  const today = () => {
    const api = getCalendarApi();
    if (api) {
      api.today();
    }
  };

  const changeView = (view) => {
    setState({ calendarView: view });
    const api = getCalendarApi();
    if (api) {
      api.changeView(view);
    }
  };

  const getFormattedDate = (date) => {
    return dayjs(date).format("YYYY-MM-DD");
  };

  const {
    event,
    currentMonth,
    currentDay,
    calendarOptions,
    modal,
    modalEvent,
    calendarView,
    calendarPlugins,
  } = state;

  return (
    <div className={s.root}>
      <Row>
        <Col lg={4} xs={12} md={6}>
          <h1 className="page-title">
            {currentMonth} -{" "}
            <span className="fw-semi-bold">{currentDay}</span>
          </h1>
          <h3>
            Draggable <span className="fw-semi-bold">Events</span>
          </h3>
          <p>
            Just drap and drop events from there directly into the calendar.
          </p>
          <div
            ref={externalEventsRef}
            className="calendar-external-events mb-lg"
          >
            <div
              data-event='{ "classNames": ["bg-success", "text-white"], "title": "Make a tea" }'
              className="external-event draggable"
            >
              <div className={s.customExternalEvent}>
                <i className="fa fa-circle fa-fw text-success ms-1 me-2" />
                Make a tea
              </div>
            </div>
            <div
              data-event='{ "classNames": ["bg-warning", "text-white"], "title": "Open windows" }'
              className="external-event draggable"
            >
              <div className={s.customExternalEvent}>
                <i className="fa fa-circle fa-fw text-warning ms-1 me-2" />
                Open windows
              </div>
            </div>
            <div
              data-event='{ "classNames": ["bg-primary", "text-white"], "title": "Some stuff" }'
              className="external-event draggable"
            >
              <div className={s.customExternalEvent}>
                <i className="fa fa-circle fa-fw text-primary ms-1 me-2" />
                Some stuff
              </div>
            </div>
            <div
              data-event='{ "classNames": ["bg-danger", "text-white"], "title": "Study UX engineering" }'
              className="external-event draggable"
            >
              <div className={s.customExternalEvent}>
                <i className="fa fa-square fa-fw text-danger ms-1 me-2" />
                Study UX engineering
              </div>
            </div>
            <div
              data-event='{ "classNames": ["bg-gray", "text-white"], "title": "Another stuff" }'
              className="external-event draggable"
            >
              <div className={s.customExternalEvent}>
                <i className="fa fa-circle-o fa-fw text-gray-light ms-1 me-2" />
                Another stuff
              </div>
            </div>
          </div>
        </Col>
        <Col md={6} lg={8} xs={12}>
          <Widget>
            <Row className="calendar-controls">
              <Col md={3}>
                <ButtonGroup className="me-3 mb-3">
                  <Button color="default" onClick={prev}>
                    <i className="fa fa-angle-left" />
                  </Button>
                  <Button color="default" onClick={next}>
                    <i className="fa fa-angle-right" />
                  </Button>
                </ButtonGroup>
                <Button className="mb-3" color="default" onClick={today}>
                  Today
                </Button>
              </Col>
              <Col md={9} className="calendar-controls text-end">
                <ButtonGroup className="mb-3">
                  <Button
                    color="default"
                    onClick={() => changeView("dayGridMonth")}
                    active={calendarView === "dayGridMonth"}
                  >
                    Month
                  </Button>
                  <Button
                    color="default"
                    onClick={() => changeView("timeGridWeek")}
                    active={calendarView === "timeGridWeek"}
                  >
                    Week
                  </Button>
                  <Button
                    color="default"
                    onClick={() => changeView("timeGridDay")}
                    active={calendarView === "timeGridDay"}
                  >
                    Day
                  </Button>
                  <Button
                    color="default"
                    onClick={() => changeView("listWeek")}
                    active={calendarView === "listWeek"}
                  >
                    List
                  </Button>
                </ButtonGroup>
              </Col>
            </Row>

            <FullCalendar
              ref={fullCalendarRef}
              initialView="dayGridMonth"
              plugins={calendarPlugins}
              select={select}
              eventClick={eventClick}
              drop={drop}
              {...calendarOptions}
            />
          </Widget>
        </Col>
      </Row>

      <Modal isOpen={modal} toggle={toggleModal} id="news-close-modal">
        <ModalHeader toggle={toggleModal} id="news-close-modal-label">
          Create New Event
        </ModalHeader>
        <ModalBody>
          Just enter event name to create a new one
          <Input
            onChange={handleChange}
            className={`${s.calendarModalInput} border-0`}
            value={event.title}
            type="text"
            name="title"
            placeholder="Title"
          />
        </ModalBody>
        <ModalFooter>
          <Button
            color="default"
            onClick={toggleModal}
            data-dismiss="modal"
          >
            Close
          </Button>{" "}
          <Button
            color="success"
            onClick={createEvent}
            id="news-widget-remove"
            className="ms-3"
          >
            Create
          </Button>
        </ModalFooter>
      </Modal>

      <Modal
        isOpen={modalEvent}
        toggle={toggleModalEvent}
        id="news-close-modal"
      >
        <ModalHeader
          toggle={toggleModalEvent}
          id="news-close-modal-label"
        >
          {event.title}
        </ModalHeader>
        <ModalBody>
          <p className="text-muted">
            <i className="la la-calendar"></i>
            {getFormattedDate(event.start)}
          </p>
          <p>{event.extendedProps && event.extendedProps.description}</p>
        </ModalBody>
        <ModalFooter>
          <Button
            color="default"
            onClick={toggleModalEvent}
            data-dismiss="modal"
          >
            OK
          </Button>
        </ModalFooter>
      </Modal>
    </div>
  );
};

export default Calendar;
