// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math' as math;

import 'package:flutter/material.dart';

class ExampleDragTarget extends StatefulWidget {
  const ExampleDragTarget({super.key});

  @override
  ExampleDragTargetState createState() => ExampleDragTargetState();
}

class ExampleDragTargetState extends State<ExampleDragTarget> {
  Color _color = Colors.grey;

  void _handleAccept(Color data) {
    setState(() {
      _color = data;
    });
  }

  @override
  Widget build(BuildContext context) {
    return DragTarget<Color>(
      onAccept: _handleAccept,
      builder: (BuildContext context, List<Color?> data, List<dynamic> rejectedData) {
        return Container(
          height: 100.0,
          margin: const EdgeInsets.all(10.0),
          decoration: BoxDecoration(
            color: data.isEmpty ? _color : Colors.grey.shade200,
            border: Border.all(
              width: 3.0,
              color: data.isEmpty ? Colors.white : Colors.blue,
            ),
          ),
        );
      },
    );
  }
}

class Dot extends StatefulWidget {
  const Dot({ super.key, this.color, this.size, this.child, this.tappable = false });

  final Color? color;
  final double? size;
  final Widget? child;
  final bool tappable;

  @override
  DotState createState() => DotState();
}
class DotState extends State<Dot> {
  int taps = 0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.tappable ? () { setState(() { taps += 1; }); } : null,
      child: Container(
        width: widget.size,
        height: widget.size,
        decoration: BoxDecoration(
          color: widget.color,
          border: Border.all(width: taps.toDouble()),
          shape: BoxShape.circle,
        ),
        child: widget.child,
      ),
    );
  }
}

class ExampleDragSource extends StatelessWidget {
  const ExampleDragSource({
    super.key,
    this.color,
    this.heavy = false,
    this.under = true,
    this.child,
  });

  final Color? color;
  final bool heavy;
  final bool under;
  final Widget? child;

  static const double kDotSize = 50.0;
  static const double kHeavyMultiplier = 1.5;
  static const double kFingerSize = 50.0;

  @override
  Widget build(BuildContext context) {
    double size = kDotSize;
    if (heavy) {
      size *= kHeavyMultiplier;
    }

    final Widget contents = DefaultTextStyle(
      style: Theme.of(context).textTheme.bodyMedium!,
      textAlign: TextAlign.center,
      child: Dot(
        color: color,
        size: size,
        child: Center(child: child),
      ),
    );

    Widget feedback = Opacity(
      opacity: 0.75,
      child: contents,
    );

    Offset feedbackOffset;
    DragAnchorStrategy dragAnchorStrategy;
    if (!under) {
      feedback = Transform(
        transform: Matrix4.identity()
                     ..translate(-size / 2.0, -(size / 2.0 + kFingerSize)),
        child: feedback,
      );
      feedbackOffset = const Offset(0.0, -kFingerSize);
      dragAnchorStrategy = pointerDragAnchorStrategy;
    } else {
      feedbackOffset = Offset.zero;
      dragAnchorStrategy = childDragAnchorStrategy;
    }

    if (heavy) {
      return LongPressDraggable<Color>(
        data: color,
        feedback: feedback,
        feedbackOffset: feedbackOffset,
        dragAnchorStrategy: dragAnchorStrategy,
        child: contents,
      );
    } else {
      return Draggable<Color>(
        data: color,
        feedback: feedback,
        feedbackOffset: feedbackOffset,
        dragAnchorStrategy: dragAnchorStrategy,
        child: contents,
      );
    }
  }
}

class DashOutlineCirclePainter extends CustomPainter {
  const DashOutlineCirclePainter();

  static const int segments = 17;
  static const double deltaTheta = math.pi * 2 / segments; // radians
  static const double segmentArc = deltaTheta / 2.0; // radians
  static const double startOffset = 1.0; // radians

  @override
  void paint(Canvas canvas, Size size) {
    final double radius = size.shortestSide / 2.0;
    final Paint paint = Paint()
      ..color = const Color(0xFF000000)
      ..style = PaintingStyle.stroke
      ..strokeWidth = radius / 10.0;
    final Path path = Path();
    final Rect box = Offset.zero & size;
    for (double theta = 0.0; theta < math.pi * 2.0; theta += deltaTheta) {
      path.addArc(box, theta + startOffset, segmentArc);
    }
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(DashOutlineCirclePainter oldDelegate) => false;
}

class MovableBall extends StatelessWidget {
  const MovableBall(this.position, this.ballPosition, this.callback, {super.key});

  final int position;
  final int ballPosition;
  final ValueChanged<int> callback;

  static final GlobalKey kBallKey = GlobalKey();
  static const double kBallSize = 50.0;

  @override
  Widget build(BuildContext context) {
    final Widget ball = DefaultTextStyle(
      style: Theme.of(context).primaryTextTheme.bodyMedium!,
      textAlign: TextAlign.center,
      child: Dot(
        key: kBallKey,
        color: Colors.blue.shade700,
        size: kBallSize,
        tappable: true,
        child: const Center(child: Text('BALL')),
      ),
    );
    const Widget dashedBall = SizedBox(
      width: kBallSize,
      height: kBallSize,
      child: CustomPaint(
        painter: DashOutlineCirclePainter()
      ),
    );
    if (position == ballPosition) {
      return Draggable<bool>(
        data: true,
        childWhenDragging: dashedBall,
        feedback: ball,
        maxSimultaneousDrags: 1,
        child: ball,
      );
    } else {
      return DragTarget<bool>(
        onAccept: (bool data) { callback(position); },
        builder: (BuildContext context, List<bool?> accepted, List<dynamic> rejected) {
          return dashedBall;
        },
      );
    }
  }
}

class DragAndDropApp extends StatefulWidget {
  const DragAndDropApp({super.key});

  @override
  DragAndDropAppState createState() => DragAndDropAppState();
}

class DragAndDropAppState extends State<DragAndDropApp> {
  int position = 1;

  void moveBall(int newPosition) {
    setState(() { position = newPosition; });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Drag and Drop Flutter Demo'),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                ExampleDragSource(
                  color: Colors.yellow.shade300,
                  child: const Text('under'),
                ),
                ExampleDragSource(
                  color: Colors.green.shade300,
                  under: false,
                  heavy: true,
                  child: const Text('long-press above'),
                ),
                ExampleDragSource(
                  color: Colors.indigo.shade300,
                  under: false,
                  child: const Text('above'),
                ),
              ],
            ),
          ),
          Expanded(
            child: Row(
              children: const <Widget>[
                Expanded(child: ExampleDragTarget()),
                Expanded(child: ExampleDragTarget()),
                Expanded(child: ExampleDragTarget()),
                Expanded(child: ExampleDragTarget()),
              ],
            ),
          ),
          Expanded(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                MovableBall(1, position, moveBall),
                MovableBall(2, position, moveBall),
                MovableBall(3, position, moveBall),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

void main() {
  runApp(const MaterialApp(
    title: 'Drag and Drop Flutter Demo',
    home: DragAndDropApp(),
  ));
}
