/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package wordanalyzer;
import java.util.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.concurrent.TimeUnit;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.util.*;

/**
 *
 * @author i
 */
public class WordAnalyzer {
    public static int MAX_DUPLICATION_COUNT = 0;
    public static int MIN_DUPLICATION_COUNT = 0;
    public static int MAX_FILE_COUNT = 0;
    public static final String DIVIDING_LINE_SINGLE = "______________________________________________________________________________________\n";
    public static final String DIVIDING_LINE_DOUBLE = "======================================================================================\n";
    public static final String FOLDERPATH_HDR = "[FOLDER PATH] ";
    public static final String ERR_FILENOTFOUND_MSG = "[ERROR] PDF FILE NOT FOUND";
    public static final String ERR_FILEENCRYPTED_MSG = "[ERROR] PDF FILE IS ENCRYPTED";
    public static final String ERR_FOLDERPATHNOTEXISTS_MSG = "[ERROR] FOLDER PATH NOT EXISTS";
    public static final String INTRODUCTION = "WELCOME TO WORD ANALYZER!\nAUTHOR: JUYOUNG LEE  LAST UPDATED: 10-30-2014  VERSION: 1.0\n";
    public static Map<String, Integer> map = new TreeMap<>();
    
    public static int fileCount = 0;
    public static String folderPath;
    public static long startTime = 0, finishTime = 0;
    
    
    //public static JLabel textLabel = new JLabel();
    public static JTextArea textArea = new JTextArea(14, 55);
    public static JTextArea textAreaResultWindow = new JTextArea(8, 55);
    public static JScrollPane scrollPane = new JScrollPane(textArea);
    public static JScrollPane scrollPaneResultWindow = new JScrollPane(textAreaResultWindow);
    public static JButton btnConfirmFolderPath = new JButton(" Confirm Folder Path ");   
    
    /**
     * @param args the command line arguments
     */
    
    public static void main(String[] args){
        window();

    }
    
    public static void window(){
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        double width = screenSize.getWidth();
        double height = screenSize.getHeight();

        //Create and set up the window.
        JFrame frame = new JFrame("Word Analyzer");
        JPanel panel = new JPanel();
        
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");
        JMenu viewMenu = new JMenu("View");
        JMenu toolsMenu = new JMenu("Tools");
        JMenu windowMenu = new JMenu("Window");
        JMenu helpMenu = new JMenu("Help");
        
        JMenuItem newAction = new JMenuItem("New");
        JMenuItem openAction = new JMenuItem("Open");
        JMenuItem saveAction = new JMenuItem("Save");
        JMenuItem exitAction = new JMenuItem("Exit");
        
        frame.setJMenuBar(menuBar);
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(viewMenu);
        menuBar.add(toolsMenu);
        menuBar.add(windowMenu);
        menuBar.add(helpMenu);
        fileMenu.add(newAction);
        fileMenu.add(openAction);
        fileMenu.add(saveAction);
        fileMenu.add(exitAction);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setMinimumSize(new Dimension((int)(width * 0.5),(int)(height * 0.7)));
        
        //JLabel textLabel = new JLabel("This is a label in the window",SwingConstants.CENTER);
        //frame.getContentPane().add(textLabel, BorderLayout.CENTER);
        
        //Display the window.
        frame.setLocationRelativeTo(null); // centers a frame onscreen.
        frame.pack();
        frame.setVisible(true);
        frame.setResizable(false);
        
        JTextField txtboxFolderPath = new JTextField(34);
        txtboxFolderPath.setMargin(new Insets(2, 2, 2, 2));
        txtboxFolderPath.setText("C:\\");
        
        JLabel lblMaxDupCount = new JLabel("MAX. DUP. COUNT: ");
        JTextField txtboxMaxDupCount = new JTextField(5);
        txtboxMaxDupCount.setMargin(new Insets(2, 2, 2, 2));
        txtboxMaxDupCount.setText("0");
        JLabel lblMinDupCount = new JLabel("MIN. DUP. COUNT: ");
        JTextField txtboxMinDupCount = new JTextField(5);
        txtboxMinDupCount.setMargin(new Insets(2, 2, 2, 2));
        txtboxMinDupCount.setText("0");
        JLabel lblMaxFileCount = new JLabel("MAX. FILE COUNT (OPTIONAL): ");
        JTextField txtboxMaxFileCount = new JTextField(5);
        txtboxMaxFileCount.setMargin(new Insets(2, 2, 2, 2));
        //textLabel.setFont(new Font("Serif", Font.PLAIN, 14));
        //textLabel.setVerticalTextPosition(JLabel.BOTTOM);
        //textLabel.setHorizontalTextPosition(JLabel.CENTER);
        
        //JLabel textLabel = new JLabel();
        
        textArea.setEditable(false);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setText(DIVIDING_LINE_SINGLE + INTRODUCTION + DIVIDING_LINE_DOUBLE);
        textArea.setMargin(new Insets(10,10,10,10));
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        
        textAreaResultWindow.setEditable(false);
        textAreaResultWindow.setLineWrap(true);
        textAreaResultWindow.setWrapStyleWord(true);
        textAreaResultWindow.setMargin(new Insets(10,10,10,10));
        scrollPaneResultWindow.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        
        JButton btnStopScan = new JButton(" Stop Scan ");
        btnStopScan.setEnabled(false);
        
        btnStopScan.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                btnStopScan.setEnabled(false);
                btnConfirmFolderPath.setEnabled(true);
            }
        });
        
        //btnConfirmFolderPath.setEnabled(true);
        
        btnConfirmFolderPath.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                String strMinDupCount = txtboxMinDupCount.getText();
                String strMaxDupCount = txtboxMaxDupCount.getText();
                String strMaxFileCount = txtboxMaxFileCount.getText();
                try{
                    MIN_DUPLICATION_COUNT = Integer.parseInt(strMinDupCount);
                } catch (Exception ex){
                    MIN_DUPLICATION_COUNT = 0;
                }
                try{
                    MAX_DUPLICATION_COUNT = Integer.parseInt(strMaxDupCount);
                } catch (Exception ex){
                    MAX_DUPLICATION_COUNT = 0;
                }
                try{
                    MAX_FILE_COUNT = Integer.parseInt(strMaxFileCount);
                } catch (Exception ex){
                    MAX_FILE_COUNT = 1000000000;
                }
                btnConfirmFolderPath.setEnabled(false);
                folderPath = txtboxFolderPath.getText();
                startTime = System.currentTimeMillis();
                textAreaResultWindow.append(DIVIDING_LINE_SINGLE + "[RESULT] DUP WORD (DUP TIMES)\n");
                scanner();
                btnConfirmFolderPath.setEnabled(true);
                finishTime = System.currentTimeMillis();
                String exeTime = millisToShortDHMS(finishTime - startTime);
                textArea.insert("[SCAN COMPLETED] " + folderPath +"\n" ,0);
                textArea.append("[LOG] SCANNED FOLDER: " + folderPath  + "\n[LOG] NUMBER OF FILES SCANNED: " + fileCount + "\n"
                        +"[LOG] TOTAL TIME: " + exeTime + "\n" + DIVIDING_LINE_SINGLE);
                textArea.insert(DIVIDING_LINE_SINGLE, 0);
                textArea.update(textArea.getGraphics());
                textArea.setCaretPosition(textArea.getDocument().getLength());
            }
        });
    
        
        //panel.setLayout(new GridLayout(1, 1));

        frame.add(panel);
        panel.add(txtboxFolderPath);
        panel.add(btnConfirmFolderPath);
        panel.add(btnStopScan);
        panel.add(lblMinDupCount);
        panel.add(txtboxMinDupCount);
        panel.add(lblMaxDupCount);
        panel.add(txtboxMaxDupCount);
        panel.add(lblMaxFileCount);
        panel.add(txtboxMaxFileCount);
        //panel.add(textLabel);
        //panel.add(textArea); // I don't need to add textArea again into other container <http://stackoverflow.com/questions/10177183/java-add-scroll-into-text-area>
        panel.add(scrollPane);
        panel.add(scrollPaneResultWindow);
    }
    
    public static void scanner(){
        PDDocument pdfDoc;
        BufferedWriter wrtTxt;
        File folder = new File(folderPath);
        File[] listOfFiles = folder.listFiles();
        fileCount = 0; //initialize fileCount every time
        textArea.insert(FOLDERPATH_HDR + folderPath + "\n", 0);
        textArea.update(textArea.getGraphics());
        try{
            if(!folder.exists()){
                textArea.insert(ERR_FOLDERPATHNOTEXISTS_MSG + "\n", 0);
                textArea.update(textArea.getGraphics());
                btnConfirmFolderPath.setEnabled(true);
            }
        } catch(Exception e){
            
        }
        
        
        for (File listOfFile : listOfFiles) {
            //System.out.println(listOfFile);
            String fileInputPath = listOfFile.getAbsolutePath(); // path
            fileCount++;
            textArea.insert("[" + fileCount + "/" + folder.listFiles().length + "] SCANNED FILE PATH: " +  fileInputPath + "\n", 0);
            textArea.update(textArea.getGraphics());
            //System.out.println("[" + fileCount + "/" + folder.listFiles().length + "] Scanned File Path: " +  fileInputPath);
            String fileOutputPath = fileInputPath.substring(0, fileInputPath.length() - 4);
            
            //System.out.println(fileOutputPath);
            if(! ".pdf".equals(fileInputPath.substring(fileInputPath.length() - 4)) ){
                textArea.insert(ERR_FILENOTFOUND_MSG + "\n", 0);
                textArea.update(textArea.getGraphics());
                //System.out.println(ERR_FILENOTFOUND_MSG);
            }
            else{
                try {
                    File input = new File(fileInputPath);  // The PDF file from where you would like to extract
                    File output = new File(fileOutputPath + ".txt"); // The text file where you are going to store the extracted data
                    pdfDoc = PDDocument.load(input);
                    //System.out.println(pdfDoc.getNumberOfPages());
                    if(pdfDoc.isEncrypted()){
                        textArea.insert(ERR_FILEENCRYPTED_MSG + "\n", 0);
                        textArea.update(textArea.getGraphics());
                        //System.out.println(ERR_FILEENCRYPTED_MSG);
                    }
                    //pdfDoc.save("CopyOfInvoice.pdf"); // Creates a copy called "CopyOfInvoice.pdf"
                    PDFTextStripper stripper = new PDFTextStripper();
                    String text = stripper.getText(pdfDoc);
                    text = text.replaceAll("[^a-zA-Z0-9\uAC00-\uD7A3 -]", " ");
                    text = text.trim();
                    String textSplited[] = text.split("\\s+");
                    //System.out.println(text);
                    for (int i = 0; i < textSplited.length; i++) {
                        text = textSplited[i];
                        map.put(text, (map.get(text) == null ? 1 : (map.get(text) + 1)) );
                    }
                    //System.out.println(text);
                    wrtTxt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(output)));
                    stripper.writeText(pdfDoc, wrtTxt);
                    if (pdfDoc != null) {
                        pdfDoc.close();
                    }
                    // I use close() to flush the stream.
                    wrtTxt.close();
                    output.delete();
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
            for (String key : map.keySet()){
                
                if( (map.get(key) >= MIN_DUPLICATION_COUNT)&&(map.get(key) <= MAX_DUPLICATION_COUNT) ){
                    if(fileCount == folder.listFiles().length){
                        textAreaResultWindow.append(key + " ("+ map.get(key) +")\n");
                        textAreaResultWindow.update(textAreaResultWindow.getGraphics());
                        //System.out.println("[Result] Dup Word: Dup Times = " + key + ": "+ map.get(key));
                    }
                    /*display results for each file
                    if(fileCount == scanCount){
                        textArea.insert("[SCAN COMPLETED] " + folderPath ,0);
                    }*/
                }
                
            }
            
        }
        
        
    }
    
    
    
    public static String millisToShortDHMS(long duration) {
    String res;
    long days  = TimeUnit.MILLISECONDS.toDays(duration);
    long hours = TimeUnit.MILLISECONDS.toHours(duration)
                   - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
                     - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
                   - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    String wordSecond = "SECOND", wordMinute ="MINUTE", wordHour = "HOUR", wordDay = "DAY";
    if(seconds > 1){
        wordSecond = "SECONDS";
    }
    if(minutes > 1){
        wordMinute = "MINUTES";
    }
    if(hours > 1){
        wordHour = "HOURS";
    }
    if(days > 1){
        wordDay = "DAYS";
    }
    
    
    if (minutes == 0 && hours == 0 && days == 0) {
        res = String.format("%d " + wordSecond, seconds);
    }
    else if (hours == 0 && days == 0){
        res = String.format("%d " + wordMinute +" %d " + wordSecond, minutes, seconds);
    }
    else if (days == 0){
        res = String.format("%d " + wordHour + " %d " + wordMinute + " %d " + wordSecond, hours, minutes, seconds);
    }
    else{
        res = String.format("%d "+ wordDay + "%d " + wordHour + " %d " + wordMinute + " %d " + wordSecond, days, hours, minutes, seconds);
    }
    return res;
  }
    
    
}
