package news;

import com.sun.syndication.feed.synd.SyndEntryImpl;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

public class NewsReader extends Application {
    
    private final int WIDTH = 768;
    private final int HEIGHT = 512;
    
    private final List<Story> stories = new ArrayList<>();
    private final Random rng = new Random();
    
    private final String DEUTSCHE_WELLE_NAME = "Deutsche Welle";
    private final String DEUTSCHE_WELLE_URL
            = "http://rss.dw.com/xml/rss-de-deutschlandentdecken";
    
    private final String GOETHE_INSTITUT_NAME = "Goethe Institut";
    private final String GOETHE_INSTITUT_URL
            = "https://www.goethe.de/de/feed/kul.rss";
    
    private final String HELMHOLTZ_ASSOC_NAME = "Helmholtz Association";
    private final String HELMHOLTZ_ASSOC_URL
            = "https://www.helmholtz.de/aktuell/"
            + "presse_und_medien/mediathek/rss_feeds/technologie/";
    
    private final String SUEDDEUTSCHE_ZEITUNG_NAME = "Süddeutsche Zeitung";
    private final String SUEDDEUTSCHE_ZEITUNG_URL
            = "http://rss.sueddeutsche.de/rss/Topthemen";
    
    private final String PRONOUNS_NAME = "Pronouns";
    private final String PRONOUNS_ID = "Pronouns";
    
    private final String DEF_ARTICLES_NAME = "Definite articles";
    private final String DEF_ARTICLES_ID = "Definite articles";
    
    private final String INDEF_ARTICLES_NAME = "Indefinite articles";
    private final String INDEF_ARTICLES_ID = "Indefinite articles";
    
    private final String PREPOSITIONS_NAME = "Prepositions";
    private final String PREPOSITIONS_ID = "Prepositions";
    
    private final String DEFINITE_ARTICLES = 
            "das|den|dem|der|die";
    private final String INDEFINITE_ARTICLES =
            "ein|einem|einen|einer|kein|keinem|keinen|keiner";
    private final String PRONOUNS =
            "er|es|ihn|ihm|ihr|sie|uns|wir";
    private final VBox vBox = new VBox(18);
    
    @Override
    public void init() {
        readChannel(SUEDDEUTSCHE_ZEITUNG_URL);
    } // NewsReader()

    @Override
    public void start(Stage stage) {
        BorderPane topLevel = new BorderPane();
        topLevel.getStyleClass().add("border-pane");
        
        ScrollPane scrollPane = new ScrollPane();
        scrollPane.getStyleClass().add("scroll-pane");
        
        this.vBox.setPrefWidth(WIDTH);
        this.vBox.getStyleClass().add("vbox-flow");
        scrollPane.setContent(this.vBox);
        
        topLevel.setCenter(scrollPane);
        
        MenuItemHandler handler = new MenuItemHandler(this);
        
        MenuBar menuBar = new MenuBar();
        Menu channels = new Menu("Channel");
        menuBar.getMenus().add(channels);
        
        MenuItem channel0 = createMenuItem(DEUTSCHE_WELLE_NAME,
                DEUTSCHE_WELLE_URL, handler);
        MenuItem channel1 = createMenuItem(GOETHE_INSTITUT_NAME,
                GOETHE_INSTITUT_URL, handler);
        MenuItem channel2 = createMenuItem(HELMHOLTZ_ASSOC_NAME,
                HELMHOLTZ_ASSOC_URL, handler);
        MenuItem channel3 = createMenuItem(SUEDDEUTSCHE_ZEITUNG_NAME,
                SUEDDEUTSCHE_ZEITUNG_URL, handler);
        
        channels.getItems().addAll(
                channel0,
                channel1,
                channel2,
                channel3);
        
        Menu partsOfSpeech = new Menu("Parts of speech");
        menuBar.getMenus().add(partsOfSpeech);
        
        MenuItem part0 = createMenuItem(DEF_ARTICLES_NAME,
                DEF_ARTICLES_ID, handler);
        MenuItem part1 = createMenuItem(INDEF_ARTICLES_NAME,
                INDEF_ARTICLES_ID, handler);
        MenuItem part2 = createMenuItem(PREPOSITIONS_NAME,
                PREPOSITIONS_ID, handler);
        MenuItem part3 = createMenuItem(PRONOUNS_NAME,
                PRONOUNS_ID, handler);
        
        partsOfSpeech.getItems().addAll(
                part0,
                part1,
                part2,
                part3);
        
        topLevel.setTop(menuBar);
        
        Scene scene = new Scene(topLevel, WIDTH, HEIGHT);
        scene.getStylesheets().add(NewsReader.class
                .getResource("NewsReader.css")
                .toExternalForm());
        
        stage.setTitle("Nachrichten aus Deutschland");
        stage.setScene(scene);
        stage.show();
    } // start( Stage )

    private MenuItem createMenuItem(String name,
            String url, MenuItemHandler handler) {
        MenuItem result = new MenuItem(name);
        result.setId(url);
        result.setOnAction(handler);
        return result;
    } // createMenuItem( String )

    public void readChannel(String url) {
        boolean ok = false;
        try {
            URL feedUrl = new URL(url);
            
            SyndFeedInput input = new SyndFeedInput();
            XmlReader reader = new XmlReader(feedUrl);
            SyndFeed feed = input.build(reader);
            
            this.stories.clear();
            for (Object o : feed.getEntries()) {
                if (o instanceof SyndEntryImpl) {
                    SyndEntryImpl e = (SyndEntryImpl) o;
                    
                    String title = e.getTitle();
                    String description = e.getDescription().getValue();
                    String link = e.getLink();
                    
                    description = description.replaceAll("<p>|</p>", "");
                    
                    Story story = new Story(title, description, link);
                    
                    this.stories.add(story);
                } // if
            } // for

            ok = true;
        } // try
        catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("ERROR: " + ex.getMessage());
        } // catch( Exception )

        if (!ok) {
            System.out.println();
            System.out.println("FeedReader reads and prints "
                    + "any RSS/Atom feed type.");
            System.out.println("The first parameter must be "
                    + "the URL of the feed to read.");
            System.out.println();
        } // if

        this.vBox.getChildren().clear();
        for (Story story : this.stories) {
            
            TextFlow titleFlow = new TextFlow();
            Text title = new Text(story.getTitle());
            titleFlow.getChildren().add(title);
            title.getStyleClass().add("story-title");
            
            TextFlow descriptionFlow = new TextFlow();
            ObservableList<Node> children = descriptionFlow.getChildren();
            String sentence = story.getDescription();
            for (String word : sentence.split(" ")) {
                Text descriptionWord = new Text(word + " ");
                if (word.toLowerCase().matches(DEFINITE_ARTICLES)) {
                    descriptionWord.getStyleClass().add("definite-article");
                } // if
                else if( word.toLowerCase().matches(INDEFINITE_ARTICLES)) {
                    descriptionWord.getStyleClass().add("indefinite-article");
                } // else if
                else {
                    descriptionWord.getStyleClass().add("story-description");
                } // else
                children.add(descriptionWord);
            } // for
            descriptionFlow.setPrefWidth(WIDTH / 2);
            
            VBox storyBox = new VBox(6);
            storyBox.getChildren().addAll(titleFlow, descriptionFlow);
            
            this.vBox.getChildren().add(storyBox);
        } // for
    } // readChannel( String )

    public static void main(String[] args) {
        launch(args);
    } // main( String [] )

} // NewsReader
