import React from "react";
import { Helmet } from "react-helmet";
import "./EventCreatePage.scss";
import { isAuthenticated } from "@utils/auth";
import Form from "react-jsonschema-form";
import { Tag, getTags } from "@models/Tag";
import { SignupForm, getForms } from "@models/SignupForm";
import { createEvent, getEvent, updateEvent, Event } from "@models/Event";
import DatetimeWidget from "@components/DatetimeWidget";
import SectionDividerWidget from "@components/SectionDividerWidget";
import Icon from "@components/Icon";
import { IconType } from "@components/Icon/Icon";

const widgets = {
  datetime: DatetimeWidget,
  section_divider: SectionDividerWidget,
};

export interface EventCreatePageProps {
  history: {
    push: (to: string) => void;
  };
  match: {
    params: {
      id?: number;
    };
  };
}
export interface EventCreatePageState {
  tags: Tag[];
  signupForm: SignupForm[];
  error?: string;
  statusMessage?: string;
  formData: any;
}

class EventCreatePage extends React.Component<EventCreatePageProps, EventCreatePageState> {
  constructor(props) {
    super(props);
    this.state = {
      tags: [],
      signupForm: [],
      formData: {},
    };

    this.fetchTags();
    this.fetchSignupForms();

    const { id } = props.match.params;
    if (id !== undefined) {
      this.fetchInitialFormData(id);
    }
  }

  fetchInitialFormData = async (id) => {
    try {
      const data = await getEvent(id, true);
      data.tags = data.tag_id as any;
      data.signupForm = data.signup_id as any;
      this.setState({
        formData: data,
      });
    } catch (err) {
      this.setState({
        error: String(err),
      });
    }
  }

  fetchTags = async () => {
    try {
      const tags = await getTags();
      this.setState({
        tags,
      });
      return tags;
    } catch (err) {
      this.setState({
        error: String(err),
      });
      throw err;
    }
  }

  fetchSignupForms = async () => {
    try {
      const signupForm = await getForms(true);
      this.setState({
        signupForm
      })
      return signupForm;
    } catch (err) {
      this.setState({
        error: String(err),
      });
      throw err;
    }
  }

  onSubmit = async (data) => {
    console.log("submitted, data:");
    console.log(data.formData);

    const { history } = this.props;

    try {
      const payload = data.formData;
      if (typeof payload.image === "string" && payload.image.startsWith("http")) payload.image = undefined;
      payload.signup_id = payload.signupForm;
      payload.tag_id = payload.tags;
      if (payload.id === undefined) {
        const resp = await createEvent(payload);
        resp.tags = resp.tag_id as any;
        resp.signupForm = resp.signup_id as any;
        this.setState({
          formData: resp,
          statusMessage: "Event created successfully",
        });
      } else {
        const resp = await updateEvent(payload);
        resp.tags = resp.tag_id as any;
        resp.signupForm = resp.signup_id as any;
        this.setState({
          formData: resp,
          statusMessage: "Event updated successfully.",
        });
      }
    } catch (err) {
      this.setState({
        error: String(err),
      });
    }
  }

  onError = (data) => {
    console.error("error, data:");
    console.log(data);
  }

  onChange = (data) => {
    this.setState({
      formData: data.formData,
    });
  }

  onFocus = () => {
    this.setState({
      statusMessage: null,
    });
  }

  buildSchema = () => {
    const { tags, signupForm, error } = this.state;

    const formData = this.state.formData as Event;

    const date = new Date();
    const currentDatetime = date.toISOString();
    const tomorrowDate = new Date();
    tomorrowDate.setDate(tomorrowDate.getDate() + 1);
    const tomorrowDatetime = tomorrowDate.toISOString();

    const schema = {
      title: formData.id ? formData.title_fi : "New Event",
      type: "object",
      required: ["title_fi", "title_en", "tags", "location", "start_time", "end_time", "description_fi", "description_en", "content_fi", "content_en"],
      properties: {
        tags: {
          type: "array",
          title: "Event tags",
          items: {
            type: "number",
            enum: tags.map(t => t.id),
            enumNames: tags.map(t => t.name_fi),
          },
          uniqueItems: true,
          default: [],
        },
        visible: {
          type: "boolean",
          title: "Visible",
          default: true,
        },
        location: {
          type: "string",
          title: "Location",
          default: "",
        },
        start_time: {
          type: "string",
          title: "Start time",
          default: currentDatetime,
        },
        end_time: {
          type: "string",
          title: "End time",
          default: tomorrowDatetime,
        },
        signupForm: {
          type: ["array"],
          title: "Signup forms",
          items: {
            type: ["number", "null"],
            // TODO: A bug here, DB must have at least one SignupForm, otherwise cannot submit
            enum: signupForm.map(form => form.id),
            enumNames: signupForm.map(form => form.title),
          },
          uniqueItems: true,
        },
        image: {
          type: ["string", "null"],
          format: formData.image ? "uri-reference" : "data-url",
          title: "Override tag icon with image",
          default: undefined
        },
        finnish_section_divider: {
          title: "Finnish",
          type: "string",
        },
        title_fi: {
          type: "string",
          title: "Title",
          default: ""
        },
        description_fi: {
          type: "string",
          title: "Description",
          default: "",
        },
        content_fi: {
          type: "string",
          title: "Content",
          default: "",
        },
        english_section_divider: {
          title: "English",
          type: "string",
        },
        title_en: {
          type: "string",
          title: "Title",
          default: ""
        },
        description_en: {
          type: "string",
          title: "Description",
          default: "",
        },
        content_en: {
          type: "string",
          title: "Content",
          default: "",
        },
      }
    };
    return schema;
  }

  buildUISchema = () => {
    const uiSchema = {
      content_fi: {
        "ui:widget": "textarea",
      },
      content_en: {
        "ui:widget": "textarea",
      },
      start_time: {
        "ui:widget": "datetime",
      },
      end_time: {
        "ui:widget": "datetime",
      },
      image: {
        "ui:options": {
          accept: [".jpg", ".jpeg", ".png"]
        }
      },
      finnish_section_divider: {
        "ui:widget": "section_divider",
        "ui:options": {
          label: false
        },
      },
      english_section_divider: {
        "ui:widget": "section_divider",
        "ui:options": {
          label: false
        },
      },
    };
    return uiSchema;
  }

  render() {
    const { error, statusMessage } = this.state;
    const formData = this.state.formData as Event;
    const schema = this.buildSchema();
    const uiSchema = this.buildUISchema();

    const title = formData.id
      ? `Edit Event "${formData.title_fi}"`
      : "Create Event";

    return (
      <div className="event-create-page">
        <Helmet>
          <link rel="canonical" href="https://sik.ayy.fi/admin/events/create" />
        </Helmet>
        <h1>{title}</h1>
        {statusMessage && <div className="success">{statusMessage}</div>}
        <Form schema={schema as any}
          uiSchema={uiSchema}
          formData={formData}
          idPrefix="rjsf"
          widgets={widgets as any}
          onChange={this.onChange}
          onSubmit={this.onSubmit}
          onError={this.onError}
          onFocus={this.onFocus} />
        {error && <div className="error">{error}</div>}
      </div>
    );
  }
}

export default EventCreatePage;
