use crate::interpreter::supported_type::{CurveType, IntegerInfo, RustType, SupportedType};
use hardcoded::Hardcoded;
pub mod cipher;
pub mod compare;
mod hardcoded;
pub mod packing;
mod sort;

use crate::interpreter::supported_type::SliceLen;
pub use hardcoded::HardcodedId;

/// Predefined types.
pub fn get_std_types() -> [(&'static str, SupportedType); 20] {
    [
        (
            "u8",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(false, 8)))),
        ),
        (
            "u16",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(false, 16)))),
        ),
        (
            "u32",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(false, 32)))),
        ),
        (
            "u64",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(false, 64)))),
        ),
        (
            "u128",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(false, 128)))),
        ),
        (
            "usize",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(
                false,
                usize::BITS as usize,
            )))),
        ),
        (
            "i8",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(true, 8)))),
        ),
        (
            "i16",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(true, 16)))),
        ),
        (
            "i32",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(true, 32)))),
        ),
        (
            "i64",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(true, 64)))),
        ),
        (
            "i128",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(true, 128)))),
        ),
        (
            "isize",
            SupportedType::FieldValue(RustType::Integer(Some(IntegerInfo::new(
                true,
                isize::BITS as usize,
            )))),
        ),
        (
            "ArcisField",
            SupportedType::FieldValue(RustType::ARCIS_FIELD),
        ),
        ("BaseField", SupportedType::FieldValue(RustType::BASE_FIELD)),
        (
            "ArcisX25519Pubkey",
            SupportedType::Curve(CurveType::X25519Pubkey),
        ),
        (
            "ArcisCiphertext",
            SupportedType::FieldValue(RustType::ArcisField),
        ),
        (
            "integer",
            SupportedType::FieldValue(RustType::Integer(None)),
        ),
        ("bool", SupportedType::Bool),
        ("f64", SupportedType::FieldValue(RustType::Float)),
        ("f32", SupportedType::FieldValue(RustType::Float)),
    ]
}

/// Predefined methods.
/// Could be switched to `#[arcis_circuit = "..."]` syntax and put in the mock-library or the
/// standard library.
pub fn get_std_methods() -> [(&'static str, SupportedType, &'static Hardcoded); 5] {
    [
        (
            "len",
            SupportedType::Slice(Box::new(SupportedType::ImplAny), SliceLen::None),
            const { &Hardcoded::new("len", hardcoded::len, true) },
        ),
        (
            "into_iter",
            SupportedType::ImplAny,
            const { &Hardcoded::new("into_iter", hardcoded::into_iter, false) },
        ),
        (
            "clone",
            SupportedType::ImplAny,
            const { &Hardcoded::new("clone", hardcoded::clone, true) },
        ),
        (
            "reveal",
            SupportedType::ImplAny,
            const { &Hardcoded::new("reveal", hardcoded::reveal, false) },
        ),
        (
            "sort",
            SupportedType::Slice(
                Box::new(SupportedType::FieldValue(RustType::Integer(None))),
                SliceLen::None,
            ),
            const { &Hardcoded::new("sort", sort::sort_int, true) },
        ),
    ]
}
