#![cfg(test)]

use microformats_types::{Document, Image, Item, PropertyValue};
use serde_json::json;

use crate::jf2::{IntoJf2, Object, Property};

#[test]
fn try_from_item_to_object() -> Result<(), crate::Error> {
    let item: Item = serde_json::from_value(json!({
        "type": ["h-entry"],
        "children": [
        {
            "type": ["h-cite"],
            "properties": {
                "url": "https://indieweb.org"
            }
        }
        ],
        "properties": {
            "url": "https://indieweb.org/pages",
            "content": [
            {
                "html": "<strong>HTML</strong>!",
                "value": "HTML!"
            }
            ]
        }
    }))
    .unwrap();
    similar_asserts::assert_serde_eq!(
        serde_json::json!(Object::try_from(item)?),
        json!({
            "type": "entry",
            "children": [
            {
                "type": "cite",
                "url": "https://indieweb.org"
            }
            ],
            "url": "https://indieweb.org/pages",
            "text": "HTML!",
            "html": "<strong>HTML</strong>!"
        })
    );

    Ok(())
}

#[test]
fn try_from_document_to_object() -> Result<(), crate::Error> {
    let item: Document = serde_json::from_value(json!({
        "items": [
        {
            "type": ["h-entry"],
            "children": [
            {
                "type": ["h-cite"],
                "properties": {
                    "url": ["https://indieweb.org/child"],
                    "photo": ["https://indieweb.org/child-photo.jpg"]
                }
            }
            ],
            "properties": {
                "url": ["https://indieweb.org/pages"],
                "bookmark-of": [
                    {
                        "type": ["h-cite"],
                        "properties": {
                            "url": ["https://indieweb.org/bookmark"],
                            "photo": ["https://indieweb.org/bookmark-photo.jpg"]
                        }
                    }
                ],
                "content": [
                    {
                        "html": "<strong>HTML</strong>!",
                        "value": "HTML!"
                    }
                ]
            }
        }
        ]
    }))
    .map_err(crate::Error::Json)?;

    similar_asserts::assert_serde_eq!(
    expected: json!({
        "@context": super::JSON_LD_CONTEXT_URI,
        "children": [
        {
            "text": "HTML!",
            "html": "<strong>HTML</strong>!",
            "type": "entry",
            "url": "https://indieweb.org/pages",
            "bookmark-of": "https://indieweb.org/bookmark",
            "children": [
                {
                    "type": "cite",
                    "url": "https://indieweb.org/child",
                    "photo": "https://indieweb.org/child-photo.jpg",
                }
            ]
        }
        ],
        "references": {
            "https://indieweb.org/bookmark": {
                "type": "cite",
                "photo": "https://indieweb.org/bookmark-photo.jpg",
                "url": "https://indieweb.org/bookmark",
            }
        },
    }),
    parsed: serde_json::json!(item.into_jf2()?)
        );

    Ok(())
}

#[test]
fn property_from_name_value_tuple_reserved_type() {
    assert_eq!(
        std::convert::TryInto::try_into(("type", PropertyValue::Plain("h-entry".into()))),
        Ok(Property::String("h-entry".into())),
        "recognizes 'type' as a reserved property in correct type"
    );

    assert_eq!(
        Property::try_from((
            "type",
            PropertyValue::Image(Image {
                value: "https://indieweb.org".parse().unwrap(),
                alt: Default::default()
            })
        )),
        Err(crate::Error::InvalidRequiredProperty {
            name: "type".into(),
            kind: "string".into()
        }),
        "rejects invalid type for 'type'"
    );
}
