import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:chat/data/UserData.dart';
import 'package:chat/generated/i18n.dart';
import 'package:chat/home/InfoList.dart';
import 'package:chat/home/ProgramDetail.dart';
import 'package:chat/home/rich_title.dart';
import 'package:chat/models/received_notification.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_badger/flutter_app_badger.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:rxdart/rxdart.dart';

import 'MessageMgr.dart';

class LocalNotificationUtil {
  static bool isBackground = false;

  ///是否在后台
  static int badgerCount = 0;

  ///角标计数

  BuildContext mContext;

  factory LocalNotificationUtil() => _getInstance();
  static LocalNotificationUtil get instance => _getInstance();
  static LocalNotificationUtil _instance;

  static const String PAYLOAD_DATE = 'date';
  static const String PAYLOAD_FRIENDS = 'friends';

  /// date+@+节目id
  static const String PAYLOAD_OTHER = 'other';

  /// 其他

  LocalNotificationUtil._internal() {
    // 初始化
  }
  static LocalNotificationUtil _getInstance() {
    if (_instance == null) {
      _instance = new LocalNotificationUtil._internal();
    }
    return _instance;
  }

  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
// Streams are created so that app can respond to notification-related events since the plugin is initialised in the `main` function
  BehaviorSubject<ReceivedNotification> didReceiveLocalNotificationSubject =
      BehaviorSubject<ReceivedNotification>();

  BehaviorSubject<String> selectNotificationSubject = BehaviorSubject<String>();

  void initJPush() {
    JPush jpush = new JPush();

    ///ios一定要加这句
    jpush.applyPushAuthority(
        new NotificationSettingsIOS(sound: true, alert: true, badge: true));
    jpush.addEventHandler(
      // 接收通知回调方法。
      onReceiveNotification: (Map<String, dynamic> message) async {
        print("flutter onReceiveNotification: $message");
      },
      // 点击通知回调方法。
      onOpenNotification: (Map<String, dynamic> message) async {
        print("flutter onOpenNotification: $message");
        print("flutter onOpenNotification extras: ${message['extras']}");

//           flutter onOpenNotification: {aps: {alert: {title: ddd, body: 大幅度发}, badge: 1, sound: default}, payload: other@1, extras: {payload: other@1}, _j_uid: 33833979419, _j_msgid: 29273440739312177, _j_business: 1}
        Map jExtra = message['extras'];
        print('onOpenNotification jExtra:$jExtra');
        if (jExtra.containsKey('cn.jpush.android.EXTRA')) {
          ///android
          Map map = json.decode(jExtra['cn.jpush.android.EXTRA']);
          print('map: $map');
          String payload = getPayload(map);
          print('onOpenNotification payload:$payload');
          goPage(payload);
          return;
        } else {
          ///ios
          print("flutter jExtra : $jExtra");
          String payload = getPayload(jExtra);
          print('onOpenNotification payload:$payload');
          goPage(payload);
        }
      },
      // 接收自定义消息回调方法。
      onReceiveMessage: (Map<String, dynamic> message) async {
        print("flutter自定义 onReceiveMessage: $message");
      },
    );
    jpush.setup(
      appKey: "13dd603952a6632d1dd3ac54",
      channel: "theChannel",
      production: false,
      debug: true, // 设置是否打印 debug 日志
    );
    jpush.getRegistrationID().then((rid) {
      print('jpush getRegistrationID $rid ');
    });
  }

  void setAlias() {
    JPush jpush = new JPush();
    print('flutter jpush setAlias ${UserData().basicInfo.userId.toString()}');
    jpush.setAlias(UserData().basicInfo.userId.toString()).then((map) {});
    jpush.addTags(
      ["yueliao", 'yueliao_' + UserData().language.toString()],
    ).then((map) {});

    if (Platform.isIOS) {
      jpush.getLaunchAppNotification().then((map) {
        print('getLaunchAppNotification $map');
        Map jExtra = map['extras'];
        String payload = getPayload(jExtra);
        print('onOpenNotification payload:$payload');
        goPage(payload);
        FlutterAppBadger.removeBadge();
      }).catchError((error) {
        print('getLaunchAppNotificationerror  $error');
      });
    }
  }

  void removeAlias() {
    JPush jpush = new JPush();
    jpush.deleteAlias();
    jpush.stopPush();
  }

  void initState(BuildContext context) {
    this.mContext = context;
    if (hasInit) {
      return;
    }
    hasInit = true;
    didReceiveLocalNotificationSubject.stream
        .listen((ReceivedNotification receivedNotification) async {
      print('ios低版本推送点击:${receivedNotification.payload}');

      await showDialog(
        context: mContext,
        builder: (BuildContext context) => CupertinoAlertDialog(
          title: receivedNotification.title != null
              ? Text(receivedNotification.title)
              : null,
          content: receivedNotification.body != null
              ? Text(receivedNotification.body)
              : null,
          actions: [
            CupertinoDialogAction(
              isDefaultAction: false,
              child: Text(I18n.of(mContext).cancel),
              onPressed: () async {
                Navigator.of(mContext, rootNavigator: true).pop();
              },
            ),
            CupertinoDialogAction(
              isDefaultAction: true,
              child: Text(I18n.of(mContext).determine),
              onPressed: () async {
                Navigator.of(mContext, rootNavigator: true).pop();
                goPage(receivedNotification.payload);
              },
            ),
          ],
        ),
      );
    });
    print('点击事件----selectNotificationSubject --');
    selectNotificationSubject.stream.listen((String payload) async {
      print('这里---推送点击');
      goPage(payload);
    });

    setAlias();
  }

  static bool hasInit = false;
  void initLocalPush() async {
    // needed if you intend to initialize in the `main` function
    WidgetsFlutterBinding.ensureInitialized();
    // NOTE: if you want to find out if the app was launched via notification then you could use the following call and then do something like
    // change the default route of the app
    // var notificationAppLaunchDetails =
    //     await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();

    var initializationSettingsAndroid =
        AndroidInitializationSettings('ic_launcher_1');

    ///android推送图标在drawable文件夹
    var initializationSettingsIOS = IOSInitializationSettings(
        onDidReceiveLocalNotification:
            (int id, String title, String body, String payload) async {
      print('onDidReceiveLocalNotification $payload');
      didReceiveLocalNotificationSubject.add(ReceivedNotification(
          id: id, title: title, body: body, payload: payload));
    });
    var initializationSettings = InitializationSettings(
        initializationSettingsAndroid, initializationSettingsIOS);
    print('点击事件初始化');
    bool isOK =await flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: (String payload) async {
      print('AAA这里---推送点击');
      selectNotificationSubject.add(payload);
    });
    print('点击事件初始化----$isOK');
  }

  String getPayload(Map notifition) {
    String payload = 'default';
    int type = int.parse(notifition['Type'].toString());
    print('onOpenNotification type:$type');
    switch (type) {
      case 1:
        payload = PAYLOAD_DATE + '@' + notifition['Id'].toString();
        break;
      case 2:
        payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();

        break;
      case 3:
        payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();
        break;
      case 4:
        payload = PAYLOAD_OTHER + '@' + InfoType.Money.toString();
        break;
      case 5:
        payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
        break;
      case 6:
        payload = PAYLOAD_FRIENDS + '@' + InfoType.Apply.toString();
        break;

      case 7:
        payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
        break;

      default:
        payload = 'default';
        break;
    }
    return payload;
  }

  void goPage(String payload) {
    print('goPage payload: $payload');
    print('### 开始跳转');
    if (payload != null) {
      if (payload == 'default') {
        return;
      }

      if (payload.startsWith(PAYLOAD_DATE)) {
        Navigator.of(mContext).push(
          MaterialPageRoute(
            builder: (mContext) {
              return ProgramDetailPage(
                programId: int.parse(payload.split('@')[1]),
              );
            },
          ),
        );
      } else if (payload.startsWith(PAYLOAD_FRIENDS)) {
        MessageMgr().emit('goto_new_friends');
      } else {
        int type = int.parse(payload.split('@')[1]);
        String title = '';
        switch (type) {
          case InfoType.Apply:
            title = I18n.of(mContext).application_notice;
            break;

          case InfoType.Money:
            title = I18n.of(mContext).wallet_reminder;
            break;

          case InfoType.System:
            title = I18n.of(mContext).appName;
            break;
        }

        Navigator.of(mContext).push(
          new MaterialPageRoute(
            builder: (context) {
              return InfoListPage(
                title: title,
                type: type,
              );
            },
          ),
        );
      }

      print('notification payload: ' + payload);
    }
  }

  Future<void> show(String title, String content,{int id}) async {
    if (!isBackground || !UserData().privatyMsgPushSwitch) {
//      print('程序在前台，不发生推送通知 || 用户关闭推送');
      return;
    }
    showNotification(title, content,id: id);
  }

  Future<void> showOtherNotification(
      Map notifition, String defaultTitle, String defaultContent) async {
    int type = notifition['Type'];

    String payload = 'default';
    bool needPush = true;
    switch (type) {
      case 1:
        needPush = UserData().newDateSwitch;
        payload = PAYLOAD_DATE + '@' + notifition['Id'].toString();
        break;
      case 2:
        needPush = UserData().applyCheckSwitch;
        payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();

        break;
      case 3:
        needPush = UserData().acceptCheckSwitch;
        payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();
        break;
      case 4:
        needPush = UserData().checkPhotoSwitch;
        payload = PAYLOAD_OTHER + '@' + InfoType.Money.toString();
        break;
      case 5:
        needPush = UserData().codeSucessSwitch;
        payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
        break;
      case 6:

//        needPush = UserData().codeSucessSwitch;
        payload = PAYLOAD_FRIENDS + '@' + InfoType.Apply.toString();
        break;

      case 7:
        payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
        break;
      default:
        payload = 'default';
        break;
    }
    print('showOtherNotification payload $payload');

    if(selectNotificationSubject==null){
      print('selectNotificationSubject == null');
    }else{
      print('selectNotificationSubject 不空');
    }

    if(flutterLocalNotificationsPlugin==null){
      print('flutterLocalNotificationsPlugin == null');
    }else{
      print('flutterLocalNotificationsPlugin 不空');
    }



    if (needPush) {
      showNotification(defaultTitle, defaultContent, payload: payload);
    }
  }

  void showNotification(String title, String content,
      {payload = 'default',int id}) async {
    if(id == null){
      id = Random().nextInt(1000);
    }
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        '668123', 'com.cyhd.henhoandroid.push', 'private message push',
        importance: Importance.Max, priority: Priority.High, ticker: title);
    var iOSPlatformChannelSpecifics = IOSNotificationDetails();
    var platformChannelSpecifics = NotificationDetails(
        androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
    print('payload- $payload');
    await flutterLocalNotificationsPlugin.show(
        id, title, content, platformChannelSpecifics,
        payload: payload);
    badgerCount++;
    FlutterAppBadger.updateBadgeCount(badgerCount);

      ///等极光修复了iOS本地推送点击事件后改为下面的方法
//    var fireDate = DateTime.fromMillisecondsSinceEpoch(
//        DateTime.now().millisecondsSinceEpoch + 3000);
//    var localNotification = LocalNotification(
//        id: 234,
//        title: 'fadsfa',
//        buildId: 1,
//        content: 'fdas',
//        fireTime: fireDate,
//        subtitle: 'fasf',
//        badge: 5,
//        extra: {"fa": "0"});
//    JPush jpush = new JPush();
//    jpush.sendLocalNotification(localNotification);

  }

  Future<void> cleanAllNotifications() async {
    await flutterLocalNotificationsPlugin.cancelAll();
    FlutterAppBadger.removeBadge();
    JPush jpush = new JPush();
    if (Platform.isIOS) {
      jpush.setBadge(0);
    }
    badgerCount = 0;
    FlutterAppBadger.updateBadgeCount(badgerCount);
  }


  void startPush(){
    JPush jpush = new JPush();
    jpush.resumePush();
  }

  void pausePush(){
    JPush jpush = new JPush();
    jpush.stopPush();
  }


  void dispose() {
//    if(didReceiveLocalNotificationSubject !=null && selectNotificationSubject !=null){
//      didReceiveLocalNotificationSubject.close();
//      selectNotificationSubject.close();
//    }
  }
}
