#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

# Load Libraries
v_required_packages <- c("shiny", "shinythemes", "shinyjs", 
                         "dplyr", "pdftools", "tm", "wordcloud", 
                         "DT", "readr", "textclean", "SnowballC")

for (v_package in v_required_packages) {
    if(v_package %in% rownames(installed.packages()) == FALSE) 
    {
        install.packages(v_package, dependencies=TRUE)
    }
}

library(shiny)
library(shinythemes)
library(shinyjs)
## 
## Attaching package: 'shinyjs'
## The following object is masked from 'package:shiny':
## 
##     runExample
## The following objects are masked from 'package:methods':
## 
##     removeClass, show
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(pdftools)
library(tm)
## Loading required package: NLP
library(wordcloud)
## Loading required package: RColorBrewer
library(DT)
## 
## Attaching package: 'DT'
## The following objects are masked from 'package:shiny':
## 
##     dataTableOutput, renderDataTable
library(readr)
library(textclean)
library(SnowballC)

C_SLIDER_DEFAULT_VALUE <- 50
C_TEXT_FILE_INDICATOR <- "TXT"
C_PDF_FILE_INDICATOR <- "PDF"

v_df <- reactive({
    data.frame(ind = c("test1", "test2"), n = c(10, 20))
})

v_prev_file_type <- C_TEXT_FILE_INDICATOR

gatherFileStatistics <- function(p_input_file_name) {
    v_file_name <- p_input_file_name
    v_generation_date <- format(Sys.Date(), "%Y-%m-%d")
    v_total_words <- nrow(v_df())

    ### Form the record
    v_record <- tibble(
        v_file_name, 
        v_generation_date, 
        v_total_words
    )
    
    return(v_record)
}

# Define UI for application
ui <- fluidPage(
    shinyjs::useShinyjs(),
    theme = shinytheme("united"),
    tags$head(
        tags$style(
            HTML(".shiny-notification {
                             position:fixed;
                             top: calc(50%);
                             left: calc(50%);
                             font-family:Verdana;
                             fontSize:xx-large;
                             }
                             "
            )
        )
    ),
    
    # Application title
    fluidRow(
        column(width = 3,
               img(src="ParthaInPetra.jpg", width=200, height=112)
        ),
        column(width = 6,
               h1("ShabdhMegh", style="color:blue; text-align: center;"),
               h3("Word Cloud Producer", style="color:darkred; text-align: center;")
        ),
        column(width = 3,
               h4("...", style="color:blue; text-align: right;"),
               h4("Developed by: Partha Majumdar", style="color:blue; text-align: right;"),
               h5("Riyadh (Saudi Arabia), 30-December-2019", style="color:black; text-align: right;")
        )
    ),
    
    fluidRow(
        column(width =  4,
               wellPanel(
                   radioButtons("v_file_type", h3("Select the File Type to Upload"),
                                c("Text File" = C_TEXT_FILE_INDICATOR,
                                  "PDF File" = C_PDF_FILE_INDICATOR),
                                inline = TRUE),
                   fluidRow(
                       h3("Select a file from your Computer to get started to analyse the contents of the file.", style="color:blue; text-align: center;"),
                       h4("Please select a FILE, before clicking on any TAB. This is a bug in the system.", style="color:darkred; text-align: center;"),
                       fileInput("v_input_file_txt", h3("Choose Text File"),
                                 multiple = FALSE, placeholder = "No file selected",
                                 accept = c("text/csv",
                                            "text/comma-separated-values,text/plain",
                                            ".txt")
                                 ),
                       fileInput("v_input_file_pdf", h3("Choose PDF File"),
                                 multiple = FALSE, placeholder = "No file selected",
                                 accept = c("application/PDF",
                                            ".pdf")
                       )
                   ),
                   fluidRow(
                       wellPanel(
                           p("To learn how to use SaabdhMegh, visit the ",
                             a("SaabdhMegh Demonstration Video.", 
                               href = "https://youtu.be/iAxIHqfEZsc", 
                               target="_blank")
                           )
                       )
                   ),
                   fluidRow(
                       downloadButton("report", "Download Report")
                   )
               )
        ),
        column(width = 8,
               fluidRow(
                   div(id = "DummyDisplay",
                       img(src="CourseLogo.jpg", width=1200, height=900)
                   ),
                   div(id = "OutputTabsPDF",
                       tabsetPanel(id = "mainTabsetPDF", type = "tabs",
                               tabPanel("DATA",
                                        h3("Word Frequency"),
                                        dataTableOutput("PDFcontents")
                                ),
                                tabPanel("Word Cloud",
                                        sliderInput("v_number_of_words_pdf",
                                                    h4("Set Number of Words to Display"), 
                                                    min = 20, max = 500, 
                                                    value = C_SLIDER_DEFAULT_VALUE, 
                                                    step = 10, ticks = TRUE),
                                        plotOutput("wordCloudPDF",  width = "100%")
                                )
                       )
                   ),
                   div(id = "OutputTabsTXT",
                       tabsetPanel(id = "mainTabsetTXT", type = "tabs",
                                   tabPanel("DATA",
                                            h3("Word Frequency"),
                                            dataTableOutput("TXTcontents")
                                   ),
                                   tabPanel("Word Cloud",
                                            sliderInput("v_number_of_words_txt",
                                                        h4("Set Number of Words to Display"), 
                                                        min = 20, max = 500, 
                                                        value = C_SLIDER_DEFAULT_VALUE, 
                                                        step = 10, ticks = TRUE),
                                            plotOutput("wordCloudTXT",  width = "100%")
                                   )
                       )
                   )
               )
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output, session) {
    observe({
        if ( input$v_file_type == C_TEXT_FILE_INDICATOR ) {
            shinyjs::hide("v_input_file_pdf")
            shinyjs::show("v_input_file_txt")
        } else {
            shinyjs::show("v_input_file_pdf")
            shinyjs::hide("v_input_file_txt")
        }

        if ( (is.null(input$v_input_file_pdf) || input$v_input_file_pdf == "") &&
             (is.null(input$v_input_file_txt) || input$v_input_file_txt == "")
            )
        {
            shinyjs::show("DummyDisplay")
            shinyjs::hide("OutputTabsPDF")
            shinyjs::hide("OutputTabsTXT")
            shinyjs::disable("report")
        } else {
            if ( input$v_file_type == C_TEXT_FILE_INDICATOR ) {
                if (is.null(input$v_input_file_txt) || input$v_input_file_txt == "")
                {
                    shinyjs::hide("OutputTabsTXT")
                    shinyjs::show("DummyDisplay")
                    shinyjs::disable("report")
                } else {
                    if (v_prev_file_type == C_PDF_FILE_INDICATOR) {
                        shinyjs::hide("OutputTabsTXT")
                        shinyjs::show("DummyDisplay")
                        shinyjs::disable("report")
                    } else {
                        shinyjs::show("OutputTabsTXT")
                        shinyjs::hide("DummyDisplay")
                        shinyjs::enable("report")
                    }
                }
                shinyjs::hide("OutputTabsPDF")
                v_prev_file_type <<- C_TEXT_FILE_INDICATOR
            } else {
                if (is.null(input$v_input_file_pdf) || input$v_input_file_pdf == "")
                {
                    shinyjs::hide("OutputTabsPDF")
                    shinyjs::show("DummyDisplay")
                    shinyjs::disable("report")
                } else {
                    if (v_prev_file_type == C_TEXT_FILE_INDICATOR) {
                        shinyjs::hide("OutputTabsPDF")
                        shinyjs::show("DummyDisplay")
                        shinyjs::disable("report")
                    } else {
                        shinyjs::show("OutputTabsPDF")
                        shinyjs::hide("DummyDisplay")
                        shinyjs::enable("report")
                    }
                }
                shinyjs::hide("OutputTabsTXT")
                v_prev_file_type <<- C_PDF_FILE_INDICATOR
            }
        }
    })
    
    observeEvent(input$v_input_file_pdf, {
        # Reset Display to DATA TAB
        updateTabsetPanel(session, "mainTabsetPDF",
                          selected = "DATA"
        )
        
        # Reset the Slider
        updateSliderInput(session, 'v_number_of_words_pdf', value = C_SLIDER_DEFAULT_VALUE)
    })
    
    observeEvent(input$v_input_file_txt, {
        # Reset Display to DATA TAB
        updateTabsetPanel(session, "mainTabsetTXT",
                          selected = "DATA"
        )
        
        # Reset the Slider
        updateSliderInput(session, 'v_number_of_words_txt', value = C_SLIDER_DEFAULT_VALUE)
    })
    
    output$PDFcontents <- renderDataTable({
        
        # input$v_input_file_pdf will be NULL initially. After the user selects
        # and uploads a file, data will be shown.
        # cat(paste("Point 1: ***", input$v_input_file, "+++\n", sep = ''), file = stderr())
        req(input$v_input_file_pdf)
        
        v_df <<- reactive({
            # Read the PDF File
            v_raw_text <- pdf_text(input$v_input_file_pdf$datapath) %>% 
                            strsplit("\n")

            # Calculate Word Frequency            
            calculateWordFrequency(v_raw_text)
        })
        
        ## Gather Statistics and Save Statistics
        writeStatistics(input$v_input_file_pdf$name)
        
        displayDataTable()
    })
    
    output$TXTcontents <- renderDataTable({
        
        # input$v_input_file_pdf will be NULL initially. After the user selects
        # and uploads a file, data will be shown.
        # cat(paste("Point 1: ***", input$v_input_file, "+++\n", sep = ''), file = stderr())
        req(input$v_input_file_txt)
        
        v_df <<- reactive({
            # Read the TXT File
            v_text <- tibble(text = gsub("[^[:alnum:]///' ]", "", 
                                   read_lines(input$v_input_file_txt$datapath)))

            # Drop the Empty Lines
            v_raw_text <- drop_empty_row(v_text)

            # Calculate Word Frequency            
            calculateWordFrequency(v_raw_text)
        })
        
        ## Gather Statistics and Save Statistics
        writeStatistics(input$v_input_file_txt$name)

        displayDataTable()
    })

    writeStatistics <- function(l_file_name) {
        v_record <- gatherFileStatistics(l_file_name)
        if(file.exists("./ShabdhMegh_statistics.csv")) {
            v_statistics1 <- read.csv("./ShabdhMegh_statistics.csv")
            v_statistics1$X <- NULL
            v_statistics <- rbind(v_statistics1, v_record)
        } else {
            v_statistics <- v_record
        }
        write.csv(v_statistics, file = "./ShabdhMegh_statistics.csv")
    }
    
    displayDataTable <- function() {
        DT::datatable(
            { v_df() },
            caption = htmltools::tags$caption(
                style = 'caption-side: bottom; text-align: center;',
                'Table 1: ', htmltools::em('Word Frequency.')
            ),
            extensions = 'Buttons',
            
            options = list(
                fixedColumns = TRUE,
                autoWidth = TRUE,
                ordering = TRUE,
                dom = 'Bftsp',
                buttons = c('copy', 'csv', 'excel')
            ))
    }
    
    calculateWordFrequency <- function(l_text) {
        v_data <- reactive({
            # Create the Corpus
            v_corpus <- Corpus(VectorSource(l_text))
            
            # Create the Term Document Matrix after cleaning the Corpus
            v_tdm <- TermDocumentMatrix(v_corpus, 
                                        control = 
                                            list(removePunctuation = TRUE,
                                                 stopwords = TRUE,
                                                 tolower = TRUE,
                                                 stemming = TRUE,
                                                 removeNumbers = TRUE,
                                                 bounds = list(global = c(1, Inf))
                                            )
            )
            
            # Find the Frequent Words
            v_ft <- findFreqTerms(v_tdm, lowfreq = 1, highfreq = Inf)
            
            # Convert to a Matrix
            v_matrix <- as.matrix(v_tdm[v_ft,])
            
            # Sort the Words in DESCENDING Order and create Data Frame
            stack(sort(apply(v_matrix, 1, sum), decreasing = TRUE))
        })
        
        return (v_data())
    }
    
    ######## WORD CLOUD
    output$wordCloudPDF <- renderPlot({
        req(input$v_input_file_pdf)

        generateWordCloud(input$v_number_of_words_pdf)
    })
    
    ######## WORD CLOUD
    output$wordCloudTXT <- renderPlot({
        req(input$v_input_file_txt)

        generateWordCloud(input$v_number_of_words_txt)
    })
    
    generateWordCloud <- function(l_number_of_words) {
        withProgress(message = 'Generating',
                     detail = 'This may take a while...', value = 0, {
                         wordcloud(words = v_df()$ind, freq = v_df()$values, min.freq = 1,
                                   max.words = l_number_of_words,
                                   random.order=FALSE,
                                   colors=brewer.pal(8, "Dark2")
                         )
                     })
    }
    
    output$report <- downloadHandler(
        # For PDF output, change this to "report.pdf"
        filename <- "report.pdf",
        
        content <- function(file) {
            withProgress(message = 'Generating Report. This takes a minute or two...', value = 0, {
                if (input$v_file_type == C_TEXT_FILE_INDICATOR) {
                    l_file_name <- input$v_input_file_txt$name
                    l_words_to_display <- input$v_number_of_words_txt
                } else {
                    l_file_name <- input$v_input_file_pdf$name
                    l_words_to_display <- input$v_number_of_words_pdf
                }
                
                # Set up parameters to pass to Rmd document
                v_params <- list(
                    p_input_file = l_file_name,
                    p_number_of_words_to_display = l_words_to_display,
                    p_word_frequency = v_df()
                )
                
                # Knit the document, passing in the `params` list, and eval it in a
                # child of the global environment (this isolates the code in the document
                # from the code in this app).
                rmarkdown::render("ShabdhMegh.Rmd",
                                  output_file = file,
                                  params = v_params,
                                  envir = new.env(parent = globalenv())
                )
            })
        }
    )
}

# Run the application 
shinyApp(ui = ui, server = server)
## 
## Listening on http://127.0.0.1:4174