use takumi::prelude::{Length::*, *};

use crate::test_utils::run_fixture_test;

const ROTATED_ANGLES: &[f32] = &[0.0, 45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0];

#[test]
fn test_rotate_image() {
  let image = Node::container([Node::image("assets/images/yeecord.png").with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::rotate(Some(Angle::new(90.0)))),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with(StyleDeclaration::align_items(AlignItems::Center)),
  );

  run_fixture_test(image, "style_rotate_image");
}

#[test]
fn test_rotate() {
  let container = Node::container([Node::container([]).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Rem(16.0)))
      .with(StyleDeclaration::height(Rem(16.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::black(),
      )))
      .with(StyleDeclaration::rotate(Some(Angle::new(45.0)))),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::justify_content(JustifyContent::Center))
      .with(StyleDeclaration::align_items(AlignItems::Center)),
  );

  run_fixture_test(container, "style_rotate");
}

#[test]
fn test_style_transform_origin_center() {
  let container = Node::container(
    ROTATED_ANGLES
      .iter()
      .map(|angle| create_rotated_container(*angle, PositionValue::center()))
      .collect::<Vec<_>>(),
  )
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      ))),
  );

  run_fixture_test(container, "style_transform_origin_center");
}

#[test]
fn test_style_transform_origin_top_left() {
  let container = Node::container(
    ROTATED_ANGLES
      .iter()
      .map(|angle| {
        create_rotated_container(
          *angle,
          PositionValue(SpacePair::from_pair(
            PositionComponent::KeywordX(PositionKeywordX::Left),
            PositionComponent::KeywordY(PositionKeywordY::Top),
          )),
        )
      })
      .collect::<Vec<_>>(),
  )
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::font_size(Px(24.0).into())),
  );

  run_fixture_test(container, "style_transform_origin_top_left");
}

fn create_rotated_container(angle: f32, transform_origin: PositionValue) -> Node {
  Node::image("assets/images/yeecord.png").with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::translate(SpacePair::from_single(
        Percentage(-50.0),
      )))
      .with(StyleDeclaration::rotate(Some(Angle::new(angle))))
      .with(StyleDeclaration::position(Position::Absolute))
      .with(StyleDeclaration::top(Percentage(50.0)))
      .with(StyleDeclaration::left(Percentage(50.0)))
      .with(StyleDeclaration::transform_origin(transform_origin))
      .with(StyleDeclaration::width(Px(200.0)))
      .with(StyleDeclaration::height(Px(200.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color([255, 0, 0, 30]),
      )))
      .with_border_width(Sides([Px(1.0).into(); 4]))
      .with_border_style(Sides([BorderStyle::Solid; 4]))
      .with_border_radius(BorderRadius(Sides([SpacePair::from_single(Px(12.0)); 4]))),
  )
}

#[test]
fn test_style_transform_translate_and_scale() {
  let position = Node::container([Node::text("200px x 100px".to_string())]).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Px(200.0)))
      .with(StyleDeclaration::height(Px(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color([255, 0, 0, 255]),
      ))),
  );

  let translated = Node::container([Node::image("assets/images/yeecord.png").with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0))),
  )])
  .with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Px(300.0)))
      .with(StyleDeclaration::height(Px(300.0)))
      .with_border_width(Sides([Px(1.0).into(); 4]))
      .with_border_style(Sides([BorderStyle::Solid; 4]))
      .with(StyleDeclaration::translate(SpacePair::from_single(Px(
        300.0,
      ))))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color([0, 128, 255, 255]),
      ))),
  );

  let scaled = Node::container([Node::text("100px x 100px, scale(2.0, 2.0)".to_string())])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::scale(SpacePair::from_single(
          PercentageNumber(2.0),
        )))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([0, 255, 0, 255]),
        )))
        .with(StyleDeclaration::width(Px(100.0)))
        .with(StyleDeclaration::height(Px(100.0)))
        .with_border_width(Sides([Px(1.0).into(); 4]))
        .with_border_style(Sides([BorderStyle::Solid; 4]))
        .with(StyleDeclaration::font_size(Px(12.0).into())),
    );

  let rotated = Node::container([Node::text("200px x 200px, rotate(45deg)".to_string())])
    .with_style(
      Style::default()
        .with(StyleDeclaration::display(Display::Flex))
        .with(StyleDeclaration::rotate(Some(Angle::new(45.0))))
        .with(StyleDeclaration::background_color(ColorInput::Value(
          Color([0, 0, 255, 255]),
        )))
        .with(StyleDeclaration::width(Px(200.0)))
        .with(StyleDeclaration::height(Px(200.0)))
        .with_border_width(Sides([Px(1.0).into(); 4]))
        .with_border_style(Sides([BorderStyle::Solid; 4]))
        .with(StyleDeclaration::color(ColorInput::Value(Color::white())))
        .with_border_color(Sides([ColorInput::Value(Color::black()); 4])),
    );

  let container = Node::container([position, translated, scaled, rotated]).with_style(
    Style::default()
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::width(Percentage(100.0)))
      .with(StyleDeclaration::height(Percentage(100.0)))
      .with(StyleDeclaration::background_color(ColorInput::Value(
        Color::white(),
      )))
      .with(StyleDeclaration::display(Display::Flex))
      .with(StyleDeclaration::font_size(Px(24.0).into())),
  );

  run_fixture_test(container, "style_transform_translate_and_scale");
}
