/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package opennlp.tools.cmdline.namefind.generator;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Locale;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Generates randomly created sentences for the German language
 * to compile a text corpus for training purposes.
 * <p>
 * Covers famous books and movies, recent sport events, music highlights, and events
 * from politics and science, distributed across the last 100 years.
 * <p>
 * Dates are formatted as {@code <START:date> ... <END>} in different German date format variations.
 *
 * @implNote Event template phrases generated by AI (MS Copilot).
 *
 * @see opennlp.tools.namefind.NameFinderMEWithDatesTest
 */
public class RandomGermanNewsGenerator extends AbstractNewsGenerator {

  private static final Logger logger = LoggerFactory.getLogger(RandomGermanNewsGenerator.class);

  private static final String START_DATE = "<START:date> ";
  private static final String END = " <END>";

  // Origin: https://en.wikipedia.org/wiki/List_of_date_formats_by_country
  private static final String[] DATE_FORMATS = {
      "dd. MMMM yyyy",
      "EEEE, dd. MMMM yyyy",
      "MMMM yyyy",
      "dd.MM.yyyy",
      "d.MM.yyyy",
      "d.M.yyyy",
      "d.M.yy"
  };

  private static final String[] SPORTS_EVENTS = {
      "fand der legendäre Boxkampf zwischen Joe Louis und Max Schmeling statt.",
      "wurden die Olympischen Spiele in Rom ausgetragen.",
      "ereignete sich das 'Wunder von Bern', als die deutsche Fußballnationalmannschaft" +
              " die Weltmeisterschaft gewann.",
      "wurden die Olympischen Winterspiele in Lake Placid abgehalten.",
      "fand die Fußball-Weltmeisterschaft in Italien statt.",
      "wurden die Olympischen Spiele in Atlanta ausgerichtet.",
      "wurde die Fußball-Weltmeisterschaft in Brasilien ausgetragen.",
      "fanden die Olympischen Spiele in Tokio statt.",
      "wurde die Fußball-Europameisterschaft in mehreren Städten Europas ausgetragen.",
      "wurden die Olympischen Winterspiele in Peking abgehalten.",
      "wurde die Fußball-Weltmeisterschaft in Katar ausgetragen.",
      "werden die Olympischen Spiele in Paris stattfinden.",
      "gewann die brasilianische Fußballnationalmannschaft die Weltmeisterschaft.",
      "stellte Usain Bolt einen neuen Weltrekord im 100-Meter-Lauf auf.",
      "gewann Serena Williams ihren 23. Grand-Slam-Titel.",
      "fand das Finale der NBA-Meisterschaft statt, bei dem die Los Angeles Lakers" +
              " den Titel holten.",
      "gewann Michael Phelps seine 23. olympische Goldmedaille.",
      "fand das Wimbledon-Finale statt, bei dem Roger Federer seinen achten Titel gewann.",
      "gewann die deutsche Fußballnationalmannschaft die Europameisterschaft.",
      "fand das Super Bowl-Finale statt, bei dem die New England Patriots den Sieg errangen.",
      "gewann Rafael Nadal seinen 13. French-Open-Titel.",
      "fand das Finale der UEFA Champions League statt, bei dem Real Madrid den Titel holte."
  };

  private static final String[] MUSIC_EVENTS = {
      "erschien Elvis Presleys erste Single 'That's All Right'.",
      "wurde das Album 'A Night at the Opera' von Queen veröffentlicht.",
      "begann das Woodstock-Festival.",
      "erschien das Album 'Nevermind' von Nirvana.",
      "wurde das Album '25' von Adele veröffentlicht.",
      "verstarb Michael Jackson, der 'King of Pop'.",
      "erschien das Album 'A Seat at the Table' von Solange.",
      "wurde das Album 'Montero' von Lil Nas X veröffentlicht.",
      "erschien das Album 'Motomami' von Rosalía.",
      "wurde das Album 'Midnights' von Taylor Swift veröffentlicht.",
      "wurde das Album 'Thriller' von Michael Jackson veröffentlicht.",
      "erschien das Album 'The Dark Side of the Moon' von Pink Floyd.",
      "wurde das Album 'Abbey Road' von den Beatles veröffentlicht.",
      "erschien das Album 'Back in Black' von AC/DC.",
      "wurde das Album 'Rumours' von Fleetwood Mac veröffentlicht.",
      "erschien das Album 'Hotel California' von den Eagles.",
      "wurde das Album 'Born to Run' von Bruce Springsteen veröffentlicht.",
      "erschien das Album 'Purple Rain' von Prince.",
      "wurde das Album 'The Wall' von Pink Floyd veröffentlicht.",
      "erschien das Album 'Led Zeppelin IV' von Led Zeppelin."
  };

  private static final String[] CINEMA_EVENTS = {
      "kam der Film 'Vom Winde verweht' in die Kinos.",
      "wurde der Film 'Lawrence von Arabien' veröffentlicht.",
      "kam der Film 'Star Wars: Eine neue Hoffnung' in die Kinos.",
      "erschien der Film 'Titanic'.",
      "kam der Film 'Avatar' in die Kinos.",
      "wurde der Film 'Die Eiskönigin – Völlig unverfroren' veröffentlicht.",
      "kam der Film 'Thor: Tag der Entscheidung' in die Kinos.",
      "wurde der Film 'Der Pate' veröffentlicht.",
      "erschien der Film 'Schindlers Liste'.",
      "kam der Film 'Der Herr der Ringe: Die Gefährten' in die Kinos.",
      "wurde der Film 'Forrest Gump' veröffentlicht.",
      "erschien der Film 'Der König der Löwen'.",
      "kam der Film 'Jurassic Park' in die Kinos.",
      "wurde der Film 'Inception' veröffentlicht.",
      "erschien der Film 'The Matrix'.",
      "kam der Film 'Gladiator' in die Kinos.",
      "wurde der Film 'Pulp Fiction' veröffentlicht."
  };

  private static final String[] ECONOMY_EVENTS = {
      "wurde bekannt gegeben, dass die globale Wirtschaft ein Wachstum von 3,5 % verzeichnet hat.",
      "wurde ein bedeutendes Abkommen zur Förderung der internationalen Zusammenarbeit im Bereich" +
              " der Wirtschaft unterzeichnet.",
      "fand eine große Konferenz zur globalen Wirtschaftsversorgung statt, bei der führende Experten" +
              " über Strategien zur Verbesserung der Wirtschaftsdienste diskutierten.",
      "wurde die Einführung des Euro als gemeinsame Währung in Europa beschlossen.",
      "fand die Gründung der Weltbank statt.",
      "wurde die Europäische Zentralbank gegründet.",
      "wurde das Bretton-Woods-Abkommen unterzeichnet.",
      "fand die erste Sitzung des Weltwirtschaftsforums in Davos statt.",
      "wurde die Welthandelsorganisation (WTO) gegründet.",
      "wurde der Vertrag von Maastricht unterzeichnet, der zur Gründung der Europäischen Union führte.",
      "wurde die Einführung des Marshallplans zur wirtschaftlichen Wiederaufbauhilfe nach dem " +
              "Zweiten Weltkrieg beschlossen.",
      "wurde die Gründung der Organisation für wirtschaftliche Zusammenarbeit und " +
              "Entwicklung (OECD) beschlossen.",
      "fand die erste Sitzung der G20 statt."
  };

  private static final String[] POLITICS_EVENTS = {
      "fanden die Bundestagswahlen in Deutschland statt.",
      "wurde ein neues Gesetz zur Förderung der digitalen Bildung verabschiedet.",
      "wurde ein bedeutendes Abkommen zur Förderung der internationalen Zusammenarbeit im Bereich" +
              " der Politik unterzeichnet.",
      "wurde die Allgemeine Erklärung der Menschenrechte von den Vereinten Nationen verabschiedet.",
      "fand die Gründung der Vereinten Nationen statt.",
      "wurde der Vertrag von Versailles unterzeichnet, der den Ersten Weltkrieg beendete.",
      "wurde die NATO gegründet.",
      "fand die erste Sitzung des Europäischen Parlaments statt.",
      "wurde der Vertrag von Lissabon unterzeichnet, der die Europäische Union reformierte.",
      "wurde die Berliner Mauer errichtet.",
      "fand die Wiedervereinigung Deutschlands statt.",
      "wurde der Vertrag von Rom unterzeichnet, der zur Gründung der " +
              "Europäischen Wirtschaftsgemeinschaft führte.",
      "wurde die Charta der Vereinten Nationen unterzeichnet."
  };

  private static final String[] SCIENCE_EVENTS = {
      "wurde ein bedeutender Durchbruch in der Quantencomputing-Forschung erzielt.",
      "startete ein bedeutendes wissenschaftliches Projekt zur Erforschung des Klimawandels.",
      "fand ein bedeutendes wissenschaftliches Symposium zu den neuesten Entwicklungen" +
              " in der Genforschung statt.",
      "wurde die Struktur der DNA von James Watson und Francis Crick entdeckt.",
      "landete die Apollo-11-Mission erfolgreich auf dem Mond.",
      "wurde das erste künstliche Herz erfolgreich transplantiert.",
      "wurde das Human Genome Project abgeschlossen.",
      "wurde das erste Klonschaf, Dolly, geboren.",
      "wurde der Large Hadron Collider in Betrieb genommen.",
      "wurde der erste Impfstoff gegen COVID-19 zugelassen.",
      "wurde das erste Bild eines Schwarzen Lochs veröffentlicht.",
      "wurde die erste erfolgreiche Gentherapie bei einem Menschen durchgeführt.",
      "wurde die erste Raumsonde auf dem Mars gelandet.",
      "wurde die Existenz von Gravitationswellen nachgewiesen.",
      "wurde das erste künstliche Organ erfolgreich transplantiert.",
      "wurde die erste CRISPR-Geneditierung bei einem Menschen durchgeführt.",
      "wurde das erste vollständig elektrische Flugzeug getestet.",
      "wurde die erste Quantenkommunikation über Satellit durchgeführt.",
      "wurde die erste erfolgreiche Stammzelltherapie bei einem Menschen durchgeführt.",
      "wurde das erste Bild eines Exoplaneten veröffentlicht."
  };

  private static final String[] SENTENCE_STARTS_WITH_DATE = {
      "Am",
      "Im",
      "An einem",
      "Während des",
      "Zu Beginn des",
      "Gegen Ende des",
      "In der Mitte des",
      "Kurz nach dem",
      "Ungefähr um den",
      "Im Verlauf des",
      "Nach dem",
      "Vor dem",
      "Etwa am"
  };

  private static final String[] SENTENCE_STARTS_WITHOUT_DATE = {
      "Berichten zufolge",
      "Laut einer Ankündigung",
      "Nach den letzten Meldungen",
      "Laut einer Mitteilung",
      "Laut Berichten",
      "Wie dpa berichtet,",
      "Nach Angaben des Behörden",
      "Nach Angaben von Experten"
  };

  private static final int NUM_SENTENCES = 10000;

  @Override
  String[] getSupportedDateFormats() {
    return DATE_FORMATS;
  }

  public static void main(String[] args) {
    String outputFileName;
    if (args.length != 1) {
      outputFileName = "RandomNewsWithGeneratedDates_DE.train";
    } else {
      outputFileName = args[0];
    }
    RandomGermanNewsGenerator newsGen = new RandomGermanNewsGenerator();
    try (BufferedWriter writer = new BufferedWriter(
            new FileWriter(outputFileName))) {
      for (int i = 0; i < NUM_SENTENCES; i++) {
        writer.write(newsGen.generateSentence());
        writer.newLine();
      }
      logger.info("Text corpus with '{}' sentences generated and written to: '{}'",
              NUM_SENTENCES, outputFileName);
    } catch (IOException e) {
      logger.error(e.getLocalizedMessage(), e);
    }
  }

  private String generateSentence() {
    String[] eventTypes = {"sports", "music", "cinema", "economy", "politics", "science"};
    String eventType = eventTypes[new Random().nextInt(eventTypes.length)];

    String event = switch (eventType) {
      case "sports" -> SPORTS_EVENTS[new Random().nextInt(SPORTS_EVENTS.length)];
      case "music" -> MUSIC_EVENTS[new Random().nextInt(MUSIC_EVENTS.length)];
      case "cinema" -> CINEMA_EVENTS[new Random().nextInt(CINEMA_EVENTS.length)];
      case "economy" -> ECONOMY_EVENTS[new Random().nextInt(ECONOMY_EVENTS.length)];
      case "politics" -> POLITICS_EVENTS[new Random().nextInt(POLITICS_EVENTS.length)];
      case "science" -> SCIENCE_EVENTS[new Random().nextInt(SCIENCE_EVENTS.length)];
      default -> "";
    };

    Random random = new Random();
    String sentence;
    if (random.nextDouble() < 0.15) {
      String date = START_DATE + formatDateWithTags(generateRandomDate(cal), Locale.GERMAN) + END;
      String sentenceStart = SENTENCE_STARTS_WITH_DATE[
              new Random().nextInt(SENTENCE_STARTS_WITH_DATE.length)];
      sentence = String.format("%s %s %s", sentenceStart, date, event);
    } else {
      String sentenceStart = SENTENCE_STARTS_WITHOUT_DATE[
              new Random().nextInt(SENTENCE_STARTS_WITHOUT_DATE.length)];
      sentence = String.format("%s %s", sentenceStart, event);
    }
    return sentence;
  }
}
