import 'package:flutter/material.dart';

enum BubbleNip { leftTop, rightBottom, none }

class BubbleEdges {
  const BubbleEdges.only({
    this.top = 0,
    this.bottom = 0,
    this.left = 0,
    this.right = 0,
  });
  const BubbleEdges.all(double value)
    : top = value,
      bottom = value,
      left = value,
      right = value;

  final double top;
  final double bottom;
  final double left;
  final double right;

  EdgeInsets toEdgeInsets() => EdgeInsets.fromLTRB(left, top, right, bottom);
}

class BubbleStyle {
  const BubbleStyle({
    this.color,
    this.borderWidth = 0,
    this.borderColor,
    this.elevation = 0,
    this.margin = const BubbleEdges.only(),
    this.padding = const BubbleEdges.all(8),
    this.alignment = Alignment.centerLeft,
    this.nip = BubbleNip.none,
    this.borderRadius = 12,
  });

  final Color? color;
  final double borderWidth;
  final Color? borderColor;
  final double elevation;
  final BubbleEdges margin;
  final BubbleEdges padding;
  final Alignment alignment;
  final BubbleNip nip;
  final double borderRadius;

  BubbleStyle copyWith({double? borderWidth, Color? borderColor}) => BubbleStyle(
    color: color,
    borderWidth: borderWidth ?? this.borderWidth,
    borderColor: borderColor ?? this.borderColor,
    elevation: elevation,
    margin: margin,
    padding: padding,
    alignment: alignment,
    nip: nip,
    borderRadius: borderRadius,
  );
}

/// The "nip" is faked by flattening one corner so the bubble anchors to
/// the speaker side.
class Bubble extends StatelessWidget {
  const Bubble({required this.child, required this.style, super.key});

  final Widget child;
  final BubbleStyle style;

  BorderRadius _radius() {
    final r = Radius.circular(style.borderRadius);
    final flat = Radius.zero;
    switch (style.nip) {
      case BubbleNip.leftTop:
        return BorderRadius.only(
          topLeft: flat,
          topRight: r,
          bottomLeft: r,
          bottomRight: r,
        );
      case BubbleNip.rightBottom:
        return BorderRadius.only(
          topLeft: r,
          topRight: r,
          bottomLeft: r,
          bottomRight: flat,
        );
      case BubbleNip.none:
        return BorderRadius.all(r);
    }
  }

  @override
  Widget build(BuildContext context) {
    final radius = _radius();
    return Align(
      alignment: style.alignment,
      child: Container(
        margin: style.margin.toEdgeInsets(),
        decoration: BoxDecoration(
          color: style.color,
          borderRadius: radius,
          border: style.borderWidth > 0
              ? Border.all(
                  color: style.borderColor ?? Theme.of(context).dividerColor,
                  width: style.borderWidth,
                )
              : null,
          boxShadow: style.elevation > 0
              ? [
                  BoxShadow(
                    color: Colors.black26,
                    blurRadius: style.elevation * 2,
                    offset: Offset(0, style.elevation),
                  ),
                ]
              : null,
        ),
        padding: style.padding.toEdgeInsets(),
        child: child,
      ),
    );
  }
}
