/*
* Copyright (c) 2022, able <abl3theabove@gmail.com>
*
* SPDX-License-Identifier: MPL-2.0
*/

use crate::{
    kmain::KERNEL_CONF,
    network::socket::{SimpleSock, Socket, SocketReturns},
    num_to_vga16, VgaBuffer, SCREEN_BUFFER,
};
use kernel::TICK;
use picorand::PicoRandGenerate;
use rkyv::{ser::serializers::AllocSerializer, Deserialize};
use vga::colors::Color16;
use y_compositor_protocol::Version;

pub fn run_tests() {
    if KERNEL_CONF.tests.run_tests {
        // quick and dirty testing framework
        screen_writer_test();
        socket_test();
        graphics_pipe_test();
        socket_startup_rng();
        socket_test_rng();
    }

    if KERNEL_CONF.tests.run_demos {
        graphics_api_demo();
    }

    if KERNEL_CONF.tests.run_shader_tests {
        shader_tests();
    }
}

pub fn socket_test() {
    let mut xyz = SimpleSock::new();

    xyz.peek();

    xyz.write(vec![0, 1, 2, 3]);

    let x = "simple 🧦".to_string().into_bytes();
    xyz.write(x);

    info!("{:?}", &xyz.read(4).unwrap());

    match &xyz.peek() {
        SocketReturns::ReadOk(strr) => {
            let out = String::from_utf8_lossy(strr);

            info!("{}", out);
        }
        SocketReturns::ReadIndexOutOfBounds => todo!(),
        SocketReturns::WriteOk => todo!(),
    }
}

pub fn socket_test_rng() {
    let mut test_sock = SimpleSock::grab_socket("RNGProvider".to_string()).unwrap();
    info!(
        "Recieving {} from protocol {}",
        test_sock.read(1).unwrap()[0],
        test_sock.protocol().unwrap()
    );
}

pub fn socket_startup_rng() {
    use picorand::{WyRand, RNG};
    let mut random_socket = SimpleSock::new();

    random_socket.register_protocol("RNGProvider".to_string());
    let bruh = TICK.load(core::sync::atomic::Ordering::Relaxed);

    let mut rng = RNG::<WyRand, u8>::new(bruh);

    for _ in 0..512 {
        let x = rng.generate();
        random_socket.write(vec![x]);
    }
}

pub fn screen_writer_test() {
    let mut sock_print_id = SimpleSock::new();

    sock_print_id.register_protocol("Screen Printer".to_string());
    // sock_print_id.write(format!("a原 b画 cフ dァ eイ fル 集").into());
    // sock_print_id.write(format!("⋮").into());

    sock_print_id.write(format!("λ³ Half Life 3 booting up  ㎣").into());
    // sock_print_id.write(format!("Happy birthday 🎉").into());
    // sock_print_id.write(format!("I look forward to ur ai stuff :^>").into());
    // sock_print_id.write(format!("1....2....3....4....5....6....7....8....9").into());

    let mut mode = SCREEN_BUFFER.lock();
    for current in (*String::from_utf8_lossy(&sock_print_id.peek().unwrap())).chars() {
        mode.draw_char(0, 0, current, from_vga_16(Color16::Red));
    }
    mode.copy_to_buffer();
}

pub fn vga_boot_screen() {
    let mut abcde = SCREEN_BUFFER.lock();

    for y in 0..480 {
        for x in 0..640 {
            let segment_x = x * 4 / 640;
            let segment_y = y * 4 / 480;
            let segment = segment_x + segment_y * 4;

            abcde.set_pixel(x, y, from_vga_16(num_to_vga16(segment as u8)));
        }
    }
}

pub fn graphics_pipe_test() {
    let mut graphics_pipe = SimpleSock::grab_socket("YCompositor".to_string()).unwrap();

    let version = Version {
        major: 13,
        minor: 123,
        patch: 0,
    };
    use rkyv::ser::Serializer;
    let mut serializer = AllocSerializer::<0>::default();
    serializer.serialize_value(&version).unwrap();
    // let bytes = serializer.into_serializer().into_inner();

    // info!("{:?}", bytes);
    let bytes = serializer.into_serializer().into_inner();
    graphics_pipe.write(bytes.into_vec());
    unsafe {
        let the_bytes = graphics_pipe.read(3).unwrap();
        let archived = rkyv::archived_root::<Version>(&the_bytes);
        let deserialized: Version = archived.deserialize(&mut rkyv::Infallible).unwrap();
        trace!("{:?}", deserialized);
    }
}

pub fn graphics_pipe_startup() {
    let mut graphics_pipe = SimpleSock::new();

    graphics_pipe.register_protocol("YCompositor".to_string());
}

pub fn graphics_api_demo() {
    let mut abcde = SCREEN_BUFFER.lock();
    abcde.force_redraw();

    abcde.draw_filled_circle(100, 100, 300, 0x0000ff00);
    abcde.draw_unfilled_rect(100, 100, 400, 200, 0xff000000);
    abcde.draw_filled_rect(300, 300, 400, 400, 0xff000000);
    abcde.draw_line(100, 100, 400, 200, 0xff000000);
    abcde.copy_to_buffer();
}

pub fn shader_tests() {
    let mut graphics = SCREEN_BUFFER.lock();

    graphics.clear();
    graphics.force_redraw();
    graphics.draw_filled_rect(25, 25, 50, 50, 0xff000000);
    graphics.set_pixel(50, 50, 0xffffff00);
    graphics.shade();

    graphics.copy_to_buffer();

    // drop(graphics)
}

pub fn ser_de_test() {
    let mut proc_1 = SimpleSock::new();
    proc_1.register_protocol("ProcessSpawner".to_string());

    let version = 0;
    use rkyv::ser::Serializer;
    let mut serializer = AllocSerializer::<0>::default();
    serializer.serialize_value(&version).unwrap();

    let bytes = serializer.into_serializer().into_inner();
    proc_1.write(bytes.into_vec());
    unsafe {
        let the_bytes = proc_1.read(3).unwrap();
        let archived = rkyv::archived_root::<Version>(&the_bytes);
        let deserialized: Version = archived.deserialize(&mut rkyv::Infallible).unwrap();
        trace!("{:?}", deserialized);
    }
}
