part of 'tab.dart';

extension on _ServerPageState {
  Widget _buildServerCardTitle(ServerState s) {
    return Padding(
      padding: const EdgeInsets.only(left: 7, right: 13),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(s.spi.name, style: UIs.text13Bold, maxLines: 1, overflow: TextOverflow.ellipsis),
          const Icon(Icons.keyboard_arrow_right, size: 17, color: Colors.grey),
          const Spacer(),
          _buildTopRightText(s),
          _buildTopRightWidget(s),
        ],
      ),
    );
  }

  Widget _buildTopRightWidget(ServerState s) {
    final (child, onTap) = switch (s.conn) {
      ServerConn.connecting || ServerConn.loading || ServerConn.connected => (
        SizedBox.square(
          dimension: _ServerPageState._kCardHeightMin,
          child: SizedLoading(_ServerPageState._kCardHeightMin, padding: 3),
        ),
        null,
      ),
      ServerConn.failed => (
        const Icon(Icons.refresh, size: 21, color: Colors.grey),
        () {
          TryLimiter.reset(s.spi.id);
          ref.read(serversProvider.notifier).refresh(spi: s.spi);
        },
      ),
      ServerConn.disconnected => (
        const Icon(MingCute.link_3_line, size: 19, color: Colors.grey),
        () => ref.read(serversProvider.notifier).refresh(spi: s.spi),
      ),
      ServerConn.finished => (
        const Icon(MingCute.unlink_2_line, size: 17, color: Colors.grey),
        () => ref.read(serversProvider.notifier).closeServer(id: s.spi.id),
      ),
    };

    // Or the loading icon will be rescaled.
    final wrapped = child is SizedBox
        ? child
        : SizedBox(height: _ServerPageState._kCardHeightMin, width: 27, child: child);
    if (onTap == null) return wrapped.paddingOnly(left: 10);
    return InkWell(borderRadius: BorderRadius.circular(7), onTap: onTap, child: wrapped).paddingOnly(left: 5);
  }

  Widget _buildTopRightText(ServerState s) {
    final hasErr = s.status.err != null;
    final str = s._getTopRightStr(s.spi);
    if (str == null) return UIs.placeholder;
    return GestureDetector(
      onTap: () {
        if (!hasErr) return;
        _showFailReason(s.status);
      },
      child: Text(str, style: UIs.text13Grey),
    );
  }

  void _showFailReason(ServerStatus ss) {
    final md =
        '''
${ss.err?.solution ?? l10n.unknown}

```sh
${ss.err?.message ?? 'null'}
''';
    context.showRoundDialog(
      title: libL10n.error,
      child: SingleChildScrollView(child: SimpleMarkdown(data: md)),
      actions: [TextButton(onPressed: () => Pfs.copy(md), child: Text(libL10n.copy))],
    );
  }

  Widget _buildDisk(ServerStatus ss, String id) {
    final cardNoti = _getCardNoti(id);
    return cardNoti.listenVal((v) {
      final isSpeed = v.diskIO ?? !Stores.setting.serverTabPreferDiskAmount.fetch();

      final (r, w) = ss.diskIO.cachedAllSpeed;

      return AnimatedSwitcher(
        duration: const Duration(milliseconds: 377),
        transitionBuilder: (child, animation) {
          return FadeTransition(opacity: animation, child: child);
        },
        child: _buildIOData(
          isSpeed ? '${l10n.read}:\n$r' : 'Total:\n${ss.diskUsage?.size.kb2Str}',
          isSpeed ? '${l10n.write}:\n$w' : 'Used:\n${ss.diskUsage?.used.kb2Str}',
          onTap: () {
            cardNoti.value = v.copyWith(diskIO: !isSpeed);
          },
          key: ValueKey(isSpeed),
        ),
      );
    });
  }

  Widget _buildNet(ServerStatus ss, String id) {
    final cardNoti = _getCardNoti(id);
    final type = cardNoti.value.net ?? Stores.setting.netViewType.fetch();
    final device = ref.watch(serversProvider).servers[id]?.custom?.netDev;
    final (a, b) = type.build(ss, dev: device);
    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 377),
      transitionBuilder: (c, anim) => FadeTransition(opacity: anim, child: c),
      child: _buildIOData(
        a,
        b,
        onTap: () => cardNoti.value = cardNoti.value.copyWith(net: type.next),
        key: ValueKey(type),
      ),
    );
  }

  Widget _buildIOData(String up, String down, {void Function()? onTap, Key? key, int maxLines = 2}) {
    final child = Column(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          up,
          style: const TextStyle(fontSize: 10, color: Colors.grey),
          textAlign: TextAlign.center,
          textScaler: _textFactor,
          maxLines: maxLines,
        ),
        const SizedBox(height: 3),
        Text(
          down,
          style: const TextStyle(fontSize: 10, color: Colors.grey),
          textAlign: TextAlign.center,
          textScaler: _textFactor,
          maxLines: maxLines,
        ),
      ],
    );
    if (onTap == null) return child;
    return IconButton(
      key: key,
      padding: const EdgeInsets.symmetric(horizontal: 3),
      onPressed: onTap,
      icon: child,
    );
  }
}
