#######################################################################
# lfl: Linguistic Fuzzy Logic
# Copyright (C) 2025 Michal Burda
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#######################################################################


#' Creating linguistic context directly from values
#'
#' This function creates a context (i.e., an instance of S3 class
#' [ctx3()], [ctx3bilat()], [ctx5()], or [ctx5bilat()]) based on values
#' of the numeric vector `x`. In default, the context is based on minimum
#' and maximum value of `x` in the following way:
#' * `ctx3`, `ctx5`: low = minimum, high = maximum value of `x`;
#' * `ctx3bilat`, `ctx5bilat`: negMax = minimum, max = maximum value of `x`,
#'    origin = mean of minimum and maximum.
#'
#' Other values are computed according to the defaults as defined in the constructors
#' [ctx3()], [ctx3bilat()], [ctx5()], and [ctx5bilat()]).
#'
#' @param x A numeric vector to compute the context from
#' @param type A type of the context to be returned. Must be one of:
#'   `ctx3`, `ctx5`, `ctx3bilat` or `ctx5bilat`
#' @param ... other parameters to be passed to the appropriate constructor
#'   ([ctx3()], [ctx3bilat()], [ctx5()], and [ctx5bilat()]) that is called internally.
#'   These values overwrite the defaults computed by `minmax` -- see the examples.
#' @examples
#'   minmax(0:100)                # returns ctx3: 0, 50, 100
#'   minmax(0:100, high=80)       # returns ctx3: 0, 40, 80
#'   minmax(0:100, relCenter=0.4) # returns ctx3: 0, 40, 100
#'   minmax(0:100, type='ctx5')   # returns ctx5: 0, 25, 50, 75, 100
#' @export
minmax <- function(x,
                   type=c('ctx3', 'ctx5', 'ctx3bilat', 'ctx5bilat'),
                   ...) {
    .mustBeNumericVector(x)
    type <- match.arg(type)
    dots <- list(...)
    mini <- min(x, na.rm=TRUE)
    maxi <- max(x, na.rm=TRUE)
    if (type %in% c('ctx3', 'ctx5')) {
        if (is.null(dots[['low']])) {
            dots[['low']] <- mini
        }
        if (is.null(dots[['high']])) {
            dots[['high']] <- maxi
        }
    } else {
        if (is.null(dots[['negMax']])) {
            dots[['negMax']] <- mini
        }
        if (is.null(dots[['max']])) {
            dots[['max']] <- maxi
        }
        if (is.null(dots[['origin']])) {
            dots[['origin']] <- mean(c(mini, maxi))
        }
    }
    do.call(type, dots)
}
