//! Exact Rust translations of `DetachThisCommandTests`.

use libremetaverse_compat_tests::block_on;
use libremetaverse_compat_tests::rlv_support::{RlvHarness, SampleInventoryTree, guid};
use libremetaverse_rlv::{InventoryMap, RlvAttachmentPoint, RlvWearableType};
use libremetaverse_types::compat::Guid;

const HAPPY: &str = "b1111111-bbbb-4bbb-8bbb-bbbbbbbbbbbb";
const RETRO: &str = "b2222222-bbbb-4bbb-8bbb-bbbbbbbbbbbb";
const GLASSES: &str = "c1111111-cccc-4ccc-8ccc-cccccccccccc";
const PRIM1: &str = "11111111-0001-4aaa-8aaa-ffffffffffff";

#[derive(Clone, Copy)]
enum Setup {
    Normal,
    NoStripItem,
    NoStripFolder,
    NoStripLink,
    Point,
    PointNoStrip,
    PointLink,
    Wearable,
    WearableNoStrip,
    WearableLink,
    WearablePrivate,
}

fn attach(item: &mut libremetaverse_rlv::RlvInventoryItem, point: RlvAttachmentPoint, prim: &str) {
    item.set_attached_to(Some(Some(point)));
    item.set_attached_prim_id(Some(Some(guid(prim))));
}

fn run(command: &str, setup: Setup, sender_item: bool) -> Vec<Guid> {
    let h = RlvHarness::new().expect("RlvService constructor");
    let mut tree = SampleInventoryTree::build().unwrap();
    attach(
        &mut tree.retro_pants,
        RlvAttachmentPoint::Pelvis,
        "11111111-0002-4aaa-8aaa-ffffffffffff",
    );
    attach(
        &mut tree.fancy_hat,
        RlvAttachmentPoint::Chin,
        "11111111-0003-4aaa-8aaa-ffffffffffff",
    );
    if matches!(
        setup,
        Setup::Wearable | Setup::WearableNoStrip | Setup::WearableLink | Setup::WearablePrivate
    ) {
        tree.happy_shirt
            .set_worn_on(Some(Some(RlvWearableType::Pants)));
        tree.glasses.set_worn_on(Some(Some(RlvWearableType::Pants)));
    } else {
        attach(&mut tree.happy_shirt, RlvAttachmentPoint::Chest, PRIM1);
        attach(
            &mut tree.glasses,
            RlvAttachmentPoint::Chest,
            "11111111-0004-4aaa-8aaa-ffffffffffff",
        );
    }
    match setup {
        Setup::NoStripItem | Setup::PointNoStrip | Setup::WearableNoStrip => {
            tree.happy_shirt.set_name("nostrip Happy Shirt".into());
        }
        _ => {}
    }
    if matches!(setup, Setup::NoStripFolder | Setup::NoStripLink) {
        tree.clothing.set_name("nostrip Clothing".into());
    }
    if matches!(
        setup,
        Setup::PointNoStrip | Setup::PointLink | Setup::WearableNoStrip | Setup::WearableLink
    ) {
        tree.accessories.set_name("nostrip Accessories".into());
    }
    if matches!(setup, Setup::NoStripLink) {
        tree.retro_pants.set_is_link(true);
    }
    if matches!(setup, Setup::PointLink | Setup::WearableLink) {
        tree.glasses.set_is_link(true);
    }
    if matches!(setup, Setup::WearablePrivate) {
        tree.clothing.set_name(".clothing".into());
    }
    h.queries.lock().unwrap().inventory_map = Some(InventoryMap::new(tree.root, vec![]).unwrap());
    if sender_item {
        block_on(h.process_from(command, PRIM1, "Happy Shirt")).unwrap();
    } else {
        block_on(h.process(command)).unwrap();
    }
    let mut result = h.actions.lock().unwrap().detachments[0].clone();
    result.sort_by_key(|id| id.0);
    result
}
fn ids(values: &[&str]) -> Vec<Guid> {
    let mut v: Vec<_> = values.iter().map(|s| guid(s)).collect();
    v.sort_by_key(|id| id.0);
    v
}

// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_Default::test ae8c0fd737f869ef3e2dbd97ae28974b35c6bbc5327151c0074d531efdaaf54e translated
#[test]
fn detach_this_default() {
    assert_eq!(
        run("@detachthis=force", Setup::Normal, true),
        ids(&[HAPPY, RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_NoStrip::test 3aa17222f7539814f8329e07de548cca4bb702f4b0409e793ea551327b0c57d0 translated
#[test]
fn detach_this_honors_item_nostrip() {
    assert_eq!(
        run("@detachthis=force", Setup::NoStripItem, true),
        ids(&[RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_NoStripFolder::test 16b74c3bf8312ccb885e61f933ec9d292988d2e1fad05e0188006df5630681f8 translated
#[test]
fn detach_this_honors_folder_nostrip() {
    assert!(run("@detachthis=force", Setup::NoStripFolder, true).is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_NoStripFolder_LinkException::test b86b22a0ab30d0ded0cd6fbc7d34fae77e521861f5672b44a25a77325e594ab4 translated
#[test]
fn detach_this_honors_folder_link_exception() {
    assert_eq!(
        run("@detachthis=force", Setup::NoStripLink, true),
        ids(&[RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ById::test 3c4a211e5fefb44b42f50f6e6e58f8f852c8cf2d732bb6c3f737c3d6a592fa22 translated
#[test]
fn detach_this_by_id() {
    assert_eq!(
        run(&format!("@detachthis:{PRIM1}=force"), Setup::Normal, false),
        ids(&[HAPPY, RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ById_NostripItemName::test f32926ca6f4328afdd3ddeb9f7bec8ff2ee01e9563555921ac8c663d20005551 translated
#[test]
fn detach_this_by_id_honors_item_nostrip() {
    assert_eq!(
        run(
            &format!("@detachthis:{PRIM1}=force"),
            Setup::NoStripItem,
            false
        ),
        ids(&[RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ById_NostripFolderName::test bec3216bf016c2543a3410b069abd786167e04a7527253887f158127644656a8 translated
#[test]
fn detach_this_by_id_honors_folder_nostrip() {
    assert!(
        run(
            &format!("@detachthis:{PRIM1}=force"),
            Setup::NoStripFolder,
            false
        )
        .is_empty()
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ById_NostripFolderName_LinkException::test 1b5eb3a0bdef8ea65b800533ab3153dc6b3ea21d2f4f27e4820d0a0df48891a2 translated
#[test]
fn detach_this_by_id_honors_link_exception() {
    assert_eq!(
        run(
            &format!("@detachthis:{PRIM1}=force"),
            Setup::NoStripLink,
            false
        ),
        ids(&[RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvAttachmentPoint::test 7e8f3a4d8b2cbdb5cc81eea598da6ef6395834b1cb7a629dc8d7ee2bfd80fab5 translated
#[test]
fn detach_this_by_attachment_point() {
    assert_eq!(
        run("@detachthis:chest=force", Setup::Point, false),
        ids(&[HAPPY, RETRO, GLASSES])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvAttachmentPoint_NoStrip::test f6ff482bdb8d28414e01952201e37e49316b3e2345b0ff85dd4cb059193d1816 translated
#[test]
fn detach_this_by_attachment_point_honors_nostrip() {
    assert_eq!(
        run("@detachthis:chest=force", Setup::PointNoStrip, false),
        ids(&[RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvAttachmentPoint_NoStrip_LinkException::test 289f8cc48f0e6a412d58258876e4aca08d8116d549642a0011bbdaf9b2223e83 translated
#[test]
fn detach_this_by_attachment_point_honors_link_exception() {
    assert_eq!(
        run("@detachthis:chest=force", Setup::PointLink, false),
        ids(&[RETRO, GLASSES])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvWearableType::test 51607294f12279974c2b44b47ba2eadca9846180a39bcde6a28c020dc4466254 translated
#[test]
fn detach_this_by_wearable() {
    assert_eq!(
        run("@detachthis:pants=force", Setup::Wearable, false),
        ids(&[HAPPY, RETRO, GLASSES])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvWearableType_NoStrip::test 30dec183993b2a644c2812ffc1c863e1714df134942f7827df818d9200e47c38 translated
#[test]
fn detach_this_by_wearable_honors_nostrip() {
    assert_eq!(
        run("@detachthis:pants=force", Setup::WearableNoStrip, false),
        ids(&[RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvWearableType_NoStrip_LinkException::test 62f59cf66f21dcac15cf3166dcec2183181c0b434e9eacba796eb7025c4f1ab3 translated
#[test]
fn detach_this_by_wearable_honors_link_exception() {
    assert_eq!(
        run("@detachthis:pants=force", Setup::WearableLink, false),
        ids(&[RETRO, GLASSES])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/DetachThisCommandTests.cs::DetachThisCommandTests.DetachThisForce_ByRlvWearableType_PrivateFolder::test dd40588598bd081189e7c4f284af3851a140155e2ede0ae2121dd59a156dc988 translated
#[test]
fn detach_this_by_wearable_skips_private_folder() {
    assert_eq!(
        run("@detachthis:pants=force", Setup::WearablePrivate, false),
        ids(&[GLASSES])
    );
}
