package com.greinet.tvtotalripper.ui;

import com.greinet.tvtotalripper.crawler.CrawlerUtil;
import com.greinet.tvtotalripper.crawler.EpisodeWrapper;
import com.greinet.tvtotalripper.download.DownloadTask;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

/**
 *
 * @author agreiner
 */
public class RipperWindow {
    /** The pane managing the tabs */
    private final JTabbedPane tabbedPane;
    /** The panel for the shows */
    private JComponent panel1;
    /** The panel for the seasons */
    private JComponent panel2;
    /** The panel for the episodes */
    private JComponent panel3;
    /** The panel for the downloads */
    private final JComponent panel4;
    /** The panel for the settings */
    private final JComponent panel5;
    /** The show panel */
    private final BaseRipperPanel showRipperPanel;
    /** The settings panel */
    private final SettingsRipperPanel srp;
    /** The downloads panel */
    private final DownloadRipperPanel drp;
    
    /**
     * Create the main application UI
     */
    public RipperWindow(){
        JFrame frame = new JFrame("TV Total Ripper");
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                
                try {
                    ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c","taskkill /F /IM chromedriver.exe /T");
                    builder.redirectErrorStream(true);
                    Process p = builder.start();
                    BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
                    String line;
                    while (true) {
                        line = r.readLine();
                        if (line == null) { break; }
                    }
                } catch (IOException ex) {
                    Logger.getLogger(RipperWindow.class.getName()).log(Level.SEVERE, null, ex);
                }
                System.exit(0);
            }
        });
        
        
        tabbedPane = new JTabbedPane();
        
        showRipperPanel = createShowsPanel();
        srp = new SettingsRipperPanel();
        drp = new DownloadRipperPanel();
        
        panel1 = showRipperPanel.getJPanel();
        panel2 = new JPanel();
        panel3 = new JPanel();
        panel4 = drp.getJPanel();
        panel5 = srp.getPanel();
        
        tabbedPane.addTab("Shows", panel1);
        tabbedPane.addTab("Seasons", panel2);
        tabbedPane.addTab("Episodes", panel3);
        tabbedPane.addTab("Downloads", panel4);
        tabbedPane.addTab("Settings", panel5);
        
        tabbedPane.setEnabledAt(1, false);
        tabbedPane.setEnabledAt(2, false);
        
        tabbedPane.setPreferredSize(new Dimension(900, 400));
        
        frame.add(tabbedPane);
        
        frame.pack();
        frame.setAlwaysOnTop(true);
        frame.setVisible(true);
    }
    
    /**
     * The main method to start the program
     * @param args the arguments
     */
    public static void main(String[] args) {
        RipperWindow ripperWindow = new RipperWindow();
    }
    
    /**
     * Create a show panel listing all available shows
     * @return the shopw panel
     */
    private BaseRipperPanel createShowsPanel(){
        List<WebElement> shows = CrawlerUtil.getShows();
        Map<String, String> namesToUrls = shows.stream().collect(Collectors.toMap(e -> e.findElement(By.xpath(".//img")).getAttribute("alt") , e -> e.getAttribute("href")));
        
        BaseRipperPanel brp = new BaseRipperPanel(namesToUrls);
        
        brp.getJButton().addActionListener((ActionEvent e) -> {
            panel3 = new JPanel();
            tabbedPane.setEnabledAt(2, false);
            panel1 = createSeasonsPanel(brp.getCurrentSelected()).getJPanel();
            tabbedPane.setComponentAt(1, panel1);
            tabbedPane.setEnabledAt(1, true);
            tabbedPane.setSelectedIndex(1);
        });
        
        return brp;
    }
    
    /**
     * Create a seaon panel for a selected show
     * @param url the URL to the show
     * @return the season panel
     */
    private BaseRipperPanel createSeasonsPanel(String url){
        List<WebElement> seasons = CrawlerUtil.getSeasons(url);
        Map<String, String> elements = seasons.stream().collect(Collectors.toMap(e -> e.getText(), e -> e.getText()));
        
        BaseRipperPanel brp = new BaseRipperPanel(elements);
        
        brp.getJButton().addActionListener((ActionEvent e) -> {
            tabbedPane.setEnabledAt(2, false);
            panel2 = createEpisodesPanel(url,brp.getCurrentSelected()).getJPanel();
            tabbedPane.setComponentAt(2, panel2);
            tabbedPane.setEnabledAt(2, true);
            tabbedPane.setSelectedIndex(2);
        });
        
        return brp;
    }
    
    /**
     * Create a episode panel
     * @param url the URL to the episode list
     * @param seasonName the name of the selected season
     * @return the episode panel
     */
    private EpisodesRipperPanel createEpisodesPanel(String url, String seasonName){
        List<EpisodeWrapper> episodes = CrawlerUtil.getEpisodes(url, seasonName);
        
        EpisodesRipperPanel erp = new EpisodesRipperPanel(episodes);
        
        erp.getDownloadButton().addActionListener((ActionEvent e) -> {
            drp.addTask(new DownloadTask(erp.getCurrentSelected()));
        });
        
        erp.getDownloadAllButton().addActionListener((ActionEvent e) -> {
            episodes.forEach(d -> drp.addTask(new DownloadTask(d)));
        });
        return erp;
    }
    
}