import { Injectable, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { Device } from '@capacitor/device';
import {
  ActionPerformed,
  PushNotificationSchema,
  PushNotifications,
  Token
} from '@capacitor/push-notifications';
import { api } from '@enums/api.enum';
import { GJainStorage } from '@enums/gjain-storage.enum';
import { Roots } from '@enums/root.enum';
import { NavController, Platform, ToastController } from '@ionic/angular';
import { HttpRequestService } from './http-request.service';
import { StateManagementService } from './state-management.service';

@Injectable({
  providedIn: 'root'
})

export class PushService {
  constructor(
    private platform: Platform,
    private httpRequestService: HttpRequestService,
    private navController: NavController,
    private stateManagementService: StateManagementService,
    private router: Router,
    private toastController: ToastController,
    private zone: NgZone,
  ) {

  }

  init() {
    // Request permission to use push notifications
    // iOS will prompt user and return if they granted permission or not
    // Android will just grant without prompting
    PushNotifications.requestPermissions().then(result => {
      if (result.receive === 'granted') {
        // Register with Apple / Google to receive push via APNS/FCM
        PushNotifications.register();
      } else {
        // Show some error
      }
    });

    // On success, we should be able to receive notifications
    PushNotifications.addListener('registration',
      async (token: Token) => {
        const deviceUUID = (await Device.getId()).identifier;
        this.stateManagementService.storage.set(GJainStorage.pushToken, token.value);
        this.stateManagementService.storage.set(GJainStorage.deviceUUID, deviceUUID);
        this.registerPushToken();
      }
    );


    // Show us the notification payload if the app is open on our device
    PushNotifications.addListener('pushNotificationReceived',
      (notification: PushNotificationSchema) => {
        this.displayToast(notification.data);
      }
    );

    // Method called when tapping on a notification
    PushNotifications.addListener('pushNotificationActionPerformed',
      (notification: ActionPerformed) => {
        this.redirectUserTo(notification.notification.data);
      }
    );
  }

  async displayToast(data: any) {
    if (data.type === 'NewMessage') {
      const payload = {
        id: +data.id,
        user_id: +data.user_id,
        avatar: data.avatar,
        avatar_url: data.avatar_url,
        name: data.name,
        created_at: data.created_at,
        message: data.message,
        unread_count: this.router.url.match(/\/message-chat/g) === null ? +data.unread_count : 0
      };
      this.stateManagementService.generalData.unread_message_count = payload.unread_count;
      this.stateManagementService.messageObservable.next(payload);
      this.stateManagementService.messageDetailObservable.next(payload);
      if (this.router.url.match(/\/message-chat/g) === null && this.router.url.match(/\/message/g) === null) {
        this.toast(data);
      }
    } else {
      this.stateManagementService.generalData.unread_notification_count++;
    }
    if (data.type === 'SanghAddedMember') {
      this.stateManagementService.generalData.sangh_menu = 1;
      this.stateManagementService.generalData.pending_sangh_invitation = 1;
    } else if (data.type === 'FriendRequest') {
      this.stateManagementService.generalData.shravak_menu = 1;
      this.stateManagementService.generalData.pending_friend_request = 1;
    } else if (data.type === 'SantSendBack') {
      this.stateManagementService.generalData.sant_menu = 1;
      this.stateManagementService.generalData.pending_sant_action = 1;
    }
    this.stateManagementService.pushNotyObservable.next(this.stateManagementService.generalData);
  }

  async toast(data: any) {
    const payload: any = {
      message: data.message,
      position: 'top',
      duration: 2000,
      cssClass: 'message-toast',
      buttons: [{
        side: 'end',
        text: 'View',
        handler: () => {
          if (data.type === 'NewMessage') {
            if (this.router.url.match(/\/message-chat/g) !== null) {
              const payload1 = {
                id: +data.id,
                user_id: +data.user_id,
                avatar: data.avatar,
                avatar_url: data.avatar_url,
                name: data.name,
                created_at: data.created_at,
                message: data.message,
                unread_count: this.router.url.match(/\/message-chat/g) === null ? +data.unread_count : 0
              };
              this.stateManagementService.messageObservable.next(payload1);
              this.stateManagementService.messageDetailObservable.next(payload1);
            } else {
              this.navController
                .navigateForward(Roots.page + '/' +
                  'message-chat;userId=' + data.user_id +
                  ';name=' + encodeURIComponent(data.name)
                );
            }
          }
        }
      }]
    };
    if (data.type === 'NewMessage') {
      payload.mode = 'md';
      payload.header = data.name + ' messaged you.';
    }
    const toast = await this.toastController.create(payload);
    toast.present();
  }

  redirectUserTo(data: any) {
    setTimeout(() => {
      this.zone.run(() => {
        const sanghNotification = [
          'SanghAddedMember',
          'SanghAddedCoreCommitteeMember',
          'UserSentMemberRequest',
          'UserAcceptedMemberRequest',
          'AdminAcceptedMemberRequest',
          'AdminRemovedMember',
          'AdminDeclinedMemberRequest',
          'SanghUpdatedMember'
        ];
        if (data.type === 'NewMessage') {
          this.navController.navigateRoot(Roots.page + '/' + Roots.message);
        } else if (data.type === 'FriendRequest') {
          const navOption = {
            state: {
              friendRequestSegment: 'received'
            },
          };
          this.navController.navigateRoot(Roots.page + '/' + Roots.friendRequest, navOption);
        } else if (data.type === 'FriendRequestAccepted') {
          const navOption = {
            state: {
              friendRequestSegment: 'friend'
            },
          };
          this.navController.navigateRoot(Roots.page + '/' + Roots.friendRequest, navOption);
        } else if (
          ['CommentPost', 'LikePost', 'TagPost', 'NewSanghPost', 'NewFriendPost'].includes(data.type)
        ) {
          const navOption = {
            state: {
              postId: data.from_id,
              type: data.user_type === 'shravak' ? '1' : '3'
            },
          };
          this.navController.navigateRoot(Roots.page + '/' + Roots.postDetail, navOption);
        } else if (data.type === 'SantApproved' || data.type === 'SantSendBack') {
          this.navController.navigateRoot(Roots.page + '/sant-profile/' + data.from_id);
        } else if (sanghNotification.includes(data.type)) {
          this.navController.navigateRoot(Roots.page + '/sangh-profile/' + data.from_id);
        } else {
          this.navController.navigateRoot(Roots.page + '/' + Roots.notification);
        }
      });
    }, 500);
  }

  async registerPushToken() {
    let platformName: string;
    const pushToken = await this.stateManagementService.storage.get(GJainStorage.pushToken);
    const deviceUUID = await this.stateManagementService.storage.get(GJainStorage.deviceUUID);
    if (!this.stateManagementService.token || !pushToken) {
      return;
    } else if (this.platform.is('android')) {
      platformName = 'android';
    } else if (this.platform.is('ios') || this.platform.is('iphone')) {
      platformName = 'ios';
    } else {
      return;
    }
    this.httpRequestService
      .post(api.registerPushToken, {
        os: platformName,
        device_id: deviceUUID,
        fcm_token: pushToken
      });
  }

  async unRegisterPushToken() {
    let platformName: string;
    if (this.platform.is('android')) {
      platformName = 'android';
    } else if (this.platform.is('ios') || this.platform.is('iphone')) {
      platformName = 'ios';
    } else {
      return;
    }
    const deviceUUID = await this.stateManagementService.storage.get(GJainStorage.deviceUUID);
    this.httpRequestService
      .post(api.unRegisterPushToken, {
        os: platformName,
        device_id: deviceUUID,
      }).then(() => {
        this.stateManagementService.token = '';
      });
  }

  async deleteExistingToken() {
    let platformName: string;
    if (this.platform.is('android')) {
      platformName = 'android';
    } else if (this.platform.is('ios') || this.platform.is('iphone')) {
      platformName = 'ios';
    } else {
      return;
    }
    const deviceUUID = await this.stateManagementService.storage.get(GJainStorage.deviceUUID);
    this.httpRequestService
      .post(api.deleteExistingToken, {
        os: platformName,
        device_id: deviceUUID,
      }).then(() => {
        this.stateManagementService.token = '';
      });
  }
}
