// Copyright 2019 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:async';

import 'package:cocoon_common/rpc_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/link.dart';

import 'commit_author_avatar.dart';
import 'progress_button.dart';

// TODO(ianh): Factor out the logic in task_overlay.dart and use it here as well,
// so that all our popups have the same look and feel and we don't duplicate code.

/// Displays Git commit information.
///
/// On click, it will open an [OverlayEntry] with [CommitOverlayContents]
/// to show the information provided. Otherwise, it just shows the avatar
/// for the author of this commit. Clicking outside of the [OverlayEntry]
/// will close it.
class CommitBox extends StatefulWidget {
  const CommitBox({
    super.key,
    required this.commit,
    this.schedulePostsubmitBuild,
  });

  /// The commit being shown
  final Commit commit;

  /// Whether to provide a 'schedule build' button'.
  final Future<void> Function()? schedulePostsubmitBuild;

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

class CommitBoxState extends State<CommitBox> {
  OverlayEntry? _commitOverlay;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: _handleTap,
      child: Padding(
        padding: const EdgeInsets.all(4.0),
        child: CommitAuthorAvatar(commit: widget.commit),
      ),
    );
  }

  void _handleTap() {
    _commitOverlay = OverlayEntry(
      builder: (_) => CommitOverlayContents(
        parentContext: context,
        commit: widget.commit,
        closeCallback: _closeOverlay,
        schedulePostsubmitBuild: widget.schedulePostsubmitBuild,
      ),
    );

    Overlay.of(context).insert(_commitOverlay!);
  }

  void _closeOverlay() => _commitOverlay?.remove();
}

/// Displays the information from a Git commit.
///
/// This is intended to be inserted in an [OverlayEntry] as it requires
/// [closeCallback] that will remove the widget from the tree.
class CommitOverlayContents extends StatelessWidget {
  const CommitOverlayContents({
    super.key,
    required this.parentContext,
    required this.commit,
    required this.closeCallback,
    required this.schedulePostsubmitBuild,
  });

  /// The parent context that has the size of the whole screen
  final BuildContext parentContext;

  /// The commit data to display in the overlay
  final Commit commit;

  /// This callback removes the parent overlay from the widget tree.
  ///
  /// On a click that is outside the area of the overlay (the rest of the screen),
  /// this callback is called closing the overlay.
  final void Function() closeCallback;

  /// This callback schedules a post-submit build.
  final Future<void> Function()? schedulePostsubmitBuild;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final renderBox = parentContext.findRenderObject() as RenderBox;
    final offsetLeft = renderBox.localToGlobal(Offset.zero);
    return Stack(
      children: <Widget>[
        // This is the area a user can click (the rest of the screen) to close the overlay.
        GestureDetector(
          onTap: closeCallback,
          child: Container(
            width: MediaQuery.of(parentContext).size.width,
            height: MediaQuery.of(parentContext).size.height,
            // Color must be defined otherwise the container can't be clicked on
            color: Colors.transparent,
          ),
        ),
        Positioned(
          width: 300,
          // Move this overlay to be where the parent is
          top: offsetLeft.dy + (renderBox.size.height / 2),
          left: offsetLeft.dx + (renderBox.size.width / 2),
          child: Card(
            child: SafeArea(
              minimum: const EdgeInsets.all(16),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  CommitAuthorAvatar(commit: commit),
                  Expanded(
                    child: Padding(
                      padding: const EdgeInsetsDirectional.only(start: 16),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: <Widget>[
                          Align(
                            alignment: Alignment.centerLeft,
                            child: AnimatedDefaultTextStyle(
                              style: theme.textTheme.titleMedium!,
                              duration: kThemeChangeDuration,
                              child: Row(
                                children: <Widget>[
                                  Link(
                                    uri: Uri.https(
                                      'github.com',
                                      '${commit.repository}/commit/${commit.sha}',
                                    ),
                                    builder: (context, open) {
                                      return ElevatedButton(
                                        onPressed: open,
                                        child: Text(commit.sha.substring(0, 7)),
                                      );
                                    },
                                  ),
                                  IconButton(
                                    icon: const Icon(Icons.copy),
                                    onPressed: () => unawaited(
                                      Clipboard.setData(
                                        ClipboardData(text: commit.sha),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(height: 8),
                          Padding(
                            padding: const EdgeInsets.only(bottom: 4),
                            child: AnimatedDefaultTextStyle(
                              style: theme.textTheme.bodyMedium!.copyWith(
                                color: theme.textTheme.bodySmall!.color,
                              ),
                              duration: kThemeChangeDuration,
                              child: SelectableText(
                                commit.message.split('\n').first,
                              ),
                            ),
                          ),
                          SelectableText(commit.author.login),
                          Tooltip(
                            key: const ValueKey('schedulePostsubmit'),
                            message: schedulePostsubmitBuild == null
                                ? 'Only enabled for release branches'
                                : ''
                                      'For release branches, the post-submit artifacts are not '
                                      'immediately available and must be manually scheduled.',
                            child: Padding(
                              padding: const EdgeInsets.only(top: 8.0),
                              child: ProgressButton(
                                child: const Text('Run all tasks'),
                                onPressed: schedulePostsubmitBuild,
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ],
    );
  }
}
