import {NativeModules, PermissionsAndroid} from 'react-native';
import _ from 'lodash';

let CallCenter = NativeModules.CallCenter;

async function initSDK(apiKey) {
  let granted =
    Platform.OS === 'android'
      ? await requestPermission(PermissionsAndroid.PERMISSIONS.CALL_PHONE)
      : true;

  if (granted) {
    return new Promise((resolve, reject) => {
      CallCenter.initSDK(
        apiKey,
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

function stopSDK() {
  return new Promise((resolve, reject) => {
    CallCenter.stopSDK(
      err => {
        reject(err);
      },
      msg => {
        resolve(msg);
      },
    );
  });
}

async function requestPermission(permission) {
  try {
    const granted = await PermissionsAndroid.request(permission);

    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log('allowed permission');
      return true;
    } else {
      console.log('denied permission');
      return false;
    }
  } catch (err) {
    console.warn(err);
    return false;
  }
}

async function requestPermissions() {
  let permissions = [
    PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
    PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
    PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
  ];

  let record_audio = await requestPermission(permissions[0]);
  let write_external_storage = await requestPermission(permissions[1]);
  let read_external_storage = await requestPermission(permissions[2]);
  let listResult = [
    record_audio,
    write_external_storage,
    read_external_storage,
  ];

  return _.compact(listResult).length == listResult.length;
}

async function requestVoiceCallWithDisplayName({optionalName, groupName}) {
  let granted = Platform.OS === 'android' ? await requestPermissions() : true;

  if (granted) {
    return new Promise((resolve, reject) => {
      CallCenter.requestVoiceCallWithDisplayName(
        optionalName,
        groupName,
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

function endVoiceCallWithDisplayName() {
  return new Promise((resolve, reject) => {
    CallCenter.endSupporting(
      err => {
        reject(err);
      },
      msg => {
        resolve(msg);
      },
    );
  });
}

function registerErrorCallBack() {
  if (Platform.OS === 'android') {
    return new Promise((resolve, reject) => {
      CallCenter.registerErrorCallBack(
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

function registerState() {
  if (Platform.OS === 'android') {
    return new Promise((resolve, reject) => {
      CallCenter.registerState(
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

function registerVoiceVideoCallCallback() {
  if (Platform.OS === 'android') {
    return new Promise((resolve, reject) => {
      CallCenter.registerVoiceVideoCallCallback(
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

async function requestChatWithDisplayName({optionalName, groupName}) {
  let granted = Platform.OS === 'android' ? await requestPermissions() : true;

  if (granted) {
    return new Promise((resolve, reject) => {
      CallCenter.requestChatWithDisplayName(
        optionalName,
        groupName,
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

function registerChatObserver() {
  if (Platform.OS === 'android') {
    return new Promise((resolve, reject) => {
      CallCenter.registerChatObserver(
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

function sendText({messContent, msgIdTo = ''}) {
  return new Promise((resolve, reject) => {
    CallCenter.sendText(
      messContent,
      msgIdTo,
      err => {
        reject(err);
      },
      msg => {
        resolve(msg);
      },
    );
  });
}

function sendImage({source, msgIdTo = ''}) {
  return new Promise((resolve, reject) => {
    CallCenter.sendImage(
      source,
      msgIdTo,
      err => {
        reject(err);
      },
      msg => {
        resolve(msg);
      },
    );
  });
}

function sendSeen({msgId, msgIdTo, msgIdFrom = '', seen = 'seen'}) {
  if (Platform.OS === 'android') {
    return new Promise((resolve, reject) => {
      CallCenter.sendSeen(
        msgId,
        msgIdTo,
        msgIdFrom,
        seen,
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  } else if (Platform.OS === 'ios') {
    return new Promise((resolve, reject) => {
      CallCenter.sendSeen(
        msgId,
        msgIdTo,
        err => {
          reject(err);
        },
        msg => {
          resolve(msg);
        },
      );
    });
  }
}

export default {
  initSDK,
  stopSDK,
  requestVoiceCallWithDisplayName,
  endVoiceCallWithDisplayName,
  registerErrorCallBack,
  registerState,
  registerVoiceVideoCallCallback,
  requestChatWithDisplayName,
  registerChatObserver,
  sendText,
  sendImage,
  sendSeen,
};
