/**
 * <%= pascalCase(singularDomainName) %> Service
 */
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {fromPromise} from 'rxjs/observable/fromPromise';
import {environment} from '../../../environments/environment';
import {PushNotificationTag, <%= pascalCase(singularDomainName) %>} from './<%= paramCase(pluralDomainName) %>.domain';

@Injectable()
export class <%= pascalCase(pluralDomainName) %>Service {
readonly endpoint = environment.<%= camelCase(baseUri) %> + '/<%= paramCase(pluralDomainName) %>';

  constructor(private http: HttpClient) {
  }

  /**
   * Asynchronous Remote Service Methods
   */

  createOne(payload: <%= pascalCase(singularDomainName) %>): Observable<<%= pascalCase(singularDomainName) %>> {
    return this.http.post<<%= pascalCase(singularDomainName) %>>(this.endpoint, payload);
}

  deleteUserTags(): Observable<void> {
    return fromPromise(new Promise((resolve, reject) => {
      try {
        setTimeout(() => {
          this.oneSignal.deleteTags(['agent_id', 'push_environment']);
          resolve();
        }, 0);
      } catch (e) {
        console.error(e);
        reject(e);
      }
    }));
}

  fetchAll(): Observable<<%= pascalCase(singularDomainName) %>[]> {
    return this.http.get<<%= pascalCase(singularDomainName) %>[]>(this.endpoint);
}

  fetchOne(id: number): Observable<<%= pascalCase(singularDomainName) %>> {
    return this.http.get<<%= pascalCase(singularDomainName) %>>(`${this.endpoint}/${id.toString()}`);
}

  init(): Observable<void> {
    return fromPromise(new Promise((resolve, reject) => {
      try {
        this.oneSignal.startInit(environment.oneSignalAppId, environment.googleProjectNumber);

        if (!environment.production) {
          this.oneSignal.setLogLevel({
            logLevel: 6, // Verbose
            visualLevel: 3, // Warnings
          });
        }

        this.oneSignal.inFocusDisplaying(this.oneSignal.OSInFocusDisplayOption.Notification);

        this.oneSignal.handleNotificationReceived().subscribe((notification: OSNotification) => {
          // do something when notification is received
          console.log('OSNotification', notification);
          if (notification) {
            const { payload } = notification;
            if (payload) {
              const {
                additionalData: {
                  push_environment,
                  push_type
                },
                body,
                launchURL,
                notificationID,
                title,
              } = payload;
              switch (push_type) {
                case PushNotificationType.AuditSubmission:
                  break;
                case PushNotificationType.Location:
                  this.store.dispatch(new AddOneClientLocation({
                    launchURL,
                    title,
                    data: additionalData,
                    id: notificationID,
                    message: body,
                    pushNotificationEnvironment: push_environment,
                    pushNotificationType: PushNotificationType.Location,
                    sent: false,
                    timestamp: getISOTimestamp(),
                  }));
                  break;
                default:
                  console.log('What kind of notification is this?');
                  break;
              }
            }
          }
        });

        // this.oneSignal.handleNotificationOpened().subscribe((notification) => {
        //   // do something when a notification is opened
        //   console.log('Notification Opened', notification);
        // });

        this.oneSignal.endInit();
        resolve();
      } catch (e) {
        reject(e);
      }
    }));
}

  sendUserTags(tags: PushNotificationTag[]): Observable<void> {
    return fromPromise(new Promise((resolve, reject) => {
      try {
        const { agentId, pushEnvironment } = tags;
        this.oneSignal.getTags().then((currentTags: any) => {
          const strAgentId = agentId.toString();
          if (!!agentId) {
            this.sendSingleTag(currentTags, 'agent_id', strAgentId);
            this.sendSingleTag(currentTags, 'push_environment', pushEnvironment);
            resolve();
          } else {
            reject({ message: 'No AgentId' });
          }
        }).catch((err: any) => reject(err));
      } catch (e) {
        reject(e);
      }
    }));
}

  subscribe(): Observable<void> {
    try {
      return fromPromise(new Promise((resolve) => {
        setTimeout(() => {
          this.oneSignal.getPermissionSubscriptionState().then((state: OSPermissionSubscriptionState) => {
            if (isPropertyDefined(state, 'subscriptionStatus')) {
              const { subscribed } = state.subscriptionStatus;
              if (!subscribed) {
                this.oneSignal.setSubscription(true);
              }
              resolve();
            } else {
              this.oneSignal.setSubscription(true);
              resolve();
            }
          });
        }, 0);
      }));
} catch (e) {
    return fromPromise(Promise.reject(e));
  }
}

  unsubscribe(): Observable<void> {
    try {
      return fromPromise(new Promise((resolve) => {
        setTimeout(() => {
          this.oneSignal.setSubscription(false);
          resolve();
        }, 0);
      }));
} catch (e) {
    return fromPromise(Promise.reject(e));
  }
}

private sendSingleTag(currentTags: any, key: string, value: string): void {
    if (!!value && (!!currentTags || (!!currentTags[key] && currentTags[key] !== value))) {
    this.oneSignal.sendTag(key, value);
  }
}
}
