/*-
 * Scram-rs - a SCRAM authentification authorization library
 * 
 * Copyright (C) 2021  Aleksandr Morozov
 * Copyright (C) 2025 Aleksandr Morozov
 * 
 * The syslog-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *
 *   2. The MIT License (MIT)
 *                     
 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
 */

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

use crate::ScramKey;

use super::
{
    common, 
    error::CApiScramRuntimeError
};



#[unsafe(no_mangle)]
pub unsafe extern "C" 
fn capi_scram_key(
    client_key: *const u8,
    client_key_len: usize,
    server_key: *const u8,
    server_key_len: usize,
    key_out: *mut *mut ScramKey,
    error_out: *mut *mut CApiScramRuntimeError
) -> i32
{
    if key_out.is_null() == true
    {
        return -5;
    }

    let mut keys = ScramKey::default();

    if client_key.is_null() == false
    {
        let key = 
            match common::carr_to_vec(client_key, client_key_len, "client key password")
            {
                Ok(r) => r,
                Err(e) =>   
                {
                    unsafe 
                    { 
                        if let Some(err) = error_out.as_mut()
                        {
                            *err = e.into_capi();
                        }
                    }
    
                    return 1;
                }
            };

        keys.set_client_key(key);
    }

    if server_key.is_null() == false
    {
        let key = 
            match common::carr_to_vec(server_key, server_key_len, "server key password")
            {
                Ok(r) => r,
                Err(e) =>   
                {
                    unsafe 
                    { 
                        if let Some(err) = error_out.as_mut()
                        {
                            *err = e.into_capi();
                        }
                    }
    
                    return 1;
                }
            };

        keys.set_client_key(key);
    }

    unsafe { *key_out.as_mut().unwrap() = Box::into_raw(Box::new(keys)) };

    return 0;
}


#[unsafe(no_mangle)]
pub unsafe extern "C" 
fn capi_scram_key_free(key: *mut ScramKey)
{
    if key.is_null() == true
    {
        return;
    }

    drop(unsafe { Box::from_raw(key) });
}