package concplus;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

public class GUI extends JFrame implements ActionListener, ComponentListener {
    JLabel          startLabel =            new JLabel("start");
    JLabel          endLabel =              new JLabel("end");
    JLabel          targetTimeLabel =       new JLabel("target");
    JLabel          delayLabel =            new JLabel("delay");
    JLabel          widenLabel =            new JLabel("widen");
    JTextField      inputText =             new JTextField();
    JTextField      startText =             new JTextField();
    JTextField      endText =               new JTextField();
    JTextField      originalStartTimeText = new JTextField();
    JTextField      originalEndTimeText =   new JTextField();
    JTextField      targetStartTimeText =   new JTextField();
    JTextField      targetEndTimeText =     new JTextField();
    JTextField      outputText =            new JTextField();
    JTextField      delayText =             new JTextField();
    JTextField      widenText =             new JTextField();
    JButton         chooseFile =            new JButton("input");
    JButton         originalTime =          new JButton("original");
    JButton         calculateModification = new JButton("calculate");
    JButton         writeFile =             new JButton("output");
    JFileChooser    fileChooser =           new JFileChooser();
    File file;
    
    static final int xStart =       5;
    static final int xInter =       5;
    static final int yStart =       5;
    static final int yInter =       5;
    static final int h =            20;
    static final int wButton =      100;
    static final int wLabel =       50;
    static final int wAlphaText =   385;
    static final int wNumText =     135;
    
    public GUI() {
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(510, 35 + 6 * (yInter + h));
        this.addComponentListener(this);
        
        this.add(chooseFile);
        this.add(inputText);
        this.add(startLabel);
        this.add(startText);
        this.add(endLabel);
        this.add(endText);
        this.add(originalTime);
        this.add(originalStartTimeText);
        this.add(originalEndTimeText);
        this.add(targetTimeLabel);
        this.add(targetStartTimeText);
        this.add(targetEndTimeText);
        this.add(calculateModification);
        this.add(delayLabel);
        this.add(delayText);
        this.add(widenLabel);
        this.add(widenText);
        this.add(writeFile);
        this.add(outputText);

        chooseFile.addActionListener(this);
        originalTime.addActionListener(this);
        calculateModification.addActionListener(this);
        writeFile.addActionListener(this);
        
        this.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        BufferedReader inFile;
        PrintWriter outFile;
        String previousLine = "";
        String line;
        int startInt = 0;
        int endInt = 0;
        int delayInt = 0;
        int originalStartTime, originalEndTime, targetStartTime, targetEndTime;
        double widenReal = 0;
        
        if (e.getSource() == chooseFile) {
            if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
                file = fileChooser.getSelectedFile();
                inputText.setText(file.getPath());
                outputText.setText(file.getName().substring(0, file.getName().length() - 3) + "srt");
            }
        }
        
        if (e.getSource() == originalTime) {
            try {
                inFile = new BufferedReader(new FileReader(file));

                try {
                    while ((line = inFile.readLine()) != null) {
                        if (line.matches("[0-9]{2}:.*")) {
                            if (previousLine.equals(startText.getText())) {
                                originalStartTimeText.setText(line.substring(0, 12));
                                targetStartTimeText.setText(line.substring(0, 8));
                            }
                            if (previousLine.equals(endText.getText())) {
                                originalEndTimeText.setText(line.substring(0, 12));
                                targetEndTimeText.setText(line.substring(0, 8));
                            }
                        }

                        previousLine = line;
                    }
                }
                catch (IOException error) {
                    this.errorMessage("error reading");
                }

            }
            catch(FileNotFoundException error) {
                this.errorMessage("error opening for reading");
            }
        }
        
        if (e.getSource() == calculateModification) {
            try {
                originalStartTime = time2ms(originalStartTimeText.getText());
                originalEndTime =   time2ms(originalEndTimeText.getText());
                targetStartTime =   time2ms(targetStartTimeText.getText());
                targetEndTime =     time2ms(targetEndTimeText.getText());
                
                widenReal = (double)(targetEndTime - targetStartTime) / (double)(originalEndTime - originalStartTime);
                delayInt = (int)(targetStartTime - widenReal * originalStartTime);
                
                widenText.setText(Double.toString(widenReal).substring(0, 7));
                delayText.setText(Integer.toString(delayInt));
            }
            catch (NumberFormatException error) {
                this.errorMessage("error parsing");
            }
        }
        
        if (e.getSource() == writeFile) {
            if (widenText.getText().equals("")) {
                widenText.setText("1");
            }
            
            try {
                delayInt = Integer.parseInt(delayText.getText());
                widenReal = Double.parseDouble(widenText.getText());

                try {
                    inFile = new BufferedReader(new FileReader(file));

                    try {
                        outFile = new PrintWriter(new FileWriter(file.getParent() + "/" + outputText.getText()), true);

                        try {
                            while ((line = inFile.readLine()) != null) {
                                outFile.println(modified(line, delayInt, widenReal));
                            }
                        }
                        catch (IOException error) {
                            this.errorMessage("error writing");
                        }

                        outFile.close();
                    }
                    catch(IOException error) {
                        this.errorMessage("error opening for writing");
                    }
                    
                }
                catch(FileNotFoundException error) {
                    this.errorMessage("error opening for reading");
                }
                
            }
            catch (NumberFormatException error) {
                this.errorMessage("error parsing");
            }
        }
    }
    
    String modified(String line, int delayInt, double widenReal) {
        if (line.matches("[0-9]{2}:.*")) {
            line = ms2time(processInput(line, delayInt, widenReal, 0, 12)) + " --> " +
                   ms2time(processInput(line, delayInt, widenReal, 17, 29));
        }
        return line;
    }
    
    int processInput(String line, int delayInt, double widenReal, int begin, int end) {
        return (int)(time2ms(line.substring(begin, end)) * widenReal + delayInt);
    }
    
    int time2ms(String time) {
        int ms;
        
        ms = 3600000 * Integer.parseInt(time.substring(0,2)) +
               60000 * Integer.parseInt(time.substring(3,5)) +
                1000 * Integer.parseInt(time.substring(6,8));
        
        if (time.length() == 12) {
            ms = ms + Integer.parseInt(time.substring(9,12));
        }
        
        return ms;
    }
    
    String ms2time(int ms) {
        DecimalFormat doubleZero = new DecimalFormat("00");
        DecimalFormat tripleZero = new DecimalFormat("000");
        
        int hours   =  ms / 3600000;
        int minutes = (ms - hours * 3600000) / 60000;
        int seconds = (ms - hours * 3600000 - minutes * 60000) / 1000;
        
        return doubleZero.format(hours)   + ":" +
               doubleZero.format(minutes) + ":" +
               doubleZero.format(seconds) + "," +
               tripleZero.format(ms % 1000);
    }
    
    void errorMessage(String text) {
        JOptionPane.showMessageDialog(null, text);
    }

    public void componentResized(ComponentEvent e) {
    }

    public void componentMoved(ComponentEvent e) {
    }

    public void componentShown(ComponentEvent e) {
        chooseFile.setBounds(               xStart,                                                 yStart,                     wButton,    h);
        inputText.setBounds(                xStart +     xInter + wButton,                          yStart,                     wAlphaText, h);
        
        startLabel.setBounds(               xStart +     xInter + wButton,                          yStart + yInter + h,        wLabel,     h);
        startText.setBounds(                xStart + 2 * xInter + wButton +     wLabel,             yStart + yInter + h,        wNumText,   h);
        endLabel.setBounds(                 xStart + 3 * xInter + wButton +     wLabel + wNumText,  yStart + yInter + h,        wLabel,     h);
        endText.setBounds(                  xStart + 4 * xInter + wButton + 2 * wLabel + wNumText,  yStart + yInter + h,        wNumText,   h);
        
        originalTime.setBounds(             xStart,                                                 yStart + 2 * (yInter + h),  wButton,    h);
        originalStartTimeText.setBounds(    xStart + 2 * xInter + wButton +     wLabel,             yStart + 2 * (yInter + h),  wNumText,   h);
        originalEndTimeText.setBounds(      xStart + 4 * xInter + wButton + 2 * wLabel + wNumText,  yStart + 2 * (yInter + h),  wNumText,   h);
        
        targetTimeLabel.setBounds(          xStart +     xInter + wButton,                          yStart + 3 * (yInter + h),  wLabel,     h);
        targetStartTimeText.setBounds(      xStart + 2 * xInter + wButton +     wLabel,             yStart + 3 * (yInter + h),  wNumText,   h);
        targetEndTimeText.setBounds(        xStart + 4 * xInter + wButton + 2 * wLabel + wNumText,  yStart + 3 * (yInter + h),  wNumText,   h);
        
        calculateModification.setBounds(    xStart,                                                 yStart + 4 * (yInter + h),  wButton,    h);
        delayLabel.setBounds(               xStart +     xInter + wButton,                          yStart + 4 * (yInter + h),  wLabel,     h);
        delayText.setBounds(                xStart + 2 * xInter + wButton +     wLabel,             yStart + 4 * (yInter + h),  wNumText,   h);
        widenLabel.setBounds(               xStart + 3 * xInter + wButton +     wLabel + wNumText,  yStart + 4 * (yInter + h),  wLabel,     h);
        widenText.setBounds(                xStart + 4 * xInter + wButton + 2 * wLabel + wNumText,  yStart + 4 * (yInter + h),  wNumText,   h);
        
        writeFile.setBounds(                xStart,                                                 yStart + 5 * (yInter + h),  wButton,    h);
        outputText.setBounds(               xStart +     xInter + wButton,                          yStart + 5 * (yInter + h),  wAlphaText, h);
    }

    public void componentHidden(ComponentEvent e) {
    }
}