#| '!! shinylive warning !!': |
#|   shinylive does not work in self-contained HTML documents.
#|   Please set `embed-resources: false` in your metadata.
#| standalone: true
#| viewerHeight: 800
library(shiny)

# Define UI
ui <- fluidPage(
    titlePanel("Sampling Distribution Simulator"),
    sidebarLayout(
        sidebarPanel(
            sliderInput("n", "Sample Size (n):", 
                        min = 1, max = 100, value = 30, step = 1),
            sliderInput("mean", "Mean:", 
                        min = 0, max = 10, value = 0, step = 0.1),
            sliderInput("sd", "Standard Deviation:", 
                        min = 0.1, max = 10, value = 1, step = 0.1),
            numericInput("B", "Number of Replications (B):", 
                         1e3, min = 1, max = 1e6),
            textInput("fun", "Function (e.g., mean, sd):", value = "mean"),
            checkboxInput("fixAxis", "Fix x-axis limits?", value = FALSE),
            conditionalPanel(
                condition = "input.fixAxis == true",
                numericInput("xMin", "X-axis Minimum:", value = -1, step = 1),
                numericInput("xMax", "X-axis Maximum:", value = 1, step = 1)
            ),
            actionButton("simulate", "Simulate")
        ),
        mainPanel(
            plotOutput("histPlot")
        )
    )
)

# Define server logic
server <- function(input, output) {
    # Function for generating the sampling distribution
    sampdist <- function(n, mean = 0, sd = 1, B = 1e3, FUN) {
        replicate(
            B,
            {
                x <- rnorm(n, mean, sd)
                FUN(x)
            }
        )
    }
    
    # Reactive value to store simulation results
    simData <- reactiveVal(NULL)
    
    # Simulate when the button is clicked
    observeEvent(input$simulate, {
        # Parse function from user input
        FUN <- match.fun(input$fun)
        
        # Generate sampling distribution
        results <- sampdist(
            n = input$n,
            mean = input$mean,
            sd = input$sd,
            B = input$B,
            FUN = FUN
        )
        
        # Update reactive value
        simData(results)
    })
    
    # Render histogram
    output$histPlot <- renderPlot({
        results <- simData()
        
        # Ensure results are available
        if (is.null(results)) return()
        
        # Determine x-axis limits
        xlim <- if (input$fixAxis) {
            c(input$xMin, input$xMax)
        } else {
            #c(input$mean - input$sd*5, input$mean + input$sd*5)
            range(results)
        }
        
        # Plot histogram
        hist(results, 
             main = paste("Sampling Distribution of", input$fun),
             breaks = 50,
             xlab = sprintf("%s(x)", input$fun),
             col = "dodgerblue", 
             border = "black",
             cex.lab = 1.5,
             cex.main = 1.5,
             xlim = xlim)
    }, height = 500, width = 700)
}

# Run the application 
shinyApp(ui = ui, server = server)