import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';

import '../models/timeline_entry.dart';
import '../services/auth_service.dart';
import '../utils/clipboard_utils.dart';
import '../utils/url_opening_utils.dart';
import 'html_text_viewer_control.dart';
import 'media_attachment_viewer_control.dart';
import 'padding.dart';
import 'timeline/link_preview_control.dart';
import 'timeline/status_header_control.dart';

class SearchResultStatusControl extends StatefulWidget {
  static final _logger = Logger('$SearchResultStatusControl');
  final TimelineEntry status;

  final Future Function() goToPostFunction;

  const SearchResultStatusControl(this.status, this.goToPostFunction,
      {super.key});

  @override
  State<SearchResultStatusControl> createState() =>
      _SearchResultStatusControlState();
}

class _SearchResultStatusControlState extends State<SearchResultStatusControl> {
  var showContent = false;

  TimelineEntry get status => widget.status;

  @override
  void initState() {
    super.initState();
    showContent = widget.status.spoilerText.isEmpty;
  }

  @override
  Widget build(BuildContext context) {
    SearchResultStatusControl._logger
        .finest('Building ${widget.status.toShortString()}');
    const otherPadding = 8.0;
    final body = Container(
      decoration: BoxDecoration(
        color: Theme.of(context).dialogBackgroundColor,
        border: Border.all(width: 0.5),
        borderRadius: BorderRadius.circular(5.0),
        boxShadow: [
          BoxShadow(
            color: Theme.of(context).dividerColor,
            blurRadius: 2,
            offset: const Offset(4, 4),
            spreadRadius: 0.1,
            blurStyle: BlurStyle.normal,
          )
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.all(5.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Expanded(
                  child: StatusHeaderControl(
                    entry: widget.status,
                    showIsCommentText: true,
                  ),
                ),
                buildMenuControl(context),
              ],
            ),
            const VerticalPadding(
              height: 5,
            ),
            if (status.spoilerText.isNotEmpty)
              TextButton(
                  onPressed: () {
                    setState(() {
                      showContent = !showContent;
                    });
                  },
                  child: Text(
                      'Content Summary: ${status.spoilerText} (Click to ${showContent ? "Hide" : "Show"}}')),
            if (showContent) ...[
              buildBody(context),
              const VerticalPadding(
                height: 5,
              ),
              if (status.linkPreviewData != null)
                LinkPreviewControl(preview: status.linkPreviewData!),
              buildMediaBar(context),
            ],
            const VerticalPadding(
              height: 5,
            ),
            const VerticalPadding(
              height: 5,
            ),
          ],
        ),
      ),
    );
    return Padding(
      padding: const EdgeInsets.only(
        left: otherPadding,
        right: otherPadding,
        top: otherPadding,
        bottom: otherPadding,
      ),
      child: body,
    );
  }

  Widget buildBody(BuildContext context) {
    return HtmlTextViewerControl(
      content: widget.status.body,
      onTapUrl: (url) async =>
          await openUrlStringInSystembrowser(context, url, 'link'),
    );
  }

  Widget buildMediaBar(BuildContext context) {
    final items = widget.status.mediaAttachments;
    if (items.isEmpty) {
      return const SizedBox();
    }

    // A Link Preview with only one media attachment will have a duplicate image
    // even though it points to different resources server side. So we don't
    // want to render it twice.
    if (widget.status.linkPreviewData != null && items.length == 1) {
      return const SizedBox();
    }

    // A Diaspora reshare will have an HTML-built card with a link preview image
    // to the same image as what would be in the single attachment but at a
    // different link. So we don't want it to render twice.
    final linkPhotoBaseUrl = Uri.https(
      context.read<AccountsService>().currentProfile.serverName,
      'photo/link',
    ).toString();
    if (widget.status.body.contains(linkPhotoBaseUrl) && items.length == 1) {
      return const SizedBox();
    }

    return SizedBox(
        height: 250.0,
        child: ListView.separated(
            scrollDirection: Axis.horizontal,
            itemBuilder: (context, index) {
              return MediaAttachmentViewerControl(
                attachments: items,
                index: index,
              );
            },
            separatorBuilder: (context, index) {
              return const HorizontalPadding();
            },
            itemCount: items.length));
  }

  Widget buildMenuControl(BuildContext context) {
    const goToPost = 'Open Post';
    const copyText = 'Copy Post Text';
    const copyUrl = 'Copy URL';
    const openExternal = 'Open In Browser';
    final options = [
      goToPost,
      copyText,
      openExternal,
      copyUrl,
    ];

    return PopupMenuButton<String>(onSelected: (menuOption) async {
      if (!context.mounted) {
        return;
      }

      switch (menuOption) {
        case goToPost:
          await widget.goToPostFunction();
          break;
        case openExternal:
          await openUrlStringInSystembrowser(
            context,
            widget.status.externalLink,
            'Status',
          );
          break;
        case copyUrl:
          await copyToClipboard(
            context: context,
            text: widget.status.externalLink,
            message: 'Status link copied to clipboard',
          );
          break;
        case copyText:
          await copyToClipboard(
            context: context,
            text: widget.status.body,
            message: 'Status text copied to clipboard',
          );
          break;
        default:
        //do nothing
      }
    }, itemBuilder: (context) {
      return options
          .map((o) => PopupMenuItem(value: o, child: Text(o)))
          .toList();
    });
  }
}
