import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:flux_ui/flux_ui.dart';

import '../../../common/config/models/index.dart';
import '../helper/helper.dart';

/// layout : 'bannerImage'
/// design : 'default'
/// fit : 'cover'
/// marginLeft : 5
/// intervalTime : 3
/// items : [{'category':28,'image':'https://user-images.githubusercontent.com/1459805/59846818-12672e80-938b-11e9-8184-5f7bfe66f1a2.png','padding':15},{'padding':15,'image':'https://user-images.githubusercontent.com/1459805/60091575-1f12ca80-976f-11e9-962c-bdccff60d143.png','category':29},{'image':'https://user-images.githubusercontent.com/1459805/60091808-a19b8a00-976f-11e9-9cc7-576ca05c2442.png','padding':15,'product':30}]
/// marginBottom : 5
/// autoPlay : false
/// isSlider : true
/// height : 0.2
/// marginRight : 5
/// marginTop : 5
/// radius : 2
/// PageIndicatorType: 'circle'

const imageDefault =
    'https://user-images.githubusercontent.com/1459805/59846818-12672e80-938b-11e9-8184-5f7bfe66f1a2.png';

class BannerConfig {
  HeaderConfig? title;

  String? text;
  String? layout;
  String? design;
  String? imageBanner;
  BoxFit? fit;
  List<BannerItemConfig> items = [];
  bool isHorizontal = false;
  bool enableBackground = false;

  /// slider
  bool autoPlay = false;
  bool isSlider = false;
  bool isBlur = false;
  bool showBackground = false;
  int? intervalTime;
  double upHeight = 0.0;
  double radius = 6.0;
  double padding = 0.0;

  /// indicator
  bool showIndicator = true;
  PageIndicatorType? pageIndicatorType;
  AlignmentDirectional indicatorAlignment = AlignmentDirectional.bottomCenter;
  EdgeInsetsDirectional indicatorPadding = const EdgeInsetsDirectional.only(
    bottom: 12,
  );

  /// number
  bool showNumber = false;
  AlignmentDirectional numberAlignment = AlignmentDirectional.topEnd;
  EdgeInsetsDirectional numberPadding = const EdgeInsetsDirectional.only(
    top: 15,
    end: 0,
  );

  VideoConfig videoConfig = const VideoConfig();

  /// bool type
  double? height;
  double marginLeft = 0.0;
  double marginRight = 0.0;
  double marginTop = 0.0;
  double marginBottom = 0.0;
  bool enableParallax = false;
  double parallaxImageRatio = 1.2;
  BoxShadowConfig? boxShadow;

  double? overrideBannerPercentWidth;

  BannerConfig({
    this.layout,
    this.text,
    this.title,
    this.design,
    this.imageBanner,
    this.fit,
    this.intervalTime,
    this.enableBackground = false,
    required this.items,
    required this.marginBottom,
    required this.autoPlay,
    required this.isSlider,
    required this.showIndicator,
    required this.showNumber,
    required this.isBlur,
    required this.showBackground,
    this.pageIndicatorType,
    this.indicatorAlignment = AlignmentDirectional.bottomCenter,
    this.indicatorPadding = const EdgeInsetsDirectional.only(bottom: 12),
    this.numberAlignment = AlignmentDirectional.topEnd,
    this.numberPadding = const EdgeInsetsDirectional.only(top: 15, end: 0),
    this.videoConfig = const VideoConfig(),
    this.height,
    this.boxShadow,
    this.overrideBannerPercentWidth,
    required this.padding,
    required this.marginLeft,
    required this.marginRight,
    required this.marginTop,
    required this.upHeight,
    required this.radius,
    required this.enableParallax,
    required this.parallaxImageRatio,
  });

  BannerConfig.fromJson(dynamic json) {
    title = json['title'] != null ? HeaderConfig.fromJson(json['title']) : null;
    layout = json['layout'];
    enableBackground = json['enableBackground'] ?? false;
    text = json['text'];
    design = json['design'];
    imageBanner = json['imageBanner'];
    fit = Helper.boxFit(json['fit']);
    intervalTime = Helper.formatInt(json['intervalTime'], 3) ?? 3;
    if (json['items'] != null) {
      items = [];
      json['items'].forEach((v) {
        items.add(BannerItemConfig.fromJson(v));
      });
    }

    autoPlay = json['autoPlay'] ?? false;
    showBackground = json['showBackground'] ?? false;
    isSlider = json['isSlider'] ?? false;
    showIndicator = json['showIndicator'] ?? true;
    showNumber = json['showNumber'] ?? false;
    isBlur = json['isBlur'] ?? false;
    enableParallax = json['parallax'] ?? false;
    parallaxImageRatio = Helper.formatDouble(json['parallaxImageRatio']) ?? 1.2;
    isHorizontal = json['isHorizontal'] ?? false;
    if (json['videoConfig'] is Map) {
      videoConfig = VideoConfig.fromJson(json['videoConfig']);
    } else {
      // For backward compatibility
      videoConfig = VideoConfig(
        isSoundOn: json['isSoundOn'] ?? false,
        autoPlay: json['autoPlayVideo'] ?? false,
        enableTimeIndicator: json['enableTimeIndicator'] ?? true,
        doubleTapToFullScreen: json['doubleTapToFullScreen'] ?? false,
        aspectRatio: 16 / 9,
        showFullScreenButton: true,
        showVolumeButton: true,
      );
    }
    pageIndicatorType = PageIndicatorType.fromString(json['pageIndicatorType']);
    indicatorAlignment =
        const AlignmentDirectionalConverter().fromJson(
          json['indicatorAlignment'],
        ) ??
        indicatorAlignment;
    indicatorPadding =
        const EdgeInsetsDirectionalConverter().fromJson(
          json['indicatorPadding'],
        ) ??
        indicatorPadding;

    numberAlignment =
        const AlignmentDirectionalConverter().fromJson(
          json['numberAlignment'],
        ) ??
        numberAlignment;
    numberPadding =
        const EdgeInsetsDirectionalConverter().fromJson(
          json['numberPadding'],
        ) ??
        numberPadding;

    boxShadow = json['boxShadow'] != null
        ? BoxShadowConfig.fromJson(json['boxShadow'])
        : null;

    overrideBannerPercentWidth = Helper.formatDouble(
      json['overrideBannerPercentWidth'],
    );

    /// double
    height = Helper.formatDouble(json['height']);
    upHeight = Helper.formatDouble(json['upHeight']) ?? 0.0;
    padding = Helper.formatDouble(json['padding']) ?? 0.0;
    radius = Helper.formatDouble(json['radius']) ?? 6.0;

    /// spacing
    marginLeft = Helper.formatDouble(json['marginLeft']) ?? 0.0;
    marginRight = Helper.formatDouble(json['marginRight']) ?? 0.0;
    marginTop = Helper.formatDouble(json['marginTop']) ?? 0.0;
    marginBottom = Helper.formatDouble(json['marginBottom']) ?? 0.0;
  }

  Map<String, dynamic> toJson() {
    var map = <String, dynamic>{};
    map['layout'] = layout;
    map['design'] = design;
    map['imageBanner'] = imageBanner;
    map['fit'] = fit?.name;
    map['marginLeft'] = marginLeft;
    map['items'] = items.map((v) => v.toJson()).toList();
    map['marginBottom'] = marginBottom;
    map['height'] = height;
    map['marginRight'] = marginRight;
    map['marginTop'] = marginTop;
    map['radius'] = radius;
    map['padding'] = padding;
    map['text'] = text;
    map['title'] = title?.toJson();
    map['parallax'] = enableParallax;
    map['parallaxImageRatio'] = parallaxImageRatio;
    map['isHorizontal'] = isHorizontal;
    map['boxShadow'] = boxShadow?.toJson();
    map['enableBackground'] = enableBackground;
    map['overrideBannerPercentWidth'] = overrideBannerPercentWidth;
    map['indicatorAlignment'] = const AlignmentDirectionalConverter().toJson(
      indicatorAlignment,
    );
    map['indicatorPadding'] = const EdgeInsetsDirectionalConverter().toJson(
      indicatorPadding,
    );
    map['numberAlignment'] = const AlignmentDirectionalConverter().toJson(
      numberAlignment,
    );
    map['numberPadding'] = const EdgeInsetsDirectionalConverter().toJson(
      numberPadding,
    );

    if (isSlider) {
      map['isSlider'] = isSlider;
      map['autoPlay'] = autoPlay;
      map['intervalTime'] = intervalTime;
      map['showIndicator'] = showIndicator;
      map['showNumber'] = showNumber;
      map['isBlur'] = isBlur;
      map['showBackground'] = showBackground;
      map['upHeight'] = upHeight;
      map['videoConfig'] = videoConfig.toJson();
      map['pageIndicatorType'] = pageIndicatorType?.name;
    }
    map.removeWhere((key, value) => value == null);
    return map;
  }
}

/// category : 28
/// image : 'https://user-images.githubusercontent.com/1459805/59846818-12672e80-938b-11e9-8184-5f7bfe66f1a2.png'
/// padding : 15
enum BannerType {
  image,
  video,
  animated;

  bool get isAnimated => this == BannerType.animated;

  factory BannerType.fromString(String? type) {
    return BannerType.values.firstWhereOrNull((e) => e.name == type) ??
        BannerType.image;
  }
}

class BannerItemConfig {
  dynamic categoryId;
  late String image;
  List<dynamic>? data;
  dynamic jsonData;
  String? background;
  BannerButtonConfig? button;
  TextConfig? title;
  TextConfig? description;
  BannerType type = BannerType.image;
  AnimatedStackContainerData? animatedConfig;

  /// static layout
  double? padding;
  double? radius;
  bool bannerWithProduct = false;
  bool defaultShowProduct = false;
  int productLength = 3;
  List<String> products = [];
  String? video;

  /// If set it true then click to banner item, it will navigate to
  /// the [SubcategoryScreen] instead of navigate to product page as default
  bool showSubcategory = false;

  BannerItemConfig({
    this.categoryId,
    required this.image,
    this.radius,
    this.padding,
    this.data,
    this.jsonData,
    this.background,
    this.button,
    this.title,
    this.description,
    this.productLength = 3,
    this.bannerWithProduct = false,
    this.defaultShowProduct = false,
    this.products = const [],
    this.showSubcategory = false,
    this.video = '',
    this.type = BannerType.image,
    this.animatedConfig,
  });

  BannerItemConfig.fromJson(dynamic json) {
    categoryId = json['category'];
    image = json['image'] ?? imageDefault;
    padding = Helper.formatDouble(json['padding']);
    radius = Helper.formatDouble(json['radius']);
    data = json['data'];
    background = json['background'];
    if (json['button'] != null) {
      button = BannerButtonConfig.fromJson(json['button']);
    }
    if (json['title'] != null && json['title'] is Map) {
      title = TextConfig.fromJson(json['title']);
    }
    if (json['description'] != null) {
      description = TextConfig.fromJson(json['description']);
    }
    bannerWithProduct = json['bannerWithProduct'] ?? false;
    defaultShowProduct = json['defaultShowProduct'] ?? false;
    products = List<String>.from(json['products'] ?? []);
    productLength = int.tryParse(json['productLength'].toString()) ?? 3;
    showSubcategory = json['showSubcategory'] ?? false;
    video = json['video'] ?? '';

    type = (video?.isNotEmpty ?? false) ? BannerType.video : BannerType.image;
    if (json['type'] != null) {
      type = BannerType.fromString(json['type']);
    }
    if (json['animatedConfig'] != null && json['animatedConfig'] is Map) {
      animatedConfig = AnimatedStackContainerData.fromJson(
        json['animatedConfig'],
      );
    }
    // ignore: prefer_initializing_formals
    jsonData = json;
  }

  Map<String, dynamic> toJson() {
    var map = Map<String, dynamic>.from(jsonData);
    map['category'] = categoryId;
    map['image'] = image;
    map['padding'] = padding;
    map['radius'] = radius;
    map['data'] = data;
    map['background'] = background;
    map['showSubcategory'] = showSubcategory;
    map['button'] = button?.toJson();
    map['title'] = title?.toJson();
    map['description'] = description?.toJson();
    map['bannerWithProduct'] = bannerWithProduct;
    map['defaultShowProduct'] = defaultShowProduct;
    map['showSubcategory'] = showSubcategory;
    map['video'] = video;
    map['products'] = List<String>.from(products);
    map['productLength'] = productLength;
    map['type'] = type.name;
    map['animatedConfig'] = animatedConfig?.toJson();
    map.removeWhere((key, value) => value == null);
    return map;
  }
}

class BannerButtonConfig {
  String text = '';
  String backgroundColor = '#3FC1BE';
  String textColor = '#3FC1BE';
  Alignment alignment = Alignment.topCenter;
  String fontFamily = 'Roboto';
  double fontSize = 20.0;

  BannerButtonConfig({
    this.text = '',
    this.backgroundColor = '#3FC1BE',
    this.textColor = '#3FC1BE',
    this.fontFamily = 'Roboto',
    this.fontSize = 20.0,
    this.alignment = Alignment.topCenter,
  });

  BannerButtonConfig.fromJson(Map json) {
    text = json['text'] ?? '';
    backgroundColor = json['backgroundColor'] ?? '#3FC1BE';
    textColor = json['textColor'] ?? '#3FC1BE';
    fontFamily = json['fontFamily'] ?? 'Roboto';
    fontSize = Helper.formatDouble(json['fontSize'], 20) ?? 20.0;

    final x = Helper.formatDouble(json['x']) ?? 0.0;
    final y = Helper.formatDouble(json['y']) ?? 0.0;
    alignment = Alignment(x, y);
  }

  Map<String, dynamic> toJson() {
    var map = <String, dynamic>{};
    map['text'] = text;
    map['backgroundColor'] = backgroundColor;
    map['textColor'] = textColor;
    map['fontFamily'] = fontFamily;
    map['fontSize'] = fontSize;
    map['x'] = alignment.x;
    map['y'] = alignment.y;
    return map;
  }
}
