/*
 * 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 {SCMetaTranslations, SCTranslations} from '../general/i18n.js';
import {SCThingMeta, SCThingType} from './abstract/thing.js';
import {
  SCAcademicPriceGroup,
  SCThingThatCanBeOffered,
  SCThingThatCanBeOfferedMeta,
  SCThingThatCanBeOfferedTranslatableProperties,
  SCThingThatCanBeOfferedWithoutReferences,
} from './abstract/thing-that-can-be-offered.js';
import {
  SCThingWithCategories,
  SCThingWithCategoriesSpecificValues,
  SCThingWithCategoriesTranslatableProperties,
  SCThingWithCategoriesWithoutReferences,
  SCThingWithCategoriesWithoutReferencesMeta,
} from './abstract/thing-with-categories.js';
import {SCCertificationWithoutReferences} from './certification.js';

/**
 * A dish without references
 */
export interface SCDishWithoutReferences
  extends SCThingThatCanBeOfferedWithoutReferences,
    SCThingWithCategoriesWithoutReferences<SCDishCategories, SCThingWithCategoriesSpecificValues> {
  /**
   * Additives of the dish
   * @filterable
   * @keyword
   */
  additives?: string[];

  /**
   * Characteristics of the dish
   */
  characteristics?: SCDishCharacteristic[];

  /**
   * Nutrition information (calories and nutrients with amounts)
   */
  nutrition?: SCNutritionInformation;

  /**
   * Section of the restaurant menu to which the dish belongs
   */
  menuSection?: SCMenuSection;

  /**
   * Translated fields of a dish
   */
  translations?: SCTranslations<SCDishTranslatableProperties>;

  /**
   * Type of a dish
   */
  type: SCThingType.Dish;
}

/**
 * A dish
 * @validatable
 * @indexable
 */
export interface SCDish
  extends SCDishWithoutReferences,
    SCThingThatCanBeOffered<SCAcademicPriceGroup>,
    SCThingWithCategories<SCDishCategories, SCThingWithCategoriesSpecificValues> {
  /**
   * Dishes ("Beilagen") that are served with the dish (if only certain supplement dishes can be taken with a dish)
   */
  dishAddOns?: SCDishWithoutReferences[];

  /**
   * Certifications this dish received
   */
  certifications?: SCCertificationWithoutReferences[];

  /**
   * Translated fields of a dish
   */
  translations?: SCTranslations<SCDishTranslatableProperties>;

  /**
   * Type of a dish
   */
  type: SCThingType.Dish;
}

export interface SCDishTranslatableProperties
  extends SCThingWithCategoriesTranslatableProperties,
    SCThingThatCanBeOfferedTranslatableProperties {
  /**
   * Additives of the dish
   * @filterable
   * @keyword
   */
  additives?: string[];
  /**
   * Characteristics of the dish
   */
  characteristics?: SCDishCharacteristic[];
}

/**
 * Composition of properties of a food characteristic
 */
export interface SCDishCharacteristic {
  /**
   * URL of an image of the characteristic
   * @keyword
   */
  image?: string;

  /**
   * Name of the characteristic
   * @filterable
   * @text
   */
  name: string;
}

/**
 * A list of categories for dishes
 */
export type SCDishCategories = 'appetizer' | 'salad' | 'main dish' | 'dessert' | 'soup' | 'side dish';

/**
 * Type definition for SCNutritionInformation
 * @see https://schema.org/NutritionInformation
 */
export interface SCNutritionInformation {
  /**
   * Number of calories contained (in kcal)
   * @float
   */
  calories?: number;

  /**
   * Content of carbohydrates (in grams)
   * @float
   */
  carbohydrateContent?: number;

  /**
   * Content of fat (in grams)
   * @float
   */
  fatContent?: number;

  /**
   * Content of proteins (in grams)
   * @float
   */
  proteinContent?: number;

  /**
   * Content of salt (in grams)
   * @float
   */
  saltContent?: number;

  /**
   * Content of saturated fat (in grams)
   * @float
   */
  saturatedFatContent?: number;

  /**
   * Content of sugar (in grams)
   * @float
   */
  sugarContent?: number;
}

export interface SCMenuSection {
  /**
   * Name of the menu section (mostly to be used as a section title)
   */
  name: 'breakfast' | 'lunch' | 'dinner';

  /**
   * The time span when the dishes from the sections are available.
   * @see http://wiki.openstreetmap.org/wiki/Key:opening_hours/specification
   */
  servingHours?: string;
}

/**
 * Meta information about a dish
 */
export class SCDishMeta extends SCThingMeta implements SCMetaTranslations<SCDish> {
  /**
   * Translations of fields
   */
  fieldTranslations = {
    de: {
      ...new SCThingWithCategoriesWithoutReferencesMeta<
        SCDishCategories,
        SCThingWithCategoriesSpecificValues
      >().fieldTranslations.de,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldTranslations.de,
      additives: 'Allergene und Zusatzstoffe',
      characteristics: 'Merkmale',
      certifications: 'Zertifizierungen',
      dishAddOns: 'Beilagen',
      nutrition: 'Nährwertangaben',
      menuSection: 'Menüabschnitt',
    },
    en: {
      ...new SCThingWithCategoriesWithoutReferencesMeta<
        SCDishCategories,
        SCThingWithCategoriesSpecificValues
      >().fieldTranslations.en,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldTranslations.en,
      additives: 'additives and allergens',
      characteristics: 'characteristics',
      certifications: 'certifications',
      dishAddOns: 'side dishes',
      nutrition: 'nutrition information',
      menuSection: 'menu section',
    },
  };

  /**
   * Translations of values of fields
   */
  fieldValueTranslations = {
    de: {
      ...new SCThingWithCategoriesWithoutReferencesMeta<
        SCDishCategories,
        SCThingWithCategoriesSpecificValues
      >().fieldValueTranslations.de,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldValueTranslations.de,
      categories: {
        'appetizer': 'Vorspeise',
        'dessert': 'Nachtisch',
        'main dish': 'Hauptgericht',
        'salad': 'Salat',
        'side dish': 'Beilage',
        'soup': 'Suppe',
      },
      type: 'Essen',
    },
    en: {
      ...new SCThingWithCategoriesWithoutReferencesMeta<
        SCDishCategories,
        SCThingWithCategoriesSpecificValues
      >().fieldValueTranslations.en,
      ...new SCThingThatCanBeOfferedMeta<SCAcademicPriceGroup>().fieldValueTranslations.en,
      type: SCThingType.Dish,
    },
  };
}
