import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:shortid/shortid.dart';
import 'package:path/path.dart' as path;

import '../../constants/assets.dart';
import 'menu_base/menu_base.dart';
import 'tray_listener.dart';

const kEventOnTrayIconLButtonDown = 'onTrayIconLButtonDown';
const kEventOnTrayIconLButtonUp = 'onTrayIconLButtonUp';
const kEventOnTrayIconRButtonDown = 'onTrayIconRButtonDown';
const kEventOnTrayIconRButtonUp = 'onTrayIconRButtonUp';
const kEventOnTrayMenuItemClick = 'onTrayMenuItemClick';

class TrayController {
  final _channel = const MethodChannel("app.flashlink/tray");
  final ObserverList<TrayListener> _listeners = ObserverList<TrayListener>();
  Menu? _trayMenu;

  TrayController() {
    _channel.setMethodCallHandler(_methodCallHandler);
  }

  Future<void> _methodCallHandler(MethodCall call) async {
    for (final TrayListener listener in _listeners) {
      switch (call.method) {
        case kEventOnTrayIconLButtonDown:
          listener.onTrayIconLButtonDown();
          break;
        case kEventOnTrayIconLButtonUp:
          listener.onTrayIconLButtonUp();
          break;
        case kEventOnTrayIconRButtonDown:
          listener.onTrayIconRButtonDown();
          break;
        case kEventOnTrayIconRButtonUp:
          listener.onTrayIconRButtonUp();
          break;
        case kEventOnTrayMenuItemClick:
          int id = call.arguments['id'];
          MenuItem? menuItem = _trayMenu?.getMenuItemById(id);
          if (menuItem != null) {
            bool? oldChecked = menuItem.checked;
            if (menuItem.onClick != null) {
              menuItem.onClick!(menuItem);
            }
            listener.onTrayMenuItemClick(menuItem);

            bool? newChecked = menuItem.checked;
            if (oldChecked != newChecked) {
              await _setContextMenu(_trayMenu!);
            }
          }
          break;
      }
    }
  }

  Future<void> _setContextMenu(Menu menu) {
    _trayMenu = menu;
    final Map<String, dynamic> arguments = {'menu': menu.toJson()};
    return _channel.invokeMethod('setContextMenu', arguments);
  }

  Future<void> _setSystemTrayWindows(String iconPath, String? tooltip) {
    final Map<String, dynamic> arguments = {
      'id': shortid.generate(),
      'icon': path.joinAll([
        path.dirname(Platform.resolvedExecutable),
        'data/flutter_assets',
        iconPath,
      ]),
      'tooltip': tooltip ?? '',
    };
    return _channel.invokeMethod('setSystemTray', arguments);
  }

  /// 设置托盘图标
  Future<void> setSystemTray(
    bool isConnected,
    bool isDark, {
    String? title,
    String? tooltip,
  }) {
    String iconPath;
    if (isConnected) {
      iconPath = isDark
          ? Assets.trayIconDarkConnectedWin
          : Assets.trayIconLightConnectedWin;
    } else {
      iconPath = isDark
          ? Assets.trayIconDarkUnConnectedWin
          : Assets.trayIconLightUnConnectedWin;
    }
    if (Platform.isWindows) {
      return _setSystemTrayWindows(iconPath, tooltip);
    } else {
      throw UnimplementedError();
    }
  }

  /// 设置托盘菜单
  Future<void> setContextMenu(Menu trayMenu) {
    return _setContextMenu(trayMenu);
  }

  /// 弹出系统托盘菜单
  Future<void> popUpContextMenu() {
    return _channel.invokeMethod('popupContextMenu');
  }

  /// 销毁系统托盘
  Future<void> resetSystemTray() {
    return _channel.invokeMethod('resetSystemTray');
  }

  bool get hasListeners {
    return _listeners.isNotEmpty;
  }

  void addListener(TrayListener listener) {
    _listeners.add(listener);
  }

  void removeListener(TrayListener listener) {
    _listeners.remove(listener);
  }
}
