import { VTextField } from "vuetify/lib/components/VTextField/VTextField";
import { VNumberInput } from "vuetify/lib/components/VNumberInput/VNumberInput";
import TextDisplay from "./components/generic/forms/TextDisplay.vue";
import TextareaField from "./components/generic/forms/TextareaField.vue";
import BooleanField from "./components/generic/forms/BooleanField.vue";
import BooleanFieldDisplay from "./components/generic/forms/BooleanFieldDisplay.vue";
import DateField from "./components/generic/forms/DateField.vue";
import DateFieldDisplay from "./components/generic/forms/DateFieldDisplay.vue";
import TimeField from "./components/generic/forms/TimeField.vue";
import TimeFieldDisplay from "./components/generic/forms/TimeFieldDisplay.vue";
import DateTimeField from "./components/generic/forms/DateTimeField.vue";
import DateTimeFieldDisplay from "./components/generic/forms/DateTimeFieldDisplay.vue";
import FileField from "./components/generic/forms/FileField.vue";
import FileFieldDisplay from "./components/generic/forms/FileFieldDisplay.vue";
import WeekDayField from "./components/generic/forms/WeekDayField.vue";
import WeekDayFieldDisplay from "./components/generic/forms/WeekDayFieldDisplay.vue";
import ColorField from "./components/generic/forms/ColorField.vue";
import ColorFieldDisplay from "./components/generic/forms/ColorFieldDisplay.vue";
import PersonDisplay from "./components/generic/forms/PersonDisplay.vue";
import GroupDisplay from "./components/generic/forms/GroupDisplay.vue";

// TODO: This should probably use the useDate composable. But it complains: Uncaught Error: [Vuetify] Could not find injected date options
// import { useDate } from 'vuetify'
// const date = useDate()
// Using luxon directly for now
import { DateTime } from "luxon";
import ArrayDisplay from "./components/generic/forms/ArrayDisplay.vue";
import ArrayField from "./components/generic/forms/ArrayField.vue";

// Graphql queries and mutations
// TODO: Most (all?) of these should be autogenerated instead.
// But this explict version has the added benefit of declaring that for example groups and persons can only be deleted and queried.
import {
  rooms,
  createRooms,
  updateRooms,
  deleteRooms,
} from "./components/room/room.graphql";
import {
  holidays,
  createHolidays,
  deleteHolidays,
  updateHolidays,
} from "./components/holiday/holiday.graphql";
import {
  roles,
  createRoles,
  deleteRoles,
  updateRoles,
} from "./components/role/role.graphql";
import {
  schoolTerms,
  createSchoolTerms,
  deleteSchoolTerms,
  updateSchoolTerms,
} from "./components/school_term/schoolTerm.graphql";
import {
  announcements,
  createAnnouncements,
  deleteAnnouncements,
  patchAnnouncements,
} from "./components/announcements/announcements.graphql";
import { deleteGroups, groups } from "./components/group/groups.graphql";
import { deletePersons, persons } from "./components/person/personList.graphql";
import {
  groupTypes,
  createGroupTypes,
  deleteGroupTypes,
  updateGroupTypes,
} from "./components/group_type/groupType.graphql";
import {
  availabilityTypes,
  createAvailabilityTypes,
  deleteAvailabilityTypes,
  updateAvailabilityTypes,
} from "./components/availability_type/availabilityType.graphql";
import {
  myAvailabilityEvents,
  createAvailabilityEvents,
  deleteAvailabilityEvents,
  updateAvailabilityEvents,
} from "./components/availability_event/availabilityEvent.graphql";
import {
  createPersonalEvents,
  updatePersonalEvents,
  deletePersonalEvents,
} from "./components/calendar/personal_event/personalEvent.graphql";
import {
  createPersonalTodos,
  updatePersonalTodos,
  deletePersonalTodos,
} from "./components/calendar/personal_todo/personalTodo.graphql";
import {
  oauthApplications,
  createOauthApplications,
  updateOauthApplications,
  deleteOauthApplications,
} from "./components/oauth/oauth_application.graphql";
import OAuthAlgorithmField from "./components/oauth/OAuthAlgorithmField.vue";
import OAuthAlgorithmDisplay from "./components/oauth/OAuthAlgorithmDisplay.vue";
import OAuthClientTypeField from "./components/oauth/OAuthClientTypeField.vue";
import OAuthClientTypeDisplay from "./components/oauth/OAuthClientTypeDisplay.vue";
import OAuthScopesField from "./components/oauth/OAuthScopesField.vue";
import OAuthScopesDisplay from "./components/oauth/OAuthScopesDisplay.vue";
// TODO: Implement min & max support for Date properties
// => A prop with a function that receives the whole item.
//    Field.vue calls this function on item update and uses its resulting object as props to its field component.

export const objectSchemas = [
  {
    type: "Int",
    editComponent: VNumberInput,
    displayComponent: TextDisplay,
  },
  {
    type: "String",
    editComponent: VTextField,
    displayComponent: TextDisplay,
  },
  {
    type: "Boolean",
    editComponent: BooleanField,
    displayComponent: BooleanFieldDisplay,
  },
  {
    type: "ID",
    hideTable: true,
    hideEdit: true,
  },
  {
    type: "Date",
    editComponent: DateField,
    read: DateTime.fromISO,
    write: (dt) => dt.toISODate(),
    displayComponent: DateFieldDisplay,
  },
  {
    type: "Time",
    editComponent: TimeField,
    displayComponent: TimeFieldDisplay,
  },
  {
    type: "DateTime",
    editComponent: DateTimeField,
    read: DateTime.fromISO,
    write: (dt) => dt.toISO(),
    displayComponent: DateTimeFieldDisplay,
  },
  {
    type: "FieldFileType",
    editComponent: FileField,
    displayComponent: FileFieldDisplay,
  },
  {
    type: "Weekday",
    editComponent: WeekDayField,
    displayComponent: WeekDayFieldDisplay,
  },
  {
    type: "Color",
    editComponent: ColorField,
    displayComponent: ColorFieldDisplay,
  },
  {
    type: "array",
    displayComponent: ArrayDisplay,
    editComponent: ArrayField,
  },
  {
    type: "ContentTypeType",
    nameProp: (ct) => ct.verboseName,
  },
  // Objects for graphql queries and mutations, see above TODO
  // TODO: model should come from backend
  {
    type: "RoomType",
    model: "Room",
    query: rooms,
    createMutation: createRooms,
    patchMutation: updateRooms,
    deleteMutation: deleteRooms,
  },
  {
    type: "HolidayType",
    model: "Holiday",
    query: holidays,
    createMutation: createHolidays,
    patchMutation: updateHolidays,
    deleteMutation: deleteHolidays,
  },
  {
    type: "RoleType",
    model: "Role",
    query: roles,
    createMutation: createRoles,
    patchMutation: updateRoles,
    deleteMutation: deleteRoles,
  },
  {
    type: "SchoolTermType",
    model: "SchoolTerm",
    query: schoolTerms,
    createMutation: createSchoolTerms,
    patchMutation: updateSchoolTerms,
    deleteMutation: deleteSchoolTerms,
    properties: {
      current: { hideTable: true, hideEdit: true },
    },
  },
  {
    type: "AnnouncementType",
    model: "Announcement",
    query: announcements,
    createMutation: createAnnouncements,
    patchMutation: patchAnnouncements,
    deleteMutation: deleteAnnouncements,
    tableFields: [
      "datetimeStart",
      "datetimeEnd",
      "isGlobal",
      "title",
      "description",
      "priority",
    ],
    editFields: [
      "datetimeStart",
      "datetimeEnd",
      "title",
      "description",
      "isGlobal",
      "priority",
      "recipientPersons",
      "recipientGroups",
    ],
    properties: {
      datetimeStart: { cols: 12 },
      datetimeEnd: { cols: 12 },
      description: {
        editComponent: TextareaField,
        cols: 12,
        hint: "announcement.description_hint",
      },
      title: { cols: 12, hint: "announcement.title_hint" },
      priority: { min: 0, hint: "announcement.priority_hint" },
      isGlobal: { hint: "announcement.is_global_hint" },
    },
  },
  {
    type: "GroupType",
    model: "Group",
    query: groups,
    deleteMutation: deleteGroups,
    tableFields: ["shortName", "name", "groupType", "schoolTerm", "avatarUrl"],
    displayComponent: GroupDisplay,
  },
  {
    type: "PersonType",
    model: "Person",
    query: persons,
    deleteMutation: deletePersons,
    nameProp: (person) => {
      if (person?.shortName) {
        return `${person.fullName} (${person.shortName})`;
      } else {
        return person.fullName;
      }
    },
    tableFields: ["shortName", "firstName", "lastName", "primaryGroup"],
    displayComponent: PersonDisplay,
  },
  {
    type: "GroupTypeType",
    model: "GroupType",
    query: groupTypes,
    createMutation: createGroupTypes,
    patchMutation: updateGroupTypes,
    deleteMutation: deleteGroupTypes,
  },
  {
    type: "AvailabilityTypeType",
    model: "AvailabilityType",
    query: availabilityTypes,
    createMutation: createAvailabilityTypes,
    patchMutation: updateAvailabilityTypes,
    deleteMutation: deleteAvailabilityTypes,
    properties: {
      free: { default: false, hint: "availability_type.free_help_text" },
      public: { default: true, hint: "availability_type.public_help_text" },
    },
    tableFields: ["name", "shortName", "free", "public", "color"],
  },
  {
    type: "AvailabilityEventType",
    model: "AvailabilityEvent",
    query: myAvailabilityEvents,
    createMutation: createAvailabilityEvents,
    patchMutation: updateAvailabilityEvents,
    deleteMutation: deleteAvailabilityEvents,
    tableFields: [
      "availabilityType",
      "datetimeStart",
      "datetimeEnd",
      "recurrences",
      "title",
      "description",
    ],
    properties: {
      free: { default: true },
    },
  },
  {
    type: "PersonalEventType",
    model: "PersonalEvent",
    // query: myAvailabilityEvents,
    createMutation: createPersonalEvents,
    patchMutation: updatePersonalEvents,
    deleteMutation: deletePersonalEvents,
  },
  {
    type: "PersonalTodoType",
    model: "PersonalTodo",
    // query: myAvailabilityEvents,
    createMutation: createPersonalTodos,
    patchMutation: updatePersonalTodos,
    deleteMutation: deletePersonalTodos,
  },
  {
    type: "DashboardWidgetType",
    model: "DashboardWidget",
  },
  {
    type: "OAuthApplicationType",
    model: "OAuthApplication",
    query: oauthApplications,
    createMutation: createOauthApplications,
    patchMutation: updateOauthApplications,
    deleteMutation: deleteOauthApplications,
    tableFields: [
      "name",
      "icon",
      "clientType",
      "algorithm",
      "allowedScopes",
      "redirectUris",
      "skipAuthorization",
    ],
    editFields: [
      "name",
      "icon",
      "clientType",
      "algorithm",
      "allowedScopes",
      "redirectUris",
      "skipAuthorization",
    ],
    properties: {
      algorithm: {
        editComponent: OAuthAlgorithmField,
        displayComponent: OAuthAlgorithmDisplay,
      },
      clientType: {
        editComponent: OAuthClientTypeField,
        displayComponent: OAuthClientTypeDisplay,
      },
      allowedScopes: {
        editComponent: OAuthScopesField,
        displayComponent: OAuthScopesDisplay,
      },
      redirectUris: { hint: "o_auth_application.redirect_uris_hint" },
    },
  },
];
export const objectLayouts = [];

// TODO: Use nameProp in other places as well; DeleteDialog
