import CallCenter from './CallCenter';
import EventEmitter from './EventEmitter';
import EventEmitter3 from 'eventemitter3';
import {after} from 'lodash';

export default class CallCenterWapper extends EventEmitter3 {
  apiKey = '';
  subscriptionSupporterVia = '';
  subscriptionStatusState = '';
  subscriptionChatObserver = '';
  subscriptionStateSDK = '';
  subscriptionFailedError = '';
  subscriptionEndSupporting = '';

  constructor(apiKey) {
    super();
    this.apiKey = apiKey;
  }

  init() {
    if (Platform.OS === 'android') {
      return CallCenter.initSDK(this.apiKey)
        .then(() => {
          let p = new Promise((resolve, reject) => {
            let onEvent = event => {
              EventEmitter.removeListener('initSDK', onEvent);
              let msg = JSON.parse(event.eventProperty);
              if (msg.success) {
                resolve();
              } else {
                reject();
              }
            };

            onEvent = after(2, onEvent);
            EventEmitter.addListener('initSDK', onEvent);
          });

          return p;
        })
        .then(() => {
          this.registerErrorCallBack();
          this.registerState();
          this.registerVoiceVideoCallCallback();
          this.registerChatObserver();
        });
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerStateSDK(resolve, reject);
        CallCenter.initSDK(this.apiKey);
      }).then(() => {
        // this.addListenerSupporterVia();
        this.addListenerChatObserver();
      });
    }
  }

  stop() {
    if (Platform.OS === 'android') {
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerStateSDK(resolve, reject);
        CallCenter.stopSDK();
      }).then(() => {
        // this.subscriptionSupporterVia.remove();
        this.subscriptionChatObserver.remove();
      });
    }
  }

  registerErrorCallBack() {
    return CallCenter.registerErrorCallBack().then(res => {
      return res;
    });
  }

  registerState() {
    CallCenter.registerState().then(() => {
      this.addListenerStatusState();
    });
  }

  registerVoiceVideoCallCallback() {
    return CallCenter.registerVoiceVideoCallCallback().then(res => {
      return res;
    });
  }

  registerChatObserver() {
    CallCenter.registerChatObserver()
      .then(() => {
        this.addListenerChatObserver();
      })
      .catch(err => {});
  }

  formatEvent(event) {
    let message = event.eventProperty;

    if (Platform.OS === 'android') {
      message = JSON.parse(message);
    } else if (Platform.OS === 'ios') {
      message = message;
    }

    return message;
  }

  addListenerSupporterVia({resolve = () => {}, reject = () => {}}) {
    this.subscriptionSupporterVia = EventEmitter.addListener(
      'registerSupporterVia',
      event => {
        this.subscriptionSupporterVia.remove();
        this.subscriptionFailedError.remove();
        let msg = this.formatEvent(event);
        resolve(msg);
      },
    );
  }

  addListenerStatusState() {
    this.subscriptionStatusState = EventEmitter.addListener(
      'registerStatusState',
      event => {
        let msg = this.formatEvent(event);
        this.emit('state', msg);
      },
    );
  }

  addListenerChatObserver() {
    this.subscriptionChatObserver = EventEmitter.addListener(
      'registerChatObserver',
      event => {
        let msg = this.formatEvent(event);
        let newMsg = {};

        if (Platform.OS === 'android') {
          newMsg = {
            content: msg.content,
            msgId: msg.id,
            from: msg.to,
          };
        } else if (Platform.OS === 'ios') {
          if (msg.status) {
            // msg status
            newMsg = {
              status: msg.status,
              msgId: msg.messageId,
              from: msg.identifier,
            };
          } else {
            // msg text or msg image
            newMsg = {
              isImage: msg.url ? true : false,
              content: msg.text || msg.url,
              msgId: msg.messageId,
              convId: msg.conversationId,
              from: msg.identifier,
              date: msg.date * 1000, // timestamp
            };
          }
        }

        this.emit('message', newMsg);
      },
    );
  }

  addListenerStateSDK(resolve, reject) {
    this.subscriptionStateSDK = EventEmitter.addListener(
      'registerStateSDK',
      event => {
        this.subscriptionStateSDK.remove();
        let msg = this.formatEvent(event);
        resolve(msg);
      },
    );
  }

  addListenerFailedError(resolve, reject, errorCode = []) {
    this.subscriptionFailedError = EventEmitter.addListener(
      'registerFailedError',
      event => {
        this.subscriptionFailedError.remove();
        let msg = this.formatEvent(event);
        let msgCode = parseInt(msg.code);
        if (!errorCode.length || errorCode.includes(msgCode)) {
          reject(msg);
        }
      },
    );
  }

  addListenerEndSupporting(resolve, reject) {
    this.subscriptionEndSupporting = EventEmitter.addListener(
      'registerEndSupporting',
      event => {
        this.subscriptionEndSupporting.remove();
        let msg = this.formatEvent(event);
        resolve(msg);
      },
    );
  }

  requestVoiceCall({displayName, groupName}) {
    if (Platform.OS === 'android') {
      return CallCenter.requestVoiceCallWithDisplayName({
        optionalName: displayName,
        groupName: groupName,
      }).then(res => {
        return res;
      });
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerFailedError(resolve, reject, [10, 11, 26, 100, 326]);
        this.addListenerSupporterVia({resolve, reject});
        CallCenter.requestVoiceCallWithDisplayName({
          optionalName: displayName,
          groupName: groupName,
        });
      });
    }
  }

  endVoiceCall() {
    return new Promise((resolve, reject) => {
      this.addListenerEndSupporting(resolve, reject);
      CallCenter.endVoiceCallWithDisplayName();
    });
  }

  requestChat({displayName, groupName}) {
    if (Platform.OS === 'android') {
      return CallCenter.requestChatWithDisplayName({
        optionalName: displayName,
        groupName: groupName,
      }).then(res => {
        return res;
      });
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerFailedError(resolve, reject, [10, 11, 26, 100, 326]);
        this.addListenerSupporterVia({resolve, reject});
        CallCenter.requestChatWithDisplayName({
          optionalName: displayName,
          groupName: groupName,
        });
      });
    }
  }

  sendText({messContent, to}) {
    if (Platform.OS === 'android') {
      return CallCenter.sendText({messContent: messContent, msgIdTo: to}).then(
        res => {
          return res;
        },
      );
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerFailedError(resolve, reject, [10, 11, 23, 202, 203]);
        CallCenter.sendText({messContent: messContent, msgIdTo: to}).then(
          res => {
            this.subscriptionFailedError.remove();
            resolve(res);
          },
        );
      });
    }
  }

  sendImage({source, to}) {
    if (Platform.OS === 'android') {
      return CallCenter.sendImage({source: source, msgIdTo: to}).then(res => {
        return res;
      });
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerFailedError(resolve, reject, [10, 11, 23, 202, 203]);
        CallCenter.sendImage({source: source, msgIdTo: to}).then(res => {
          this.subscriptionFailedError.remove();
          resolve(res);
        });
      });
    }
  }

  sendSeen({msgId, to}) {
    if (Platform.OS === 'android') {
      return CallCenter.sendSeen({
        msgId: msgId,
        msgIdTo: to,
      }).then(res => {
        return res;
      });
    } else if (Platform.OS === 'ios') {
      return new Promise((resolve, reject) => {
        this.addListenerFailedError(resolve, reject, [10, 11, 204]);
        CallCenter.sendSeen({
          msgId: msgId,
          msgIdTo: to,
        }).then(() => {
          this.subscriptionFailedError.remove();
          resolve();
        });
      });
    }
  }
}
