import { inject as injectOriginal, type InjectionKey } from 'vue';
import type { RouteLocationRaw } from 'vue-router';
import type { Date } from '@silane/datetime';

import type { Notification } from './composables/notification';
import type { Database } from './composables/database';
import type { ErrorHandler } from './composables/errorhandler';
import type { ColorLabelStore } from './composables/colorlabelstore';
import type { TimeLabelStore } from './composables/timelabelstore';
import type { ResourceStore, Resource } from './composables/resourcestore';
import type { ResourceHourStore } from './composables/resourcehourstore';
import type { EventStore, Event } from './composables/eventstore';
import type {
  GeneralTimetableScope,
} from './composables/general-timetable-scope';


const notification: InjectionKey<Notification> = Symbol('notification');
const database: InjectionKey<Database> = Symbol('database');
const errorHandler: InjectionKey<ErrorHandler> = Symbol('errorHandler');
const colorLabelStore: InjectionKey<ColorLabelStore> = Symbol('colorLabels');
const timeLabelStore: InjectionKey<TimeLabelStore> = Symbol('timeLabelStore');
const resourceStore: InjectionKey<ResourceStore> = Symbol('resourceStore');
const resourceHourStore: InjectionKey<ResourceHourStore> = Symbol(
  'resourceHourStore'
);
const eventStore: InjectionKey<EventStore> = Symbol('eventStore');
const generalTimetableScope: InjectionKey<GeneralTimetableScope> = Symbol(
  'generalTimetableScope'
);
const links: InjectionKey<{
  resourceViewLinkFn: (resource: Resource) => RouteLocationRaw,
  eventLinkFn: (event: Event) => RouteLocationRaw,
  eventChangeLinkFn: (fromEvent: Event) => RouteLocationRaw,
  dateTimeTableLinkFn: (date: Date) => RouteLocationRaw,
  resourceTimeTableLinkFn: (resource: Resource) => RouteLocationRaw,
}> = Symbol('links');

export const keys = {
  notification, database, errorHandler, colorLabelStore, timeLabelStore,
  resourceStore, resourceHourStore, eventStore, generalTimetableScope, links,
};


export function inject<T>(key: InjectionKey<T>): T;
export function inject<T>(
  key: InjectionKey<T>, defaultValue: T | null
): T | null;

export function inject<T>(
  key: InjectionKey<T>, defaultValue?: T | null | undefined
): T | null {
  const ret = injectOriginal(key);
  if(ret === undefined) {
    if(defaultValue === undefined) {
      throw new Error('Injection key not found');
    } else {
      return defaultValue;
    }
  }
  return ret;
}
