/*
 * Copyright (C) 2023 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {ComponentRef, Directive, Input, Type, ViewContainerRef} from '@angular/core';
import {SCThings, SCThingType} from '@openstapps/core';
import {BookListItemComponent} from '../types/book/book-list-item.component';
import {CatalogListItemComponent} from '../types/catalog/catalog-list-item.component';
import {DateSeriesListItemComponent} from '../types/date-series/date-series-list-item.component';
import {EventListItemComponent} from '../types/event/event-list-item.component';
import {FavoriteListItemComponent} from '../types/favorite/favorite-list-item.component';
import {MessageListItemComponent} from '../types/message/message-list-item.component';
import {OrganizationListItemComponent} from '../types/organization/organization-list-item.component';
import {PersonListItemComponent} from '../types/person/person-list-item.component';
import {PlaceListItemComponent} from '../types/place/place-list-item.component';
import {SemesterListItemComponent} from '../types/semester/semester-list-item.component';
import {VideoListItemComponent} from '../types/video/video-list-item.component';
import {PeriodicalListItemComponent} from '../types/periodical/periodical-list-item.component';
import {DataListItemHostDefaultComponent} from './data-list-item-host-default.component';
import {ArticleListItemComponent} from '../types/article/article-item.component';
import {DishListItemComponent} from '../types/dish/dish-list-item.component';
import {JobPostingListItemComponent} from '../types/job-posting/job-posting-list-item.component';

export interface DataListItem {
  item: SCThings;
}

const DataListItemIndex: Partial<Record<SCThingType, Type<DataListItem>>> = {
  [SCThingType.Catalog]: CatalogListItemComponent,
  [SCThingType.Dish]: DishListItemComponent,
  [SCThingType.DateSeries]: DateSeriesListItemComponent,
  [SCThingType.AcademicEvent]: EventListItemComponent,
  [SCThingType.SportCourse]: DateSeriesListItemComponent,
  [SCThingType.Favorite]: FavoriteListItemComponent,
  [SCThingType.Message]: MessageListItemComponent,
  [SCThingType.Organization]: OrganizationListItemComponent,
  [SCThingType.Person]: PersonListItemComponent,
  [SCThingType.Building]: PlaceListItemComponent,
  [SCThingType.Floor]: PlaceListItemComponent,
  [SCThingType.PointOfInterest]: PlaceListItemComponent,
  [SCThingType.Room]: PlaceListItemComponent,
  [SCThingType.Semester]: SemesterListItemComponent,
  [SCThingType.Video]: VideoListItemComponent,
  [SCThingType.Periodical]: PeriodicalListItemComponent,
  [SCThingType.Book]: BookListItemComponent,
  [SCThingType.Article]: ArticleListItemComponent,
  [SCThingType.JobPosting]: JobPostingListItemComponent,
};

@Directive({
  selector: '[dataListItemHost]',
})
export class DataListItemHostDirective {
  private type?: Type<DataListItem>;

  private component?: ComponentRef<DataListItem>;

  constructor(readonly viewContainerRef: ViewContainerRef) {}

  @Input() set dataListItemHost(value: SCThings | undefined) {
    if (!value) {
      this.viewContainerRef.clear();
      delete this.type;
      delete this.component;
      return;
    }

    const type = DataListItemIndex[value.type] || DataListItemHostDefaultComponent;
    if (this.type !== type || !this.component) {
      this.type = type;
      this.viewContainerRef.clear();
      this.component = this.viewContainerRef.createComponent(this.type);
    }
    this.component.instance.item = value;
  }
}
