// 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 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

import 'package:cocoon_service/protos.dart' show Commit;

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({
    Key key,
    @required this.commit,
  })  : assert(commit != null),
        super(key: key);

  /// The commit being shown
  final Commit commit;

  @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,
      ),
    );

    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({
    Key key,
    @required this.parentContext,
    @required this.commit,
    @required this.closeCallback,
  })  : assert(parentContext != null),
        assert(commit != null),
        assert(closeCallback != null),
        super(key: key);

  /// 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;

  @override
  Widget build(BuildContext context) {
    final RenderBox renderBox = parentContext.findRenderObject() as RenderBox;
    final Offset 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: Column(
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                ListTile(
                  leading: CommitAuthorAvatar(commit: commit),
                  // TODO(chillers): Show commit message here instead: https://github.com/flutter/cocoon/issues/435
                  // Shorten the SHA as we only need first 7 digits to be able
                  // to lookup the commit.
                  title: SelectableText(commit.sha.substring(0, 7)),
                  subtitle: SelectableText(commit.author),
                ),
                ButtonBar(
                  children: <Widget>[
                    ProgressButton(
                      child: const Text('OPEN GITHUB'),
                      onPressed: _openGithub,
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }

  Future<void> _openGithub() async {
    final String githubUrl = 'https://github.com/${commit.repository}/commit/${commit.sha}';
    await launch(githubUrl);
  }
}
