/*
 * Copyright (C) 2019-2022 Open 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 {SCLanguage, SCMetaTranslations, SCTranslations} from '../general/i18n.js';
import {SCMap} from '../general/map.js';
import {SCThingMeta, SCThingType} from './abstract/thing.js';
import {
  SCAcademicPriceGroup,
  SCThingThatCanBeOffered,
  SCThingThatCanBeOfferedMeta,
  SCThingThatCanBeOfferedTranslatableProperties,
  SCThingThatCanBeOfferedWithoutReferences,
} from './abstract/thing-that-can-be-offered.js';
import {SCAcademicEventWithoutReferences} from './academic-event.js';
import {SCOrganizationWithoutReferences} from './organization.js';
import {SCPersonWithoutReferences} from './person.js';

/**
 * A study module without references
 */
export interface SCStudyModuleWithoutReferences extends SCThingThatCanBeOfferedWithoutReferences {
  /**
   * ECTS points (European Credit Transfer System)
   * @float
   */
  ects: number;

  /**
   * The language in which the study module is offered
   */
  language: SCLanguage;

  /**
   * Majors that this study module is meant for
   * @filterable
   * @keyword
   */
  majors: string[];

  /**
   * Represents the modules necessity for each given major (of the major property)
   */
  necessity: SCMap<SCStudyModuleNecessity>;

  /**
   * Translated fields of a study module
   */
  translations?: SCTranslations<SCStudyModuleTranslatableProperties>;

  /**
   * Type of the study module
   */
  type: SCThingType.StudyModule;
}

/**
 * A study module
 * @validatable
 * @indexable
 */
export interface SCStudyModule
  extends SCStudyModuleWithoutReferences,
    SCThingThatCanBeOffered<SCAcademicPriceGroup> {
  /**
   * Academic events that make up a study module
   */
  academicEvents: SCAcademicEventWithoutReferences[];

  /**
   * The faculty that manages and curates the study module
   */
  faculty: SCOrganizationWithoutReferences;

  /**
   * Study modules needed for each others fulfillment
   */
  partnerModules?: SCStudyModuleWithoutReferences[];

  /**
   * Study modules required beforehand
   */
  requiredModules?: SCStudyModuleWithoutReferences[];

  /**
   * The secretary that administers requests and
   * questions concerning the study module by eg. students
   */
  secretary: SCOrganizationWithoutReferences | SCPersonWithoutReferences;

  /**
   * Translated fields of a study module
   */
  translations?: SCTranslations<SCStudyModuleTranslatableProperties>;

  /**
   * Type of the study module
   */
  type: SCThingType.StudyModule;
}

export interface SCStudyModuleTranslatableProperties extends SCThingThatCanBeOfferedTranslatableProperties {
  /**
   * Translations of the majors that this study module is meant for
   * @keyword
   */
  majors?: string[];

  /**
   * Translations of the modules necessity for each given major (of the major property)
   */
  necessity: SCMap<SCStudyModuleNecessity>;
}

/**
 * Represents a modules necessity (in a major) as it may be required, optional or
 * is in a pool of n optional modules were m out of them have to be taken/completed.
 * Hence the elective option.
 */
export enum SCStudyModuleNecessity {
  Required = 'required',
  Elective = 'elective',
  Optional = 'optional',
}

/**
 * Study module meta data
 */
export class SCStudyModuleMeta extends SCThingMeta implements SCMetaTranslations<SCStudyModule> {
  /**
   * Translations of fields
   */
  fieldTranslations = {
    de: {
      ...new SCThingMeta().fieldTranslations.de,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldTranslations.de,
      academicEvents: 'Veranstaltungen',
      ects: 'ECTS-Punkte',
      faculty: 'Fachbereich',
      language: 'Unterrichtssprache',
      majors: 'Fachrichtungen',
      necessity: 'Erforderlichkeit',
      partnerModules: 'Partnermodule',
      requiredModules: 'Benötigte Module',
      secretary: 'Sekretariat',
    },
    en: {
      ...new SCThingMeta().fieldTranslations.en,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldTranslations.en,
      academicEvents: 'academic events',
      ects: 'ECTS points',
      faculty: 'faculty',
      language: 'teaching language',
      majors: 'majors',
      necessity: 'necessity',
      partnerModules: 'partner modules',
      requiredModules: 'required modules',
      secretary: 'secretary',
    },
  };

  /**
   * Translations of values of fields
   */
  fieldValueTranslations = {
    de: {
      ...new SCThingMeta().fieldValueTranslations.de,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldValueTranslations.de,
      necessity: {
        elective: 'Wahlfach',
        optional: 'optional',
        required: 'benötigt',
      },
      type: 'Studiengangmodul',
    },
    en: {
      ...new SCThingMeta().fieldValueTranslations.en,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldValueTranslations.en,
      type: SCThingType.StudyModule,
    },
  };
}
