/* examplelib.c - Implementasi library examplelib */
#include "examplelib.h"

#include <math.h>
#include <string.h>
#include <stdio.h>

const char *exlib_version(void) {
    return EXAMPLELIB_VERSION_STRING;
}

const char *exlib_strerror(exlib_status code) {
    switch (code) {
        case EXLIB_OK:            return "sukses";
        case EXLIB_ERR_NULL:      return "pointer NULL atau n=0";
        case EXLIB_ERR_RANGE:     return "nilai di luar rentang valid";
        case EXLIB_ERR_FORMAT:    return "format input tidak valid";
        case EXLIB_ERR_OVERFLOW:  return "potensi overflow";
        case EXLIB_ERR_NOT_FOUND: return "tidak ditemukan";
        default:                  return "kode tidak dikenal";
    }
}

exlib_status exlib_mean(const double *data, size_t n, double *out) {
    if (data == NULL || out == NULL || n == 0) {
        return EXLIB_ERR_NULL;
    }
    double sum = 0.0;
    for (size_t i = 0; i < n; i++) {
        sum += data[i];
    }
    *out = sum / (double)n;
    return EXLIB_OK;
}

exlib_status exlib_stddev(const double *data, size_t n, double *out) {
    if (data == NULL || out == NULL || n == 0) {
        return EXLIB_ERR_NULL;
    }
    double mean = 0.0;
    exlib_status s = exlib_mean(data, n, &mean);
    if (s != EXLIB_OK) {
        return s;
    }
    double sum_sq = 0.0;
    for (size_t i = 0; i < n; i++) {
        double diff = data[i] - mean;
        sum_sq += diff * diff;
    }
    *out = sqrt(sum_sq / (double)n);
    return EXLIB_OK;
}

exlib_status exlib_reverse_bytes(uint8_t *data, size_t n) {
    if (data == NULL) {
        return EXLIB_ERR_NULL;
    }
    if (n < 2) {
        return EXLIB_OK;
    }
    size_t i = 0;
    size_t j = n - 1;
    while (i < j) {
        uint8_t tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
        i++;
        j--;
    }
    return EXLIB_OK;
}

exlib_status exlib_format_size(uint64_t bytes, char *out, size_t out_cap) {
    if (out == NULL) {
        return EXLIB_ERR_NULL;
    }
    if (out_cap < 16) {
        return EXLIB_ERR_RANGE;
    }
    /* Daftar unit dari kecil ke besar. */
    static const char *units[] = {"B", "KB", "MB", "GB", "TB", "PB"};
    static const int n_units = 6;
    if (bytes == 0) {
        snprintf(out, out_cap, "0.00 B");
        return EXLIB_OK;
    }
    int unit_idx = 0;
    double size = (double)bytes;
    while (size >= 1024.0 && unit_idx < n_units - 1) {
        size /= 1024.0;
        unit_idx++;
    }
    snprintf(out, out_cap, "%.2f %s", size, units[unit_idx]);
    return EXLIB_OK;
}

exlib_status exlib_contains(const char *haystack, const char *needle) {
    if (haystack == NULL || needle == NULL) {
        return EXLIB_ERR_NULL;
    }
    if (needle[0] == '\0') {
        return EXLIB_OK;
    }
    if (strstr(haystack, needle) != NULL) {
        return EXLIB_OK;
    }
    return EXLIB_ERR_NOT_FOUND;
}
