//! Exact Rust translations of `RemOutfitCommandTests`.

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

const RETRO: &str = "b2222222-bbbb-4bbb-8bbb-bbbbbbbbbbbb";
const HAPPY: &str = "b1111111-bbbb-4bbb-8bbb-bbbbbbbbbbbb";
const WATCH: &str = "c0000000-cccc-4ccc-8ccc-cccccccccccc";
const PARTY: &str = "d0000000-dddd-4ddd-8ddd-dddddddddddd";
const FANCY: &str = "d1111111-dddd-4ddd-8ddd-dddddddddddd";
const EXTERNAL1: &str = "12312312-0001-4aaa-8aaa-aaaaaaaaaaaa";
const EXTERNAL2: &str = "12312312-0002-4aaa-8aaa-aaaaaaaaaaaa";

#[derive(Clone, Copy)]
enum Setup {
    All,
    PrivateClothing,
    External,
    ExternalNoStrip,
    ExternalNoStripLink,
    ExternalByType,
    Folder,
    PrivateFolder,
    FolderNoStripItem,
    FolderNoStripName,
    FolderNoStripNameLink,
    Specific,
    SpecificPrivate,
    SpecificNoStrip,
    SpecificNoStripLink,
    BodyPart,
}

fn external(id: &str, name: &str) -> RlvInventoryItem {
    RlvInventoryItem::new(
        guid(id),
        name.into(),
        false,
        Some(Some(guid("12312312-aaaa-4aaa-8aaa-aaaaaaaaaaaa"))),
        None,
        None,
        Some(Some(RlvWearableType::Tattoo)),
        None,
    )
    .unwrap()
}

fn base_worn(tree: &mut SampleInventoryTree) {
    tree.retro_pants
        .set_worn_on(Some(Some(RlvWearableType::Pants)));
    tree.happy_shirt
        .set_worn_on(Some(Some(RlvWearableType::Shirt)));
    tree.watch.set_worn_on(Some(Some(RlvWearableType::Tattoo)));
    tree.fancy_hat
        .set_worn_on(Some(Some(RlvWearableType::Tattoo)));
    tree.party_hat
        .set_worn_on(Some(Some(RlvWearableType::Skin)));
}

fn run(command: &str, setup: Setup) -> Vec<Guid> {
    let h = RlvHarness::new().expect("RlvService constructor");
    let mut tree = SampleInventoryTree::build().unwrap();
    let mut external_items = vec![];
    match setup {
        Setup::All | Setup::Folder | Setup::Specific | Setup::BodyPart => base_worn(&mut tree),
        Setup::PrivateClothing => {
            base_worn(&mut tree);
            tree.clothing.set_name(".Clothing".into());
        }
        Setup::External | Setup::ExternalByType => {
            base_worn(&mut tree);
            external_items.push(external(EXTERNAL1, "External Tattoo"));
        }
        Setup::ExternalNoStrip | Setup::ExternalNoStripLink => {
            base_worn(&mut tree);
            tree.hats.set_name("nostrip Hats".into());
            tree.happy_shirt.set_name("nostrip Happy Shirt".into());
            if matches!(setup, Setup::ExternalNoStripLink) {
                tree.fancy_hat.set_is_link(true);
            }
            external_items.push(external(EXTERNAL1, "External Tattoo"));
            external_items.push(external(EXTERNAL2, "nostrip External Tattoo"));
        }
        Setup::PrivateFolder | Setup::SpecificPrivate => {
            base_worn(&mut tree);
            tree.hats.set_name(".Hats".into());
        }
        Setup::FolderNoStripItem => {
            base_worn(&mut tree);
            tree.fancy_hat.set_name("nostrip Fancy Hat".into());
        }
        Setup::FolderNoStripName | Setup::FolderNoStripNameLink => {
            base_worn(&mut tree);
            tree.hats.set_name("nostrip Hats".into());
            if matches!(setup, Setup::FolderNoStripNameLink) {
                tree.fancy_hat.set_is_link(true);
            }
        }
        Setup::SpecificNoStrip | Setup::SpecificNoStripLink => {
            tree.retro_pants
                .set_worn_on(Some(Some(RlvWearableType::Pants)));
            tree.watch.set_worn_on(Some(Some(RlvWearableType::Pants)));
            tree.party_hat
                .set_worn_on(Some(Some(RlvWearableType::Pants)));
            tree.glasses
                .set_worn_on(Some(Some(RlvWearableType::Tattoo)));
            tree.watch.set_name("nostrip Watch".into());
            tree.clothing.set_name("nostrip clothing".into());
            if matches!(setup, Setup::SpecificNoStripLink) {
                tree.retro_pants.set_is_link(true);
            }
        }
    }
    h.queries.lock().unwrap().inventory_map =
        Some(InventoryMap::new(tree.root, external_items).unwrap());
    block_on(h.process(command)).unwrap();
    let mut ids = h.actions.lock().unwrap().removed_outfits[0].clone();
    ids.sort_by_key(|id| id.0);
    ids
}

fn ids(values: &[&str]) -> Vec<Guid> {
    let mut result: Vec<_> = values.iter().map(|value| guid(value)).collect();
    result.sort_by_key(|id| id.0);
    result
}

// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit::test 60bd0e62bbd4613c4d2d1a65705644dc25fd7327408adfc0bb7e95c45d79cdcb translated
#[test]
fn remove_outfit() {
    assert_eq!(
        run("@remoutfit=force", Setup::All),
        ids(&[RETRO, HAPPY, WATCH, FANCY])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_PrivateFolders::test d79ac3806f50915390edd0a24b756ef398c1334017f69d16f4cb887dcdd41fb1 translated
#[test]
fn remove_outfit_in_private_folders() {
    assert_eq!(
        run("@remoutfit=force", Setup::PrivateClothing),
        ids(&[RETRO, HAPPY, WATCH, FANCY])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_ExternalItems::test 0265a9fee1070cbcc458bfcb05fe267991cbdb5480500c1b32aace1eb4935217 translated
#[test]
fn remove_outfit_external_items() {
    assert_eq!(
        run("@remoutfit=force", Setup::External),
        ids(&[RETRO, HAPPY, WATCH, FANCY, EXTERNAL1])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_ExternalItems_NoStrip::test b93d39d919fb70b02ccdb724969f7b983c726c707bca96e1b1ddc6ee248a734f translated
#[test]
fn remove_outfit_external_items_honors_nostrip() {
    assert_eq!(
        run("@remoutfit=force", Setup::ExternalNoStrip),
        ids(&[RETRO, WATCH, EXTERNAL1])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_ExternalItems_NoStrip_LinkException::test 5ecc44228573645e0a0c78d100dab54b793c6ce8dc50a02d79a919fe6d7c1678 translated
#[test]
fn remove_outfit_external_items_honors_link_exception() {
    assert_eq!(
        run("@remoutfit=force", Setup::ExternalNoStripLink),
        ids(&[RETRO, WATCH, FANCY, EXTERNAL1])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_ExternalItems_ByType::test 8ba106f071f8768af1d6213c04f67dd0aec846ae47552686eba86c489bdb0292 translated
#[test]
fn remove_outfit_external_items_by_type() {
    assert_eq!(
        run("@remoutfit:tattoo=force", Setup::ExternalByType),
        ids(&[FANCY, WATCH, EXTERNAL1])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Folder::test 45f9e7a9d0ef99ec7d58b59f1c1db7b6065994939717842bb02486b470b357b5 translated
#[test]
fn remove_outfit_folder() {
    assert_eq!(
        run("@remoutfit:Clothing/Hats=force", Setup::Folder),
        ids(&[FANCY])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Folder_PrivateFolder::test 68f3050a1b667304ff2b252690cc7d1994964dbd2c7633d54e5c6654714c0aed translated
#[test]
fn remove_outfit_private_folder() {
    assert_eq!(
        run("@remoutfit:Clothing/Hats=force", Setup::PrivateFolder),
        ids(&[FANCY])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Folder_NoStrip::test d56b83a72d6d3529af0390674550ce40733c14de6210cf71e277f0e195d1e330 translated
#[test]
fn remove_outfit_folder_honors_item_nostrip() {
    assert!(run("@remoutfit:Clothing/Hats=force", Setup::FolderNoStripItem).is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Folder_NoStripFolderName::test a28f5517a9d05085627d5acaf33441d598912301962f6e99aaff49ef5114af53 translated
#[test]
fn remove_outfit_folder_honors_folder_nostrip() {
    assert!(
        run(
            "@remoutfit:Clothing/nostrip Hats=force",
            Setup::FolderNoStripName
        )
        .is_empty()
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Folder_NoStripFolderName_LinkException::test 80efc201f976365e68d32ae1b30db0f10a17cbc65aedc82895ffa679700008da translated
#[test]
fn remove_outfit_folder_honors_link_exception() {
    assert_eq!(
        run(
            "@remoutfit:Clothing/nostrip Hats=force",
            Setup::FolderNoStripNameLink
        ),
        ids(&[FANCY])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Specific::test 7235143679739442ec942d294a8a68f69b7fb5678ed4e3ca03be35c74e9c71a9 translated
#[test]
fn remove_outfit_specific() {
    assert_eq!(
        run("@remoutfit:tattoo=force", Setup::Specific),
        ids(&[FANCY, WATCH])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Specific_PrivateFolder::test 3feea26f000dc7eb86b1413f1a5bdd5f109c5f9f969918cd1ce2e7f926f26c12 translated
#[test]
fn remove_outfit_specific_private_folder() {
    assert_eq!(
        run("@remoutfit:tattoo=force", Setup::SpecificPrivate),
        ids(&[FANCY, WATCH])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Specific_NoStrip::test 6e4b8bc53933a889df1cf553ca7e0601e5061bb87013a4075c2ff357cc9d987f translated
#[test]
fn remove_outfit_specific_honors_nostrip() {
    assert_eq!(
        run("@remoutfit:pants=force", Setup::SpecificNoStrip),
        ids(&[PARTY])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_Specific_NoStrip_LinkException::test 72b1409f70531d859f15a012cb1fb03d795d2065c5d03b7a263d352ca4b80e98 translated
#[test]
fn remove_outfit_specific_honors_link_exception() {
    assert_eq!(
        run("@remoutfit:pants=force", Setup::SpecificNoStripLink),
        ids(&[PARTY, RETRO])
    );
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/RemOutfitCommandTests.cs::RemOutfitCommandTests.RemOutfit_BodyPart_Specific::test 13804c96395db86821371dc8f2cacd2cb182338f8ea88034afcc5da19e3f0691 translated
#[test]
fn remove_outfit_does_not_remove_body_part() {
    assert!(run("@remoutfit:skin=force", Setup::BodyPart).is_empty());
}
