/*
 * Copyright 2023 Hongen Wang
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import 'dart:collection';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:proxypin/l10n/app_localizations.dart';
import 'package:proxypin/network/bin/configuration.dart';
import 'package:proxypin/network/bin/server.dart';
import 'package:proxypin/network/http/http.dart';
import 'package:proxypin/ui/component/multi_select_controller.dart';
import 'package:proxypin/ui/component/utils.dart';
import 'package:proxypin/ui/desktop/request/request.dart';
import 'package:proxypin/utils/keyword_highlight.dart';
import 'package:proxypin/utils/listenable_list.dart';

import '../../component/model/search_model.dart';

///请求序列 列表
/// @author wanghongen
class RequestSequence extends StatefulWidget {
  final ListenableList<HttpRequest> container;
  final ProxyServer proxyServer;
  final bool displayDomain;
  final Function(List<HttpRequest>)? onRemove;
  final MultiSelectController selectionController;
  final RequestSelectionHandlers selectionHandlers;

  const RequestSequence(
      {super.key,
      required this.container,
      required this.proxyServer,
      this.displayDomain = true,
      this.onRemove,
      required this.selectionController,
      required this.selectionHandlers});

  @override
  State<StatefulWidget> createState() {
    return RequestSequenceState();
  }
}

class RequestSequenceState extends State<RequestSequence> with AutomaticKeepAliveClientMixin {
  late Configuration configuration;

  ///显示的请求列表 最新的在前面
  Queue<HttpRequest> view = Queue();
  final Map<String, GlobalKey> rowKeys = <String, GlobalKey>{};
  bool changing = false;

  bool sortDesc = true;

  AppLocalizations get localizations => AppLocalizations.of(context)!;

  //搜索的内容
  SearchModel? searchModel;

  //关键词高亮监听
  late VoidCallback highlightListener;
  late MultiSelectListener<String> selectionListener;

  MultiSelectController get selectionController => widget.selectionController;

  @override
  void initState() {
    super.initState();
    configuration = widget.proxyServer.configuration;
    view.addAll(widget.container.source.reversed);

    highlightListener = () {
      //回调时机在高亮设置页面dispose之后。所以需要在下一帧刷新，否则会报错
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
        highlightHandler();
      });
    };
    KeywordHighlights.addListener(highlightListener);

    selectionListener = MultiSelectListener((items) {
      if (!mounted) {
        return;
      }
      _refreshChangedRows(items);
    });
    selectionController.selectedIds.addListener(selectionListener);
  }

  void changeState() {
    //防止频繁刷新
    if (!changing) {
      changing = true;
      Future.delayed(const Duration(milliseconds: 500), () {
        setState(() {
          changing = false;
        });
      });
    }
  }

  @override
  bool get wantKeepAlive => true;

  @override
  void dispose() {
    selectionController.selectedIds.removeListener(selectionListener);
    KeywordHighlights.removeListener(highlightListener);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return ListView.separated(
      cacheExtent: 1000,
      separatorBuilder: (context, index) => Divider(thickness: 0.2, height: 0, color: Theme.of(context).dividerColor),
      itemCount: view.length,
      itemBuilder: (context, index) {
        final request = view.elementAt(index);
        final requestId = request.requestId;
        final key = rowKeys.putIfAbsent(requestId, () => GlobalKey());
        return RequestWidget(
          key: key,
          request,
          index: sortDesc ? view.length - index : index,
          trailing: appIcon(request),
          proxyServer: widget.proxyServer,
          displayDomain: widget.displayDomain,
          multiSelectController: selectionController,
          selectionHandlers: widget.selectionHandlers,
          remove: (requestWidget) {
            setState(() {
              view.remove(requestWidget.request);
              rowKeys.remove(requestWidget.request.requestId);
              widget.onRemove?.call([requestWidget.request]);
            });
          },
        );
      },
    );
  }

  Widget? appIcon(HttpRequest request) {
    var processInfo = request.processInfo;
    if (processInfo == null) {
      return null;
    }

    return futureWidget(
        processInfo.getIcon(),
        (data) => data.isEmpty
            ? const SizedBox()
            : Image.memory(
                data,
                width: 23,
                height: Platform.isWindows ? 16 : null,
                errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) => const SizedBox(),
              ));
  }

  ///高亮处理
  void highlightHandler() {
    setState(() {});
  }

  ///添加请求
  void add(HttpRequest request) {
    ///过滤
    if (searchModel?.isNotEmpty == true && !searchModel!.filter(request, request.response)) {
      return;
    }

    if (sortDesc) {
      view.addFirst(request);
    } else {
      view.addLast(request);
    }

    rowKeys.putIfAbsent(request.requestId, () => GlobalKey());

    changeState();
  }

  ///添加响应
  void addResponse(HttpResponse response) {
    if (searchModel == null || searchModel!.isEmpty || response.request == null) {
      changeState();
      return;
    }

    //搜索视图
    if (searchModel?.filter(response.request!, response) == true) {
      if (!view.contains(response.request)) {
        view.addFirst(response.request!);
        rowKeys.putIfAbsent(response.request!.requestId, () => GlobalKey());
        changeState();
      }
    }
  }

  ///过滤
  void search(SearchModel searchModel) {
    this.searchModel = searchModel;
    if (searchModel.isEmpty) {
      view = Queue.of(widget.container.source.reversed);
    } else {
      view = Queue.of(widget.container.where((it) => searchModel.filter(it, it.response)).toList().reversed);
    }
    rowKeys.removeWhere((requestId, _) => !view.any((request) => request.requestId == requestId));
    selectionController.prune(view.map((request) => request.requestId));
    setState(() {});
  }

  void remove(List<HttpRequest> list) {
    setState(() {
      view.removeWhere((element) => list.contains(element));
      for (final request in list) {
        rowKeys.remove(request.requestId);
      }
    });
  }

  void clean() {
    setState(() {
      view.clear();
      rowKeys.clear();
      view.addAll(widget.container.source.reversed);
    });
  }

  void selectRange(HttpRequest request) {
    setState(() {
      selectionController.selectRange(view.map((item) => item.requestId).toList(), request.requestId);
    });
  }

  ///排序
  void sort(bool desc) {
    sortDesc = desc;
    setState(() {
      view = Queue.of(view.toList().reversed);
    });
  }

  void _refreshChangedRows(List<String> changedIds) {
    if (changedIds.isEmpty) {
      return;
    }

    for (final requestId in changedIds) {
      final key = rowKeys[requestId];
      key?.currentState?.setState(() {});
    }
  }
}
