library(shiny)
library(bslib)
library(ggplot2)
library(cowplot)
library(LRErdd)
library(DT)
library(openxlsx)
library(shinycssloaders)

# Theme -------------------------------------------------------------------

app_theme <- bs_theme(
  version = 5,
  primary = "#2C5F8A",
  secondary = "#6C757D",
  success = "#2E8B57",
  base_font = font_collection("Inter", "Segoe UI", "system-ui", "sans-serif"),
  heading_font = font_collection("Inter", "Segoe UI", "system-ui", "sans-serif"),
  "navbar-bg" = "#2C5F8A"
)

run_button <- function(id, label = "Run analysis", icon_name = "play") {
  actionButton(id, label, icon = icon(icon_name), class = "btn-primary w-100 mt-2")
}

# UI ----------------------------------------------------------------------

ui <- page_navbar(
  title = span(icon("chart-line"), "LRErdd"),
  window_title = "LRErdd - RD Designs as Local Randomized Experiments",
  id = "main_nav",
  theme = app_theme,
  fillable = FALSE,

  # . Welcome ---------------------------------------------------------------
  nav_panel(
    "Welcome", value = "nav_intro", icon = icon("house"),
    layout_columns(
      col_widths = 12,
      card(
        card_header(h4(class = "mb-0", "What you can do with LRErdd")),
        card_body(
          h5("Regression Discontinuity Designs as Local Randomized Experiments"),
          p("The LRErdd package includes a set of functions for the design and analysis of
            Regression Discontinuity Designs as local randomized experiments within the
            potential outcome approach as formalized in Li, Mattei and Mealli (2015).
            A subset of functions implements the design phase of the study, where the focus is
            on the selection of suitable subpopulations for which we can draw valid causal
            inference. These functions provide summary statistics of pre- and post-treatment
            variables by treatment status and select suitable subpopulations around the
            threshold where pre-treatment variables are well balanced between treatment
            groups, using randomization-based tests with adjustment for multiplicities.
            Functions for a visual inspection of the results are also provided. Finally, the
            package includes a set of functions for drawing inference on causal effects for
            the selected subpopulations using randomization-based modes of inference.
            Specifically, the Fisher Exact p-value and Neyman approaches are implemented for
            the analysis of both sharp and fuzzy RD designs. We illustrate the approach in a
            study concerning the effects of university grants on student dropout."),
          p(class = "text-muted small",
            "Li F, Mattei A, Mealli F (2015). Bayesian inference for regression discontinuity
             designs with application to the evaluation of Italian university grants.",
            em("The Annals of Applied Statistics"), ", 9(4), 1906-1931. doi:10.1214/15-AOAS809")
        )
      ),
      card(
        card_header(h4(class = "mb-0", "Workflow")),
        card_body(
          p("The analysis follows five sequential steps, available in the navigation bar above:"),
          img(src = "Squeme.jpg", style = "max-width: 100%; height: auto;",
              alt = "Workflow of the LRErdd application")
        )
      ),
      layout_columns(
        col_widths = c(4, 4, 4),
        card(card_header(strong("1 - Load data")),
             card_body(p(class = "small",
               "Use the default dataset on university grants included in the package, or upload
                your own data as an Excel (.xlsx) or R (.RData) file."))),
        card(card_header(strong("2 - Settings & summary")),
             card_body(p(class = "small",
               "Define the forcing variable, the threshold (s0) and the treatment assignment
                rule. Then obtain summary statistics of the selected covariates by assignment
                status."))),
        card(card_header(strong("3 - Bandwidth selection")),
             card_body(p(class = "small",
               "Select bandwidths defining suitable subpopulations around the threshold, and
                assess covariate balance with randomization-based tests and plots.")))
      ),
      layout_columns(
        col_widths = c(6, 6),
        card(card_header(strong("4 - Summary of bandwidths")),
             card_body(p(class = "small",
               "Compare several candidate bandwidths at once: randomization-based balance
                tests with multiplicity adjustment, by covariate and bandwidth."))),
        card(card_header(strong("5 - Inference on causal effects")),
             card_body(p(class = "small",
               "Draw inference within the selected subpopulations with four modes of
                inference: Sharp FEP, Sharp Neyman, Fuzzy FEP and Fuzzy Neyman.")))
      )
    )
  ),

  # . 1 Data ----------------------------------------------------------------
  nav_panel(
    "1 - Data", value = "nav_data", icon = icon("database"),
    layout_sidebar(
      sidebar = sidebar(
        width = 340, title = "Data source",
        accordion(
          open = "Default dataset", multiple = FALSE,
          accordion_panel(
            "Default dataset", icon = icon("graduation-cap"),
            p(class = "small text-muted",
              "Italian study on the effects of university grants on student dropout
               (15,984 students)."),
            actionButton("go_default_dataset", "Load grants dataset",
                         icon = icon("download"), class = "btn-primary w-100")
          ),
          accordion_panel(
            "Excel file (.xlsx)", icon = icon("file-excel"),
            fileInput("excelfile", "Upload Excel file", accept = ".xlsx"),
            numericInput("excel_sheetnumber", "Sheet number", 1, min = 1),
            numericInput("excel_startrow", "Start row number", 1, min = 1),
            textInput("excel_stringNA", "Missing value strings", "NA"),
            run_button("go_excel", "Load Excel file", "upload")
          ),
          accordion_panel(
            "R file (.RData)", icon = icon("r-project"),
            fileInput("rdatafile", "Upload RData file",
                      accept = c(".rdata", ".RData", ".Rdata")),
            run_button("go_rdata", "Load RData file", "upload")
          )
        )
      ),
      card(
        full_screen = TRUE,
        card_header("Your data"),
        card_body(withSpinner(DT::dataTableOutput("dto"), type = 4, color = "#2C5F8A"))
      )
    )
  ),

  # . 2 Settings & summary ---------------------------------------------------
  nav_panel(
    "2 - Settings & summary", value = "nav_settings", icon = icon("sliders"),
    layout_sidebar(
      sidebar = sidebar(
        width = 340, title = "RDD settings",
        uiOutput("col_sel_forcing7"),
        numericInput("cutvalue2", "Threshold value (s0)", 15000),
        radioButtons("onezero2", "Treatment assignment rule:",
                     c("Z = 1 if S >= s0 and Z = 0 if S < s0" = "under0",
                       "Z = 1 if S <= s0 and Z = 0 if S > s0" = "under1"),
                     "under0"),
        numericInput("seedval", "Random seed (for reproducibility)", 27),
        hr(),
        h6("Summary statistics"),
        uiOutput("col_sel_covar2"),
        run_button("go_bwsel2", "Compute summary", "table")
      ),
      card(
        card_header("Summary statistics by treatment assignment status"),
        card_body(
          p(class = "text-muted small",
            "Means of the selected covariates, overall and by assignment status (Z),
             together with the group sizes."),
          withSpinner(tableOutput("descriptive1"), type = 4, color = "#2C5F8A")
        )
      )
    )
  ),

  # . 3 Bandwidth selection ---------------------------------------------------
  nav_panel(
    "3 - Bandwidth selection", value = "nav_bandwidth", icon = icon("arrows-left-right-to-line"),
    layout_sidebar(
      sidebar = sidebar(
        width = 340, title = "Bandwidth",
        h6("Part A - Select and assess balance"),
        radioButtons("typerange", "Bandwidth control:",
                     c("Percentage of the range" = "perce",
                       "Symmetric sides" = "balunit",
                       "Asymmetrical sides" = "unbalunit"),
                     "perce"),
        numericInput("stepunit", "Scale of the slider", 1),
        uiOutput("ui_slide_range"),
        numericInput("nsim", "Number of iterations", 50, min = 1),
        uiOutput("col_sel_covar"),
        run_button("go_bwsel", "Run part A", "play"),
        hr(),
        h6("Part B - Distribution of one covariate"),
        uiOutput("col_sel_covar7"),
        radioButtons("intchar", "Type of covariate:",
                     c("Binary" = "binary", "Continuous" = "conti"), "binary"),
        run_button("go2", "Run part B", "chart-column")
      ),
      layout_columns(
        col_widths = 12,
        card(
          full_screen = TRUE,
          card_header(
            div(class = "d-flex justify-content-between align-items-center",
                span("Part A - Distribution of the forcing variable"),
                downloadButton("dl_histogram", "PNG", class = "btn-sm btn-outline-secondary"))
          ),
          card_body(
            p(class = "text-muted small",
              "Histogram of the forcing variable. The black dashed line marks the threshold;
               the red dashed lines mark the selected bandwidth limits."),
            withSpinner(plotOutput("histogram"), type = 4, color = "#2C5F8A")
          )
        ),
        card(
          card_header("Part A - Selected subpopulation and covariate balance"),
          card_body(
            tableOutput("summarydim"),
            p(class = "text-muted small mb-1",
              "Randomization-based balance tests (raw and multiplicity-adjusted p-values),
               in the full dataset and within the selected bandwidth:"),
            withSpinner(tableOutput("summary"), type = 4, color = "#2C5F8A")
          )
        ),
        card(
          full_screen = TRUE,
          card_header(
            div(class = "d-flex justify-content-between align-items-center",
                span("Part B - Covariate distribution before/after selection"),
                downloadButton("dl_plotprop", "PNG", class = "btn-sm btn-outline-secondary"))
          ),
          card_body(withSpinner(plotOutput("plotprop"), type = 4, color = "#2C5F8A"))
        )
      )
    )
  ),

  # . 4 Summary bandwidths ----------------------------------------------------
  nav_panel(
    "4 - Summary of bandwidths", value = "nav_sumbw", icon = icon("table-list"),
    layout_sidebar(
      sidebar = sidebar(
        width = 340, title = "Candidate bandwidths",
        selectizeInput("bandwidths9", "Bandwidths",
                       choices = c(500, 1000, 1500), selected = c(500, 1000, 1500),
                       multiple = TRUE,
                       options = list(create = TRUE,
                                      placeholder = "Type a value and press Enter")),
        numericInput("niter9", "Number of iterations", 1000, min = 1),
        uiOutput("col_sel_covar_covar9"),
        run_button("go9", "Run analysis")
      ),
      card(
        full_screen = TRUE,
        card_header("Adjusted p-values by covariate and bandwidth"),
        card_body(
          p(class = "text-muted small",
            "Randomization-based tests with multiplicity adjustment. Large p-values indicate
             subpopulations where the covariates are well balanced between treatment groups."),
          withSpinner(DT::dataTableOutput("tablemethod9"), type = 4, color = "#2C5F8A")
        )
      )
    )
  ),

  # . 5 Causal effects --------------------------------------------------------
  nav_panel(
    "5 - Causal effects", value = "nav_effects", icon = icon("flag-checkered"),
    layout_sidebar(
      sidebar = sidebar(
        width = 340, title = "Inference settings",
        selectizeInput("bandwidths", "Bandwidths",
                       choices = c(500, 1000, 1500), selected = c(500, 1000, 1500),
                       multiple = TRUE,
                       options = list(create = TRUE,
                                      placeholder = "Type a value and press Enter")),
        radioButtons("typemod", "Type of outcome:",
                     c("Binary" = "binary", "Continuous" = "cont"), "binary"),
        uiOutput("col_sel_covar_Y"),
        numericInput("niter", "Number of iterations", 1000, min = 1),
        selectInput("select_effect", "Method",
                    choices = c("Select method", "Sharp FEP", "Sharp Neyman",
                                "Fuzzy FEP", "Fuzzy Neyman")),
        conditionalPanel(
          condition = "input.select_effect == 'Sharp FEP'",
          run_button("go_sharp_fep")
        ),
        conditionalPanel(
          condition = "input.select_effect == 'Sharp Neyman' || input.select_effect == 'Fuzzy Neyman'",
          textInput("cin", "Alpha level", 0.05)
        ),
        conditionalPanel(
          condition = "input.select_effect == 'Sharp Neyman'",
          run_button("go_sharp_neyman")
        ),
        conditionalPanel(
          condition = "input.select_effect == 'Fuzzy FEP'",
          numericInput("M2", "Iterations for the MLE/posterior mode", 5, min = 1),
          radioButtons("one2side", "Type of noncompliance:",
                       c("One-sided" = "onesided", "Two-sided" = "twosided"),
                       "onesided"),
          uiOutput("col_sel_covar_W"),
          helpText("Note: the Fuzzy FEP approach is computationally demanding;
                    it may take a while."),
          run_button("go_fuzzy_fep")
        ),
        conditionalPanel(
          condition = "input.select_effect == 'Fuzzy Neyman'",
          uiOutput("col_sel_covar_W_neyman"),
          run_button("go_fuzzy_neyman")
        )
      ),
      layout_columns(
        col_widths = 12,
        card(
          full_screen = TRUE,
          card_header("Results"),
          card_body(withSpinner(DT::dataTableOutput("tablemethod"),
                                type = 4, color = "#2C5F8A"))
        ),
        card(
          full_screen = TRUE,
          card_header(
            div(class = "d-flex justify-content-between align-items-center",
                span("Plot"),
                downloadButton("dl_plotres", "PNG", class = "btn-sm btn-outline-secondary"))
          ),
          card_body(withSpinner(plotOutput("plotres", height = "480px"),
                                type = 4, color = "#2C5F8A"))
        )
      )
    )
  ),

  nav_spacer(),
  nav_item(input_dark_mode(id = "dark_mode"))
)
