//判断是否为Object
var isObject = function(options) {
  return toString.call(options) === '[object Object]';
};
//环境变量及简单方法
var ua = window.navigator.userAgent.toLowerCase();
console.log(ua, 'ua***********') //mozilla/5.0 (iphone; cpu iphone os 13_2_3 like mac os x) applewebkit/605.1.15 (khtml, like gecko) version/13.0.3 mobile/15e148 safari/604.1
var uaArr = ua.split(';');
console.log(uaArr, 'uaArr*********')
var isWKWebview = /supportJDSHWK\/1/i.test(ua); //iosapp,webview内核是否为wk
var isJd = ua.indexOf('jdapp') != -1;
var isIphone = uaArr[1] === 'iphone' || uaArr[1].indexOf('iphone') != -1;
var isAndroid = uaArr[1] === 'android';
// var isIphone1 = uaArr[1].indexOf('iphone') != -1;

var jdApp = ua.indexOf('jdapp') != -1;
var uaArr = ua.split(';');
var jdAppVersion = (function() {
  if (jdApp) {
    return uaArr[2] ? uaArr[2].replace(/\./g, '') : '';
  } else {
    return '';
  }
})();

//6.1版本分割线
var isUsingNewInterface = (function() {
  return jdApp && jdAppVersion >= 610;
})();

//判断参数是否为undefined
var isUndefined = function(param) {
  return typeof param === 'undefined';
};

//判断是否为字符串
var isString = function(param) {
  return typeof param === 'string';
}

//判断是否为函数
var isFunction = function(func) {
  return func && (typeof func === 'function');
};
/**
 * 添加提醒
 * @param {[type]} options [description]
 */
const jdReminder = (options) => {

  return new Promise(function(resolve, reject) {
    //添加提醒时，动态生成全局回调函数
    //为保证回调函数唯一性，可以使用options中的id参数来生成

    var addCallback = function(ret, callBackId) {
      console.log('addCallback11111111111111')
      var data = parseCallbackData(ret, callBackId);
      //释放内存
      window[addReminderCallBackName] = null;
      console.log(data,'addCallback************')
      resolve(data);
    }

    //定义函数名称
    var addReminderCallBackName = 'addJdReminderCallback' + options.id;

    //注册全局回调
    window[addReminderCallBackName] = addCallback;

    // //将函数名挂载至options对象中
    options.addCallback = addReminderCallBackName;
    console.log('(((((((9)))))))')
    //低版本下，IOS返回字符串Schema，android返回undefined
    //高版本下，IOS,Android均通过添加相应的回调来监听操作结果
    var ret = createJdReminderSchema('add', options);

    if (isString(ret)) {
      resolve({
        appointed: true,
        id: options.id
      });
    }

  });

}
/**
 * 生成最终的日历schema
 * 分两种环境ios和android
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createJdReminderSchema = (action, options) => {
  if (!isObject(options)) {
    throw new JdReminderException('入口参数必须为Object对象类型');
    return '入口参数必须为Object对象类型';
  }
  console.log(isIphone, 'isIphone')
  console.log(isAndroid, 'isAndroid')
  if (isIphone) {
    return createJdReminderIOSSchema(action, options)
  } else if (isAndroid) {
    return createJdReminderAndroidSchema(action, options)
  };
}
/**
 * 生成IOS日历schema
 * 三种情况:
 * (1)是否为WK内核
 * (2)>=6.1版本
 * (3)<6.1版本
 * 优先考虑是否支持WK
 * @param  {[type]} action  [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createJdReminderIOSSchema = (action, options) => {
  console.log(isWKWebview, 'isWKWebview**********')
  if (isWKWebview) {
    console.log(createIOSSchemaForWKWebview(action, options),'3333333333')
    return createIOSSchemaForWKWebview(action, options);
  }
  if (!isUsingNewInterface) {
    console.log('2222222222')
    return createIOSSchemaForLowVersion(action, options);
  } else {
    console.log('111111111111')
    return createAllSameSchemaUsingJsBridge(action, options)
  };
  // ios和android在6.1版本上，均对齐，函数名称和传入的参数类型均一致
  // 因此不需要做平台检测

}
/**
 * 京东客户端6.2版本开始IOS渲染内核改为WK，js和原生的交互方式发生变化，需要单独处理
 * @param  {[type]} action  [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createIOSSchemaForWKWebview = (action, options) => {
  let options1 = filterParamOptions(options);
  console.log(options1,'444444444***********8')
  //wk方式调用
  executeIOSSchemaInWKWebviewCircumstance({
    method: ((action == 'add') ? 'addReminder' : 'removeReminder'),
    params: createReminderOptionsJsonString(action, options1)
  });

}
/**
 * WK环境下，执行提醒相关协议
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const executeIOSSchemaInWKWebviewCircumstance = (options) => {
  console.log('55555555555')
  var WKJsonString = extendObject({
    callBackName: null,
    callBackId: null
  }, options);
  console.log(WKJsonString,'WKJsonString')

  try {
    console.log( window.webkit.messageHandlers.JDAppUnite.postMessage(WKJsonString),' window.webkit.messageHandlers.JDAppUnite')

    window.webkit.messageHandlers.JDAppUnite.postMessage(WKJsonString);

  } catch (e) {
    // throw new JdReminderException('window.webkit.messageHandlers.JDAppUnite.postMessage方法执行错误');
    console.log('window.webkit.messageHandlers.JDAppUnite.postMessage方法执行错误')
    return 'window.webkit.messageHandlers.JDAppUnite.postMessage方法执行错误'
  }
}
/**
 * 生成Android日历schema
 * @param  {[type]} action  [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createJdReminderAndroidSchema = (action, options) => {
  console.log(action, options)
  console.log(isUsingNewInterface, 'isUsingNewInterface')
  if (!isUsingNewInterface) {
    return createAndroidSchemaForLowVersion(action, options);
  } else {
    return createAllSameSchemaUsingJsBridge(action, options);
  }
  // ios和android在6.1版本上，均对齐，函数名称和传入的参数类型均一致
  // 因此不需要做平台检测

}

/**
 * 安卓 6.10版本以下
 * @param  {[type]} argument [description]
 * @return {[type]}          [description]
 */
const createAndroidSchemaForLowVersion = (action, options) => {
  console.log(action, options)
  options = filterParamOptions(options);
  options.type = 'HUODONG';
  if (window.JdAndroid) {
    if (action == 'add') {
      if (isFunction(window.JdAndroid.setJDReminder)) {
        window.JdAndroid.setJDReminder(options.type, options.id, options.title, options.time, options.url);
      } else {
        throw new JdReminderException('android->setJDReminder不是一个函数，注意该函数应该只在APP内才会有');
        return 'android->setJDReminder不是一个函数，注意该函数应该只在APP内才会有'
      }
    } else if (action == 'del') {

      if (isFunction(window.JdAndroid.cancelJDReminder)) {
        window.JdAndroid.cancelJDReminder(options.type, options.id, options.time);
      } else {
        throw new JdReminderException('android->cancelJDReminder不是一个函数，注意该函数应该只在APP内才会有');
        return 'android->cancelJDReminder不是一个函数，注意该函数应该只在APP内才会有'
      }
    }
  } else {
    throw new JdReminderException('android->window.JDAndroid对象不存在，注意该对象应该只在APP内才会有');
    return 'android->window.JDAndroid对象不存在，注意该对象应该只在APP内才会有'
  }

}
/**
 * ios 6.10版本以下，使用协议形式
 * @param  {[type]} action  [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createIOSSchemaForLowVersion = (action, options) => {
  options = filterParamOptions(options);
  options.type = 6;
  return 'openApp.jdMobile://virtual?params={' +
    '"category":"jump",' +
    '"des":"saveToCalender",' +
    '"sourceValue":"sourceValue_saveToCalender",' +
    '"sourceType":"sourceType_saveToCalender",' +
    '"SourceParam":"sourceParam",' +
    '"actionType":"' + action + '",' +
    '"dataType":"' + options.type + '",' +
    '"calendarTitle":"' + options.title + '",' +
    '"beginTime":"' + options.time + '",' +
    '"dataId":"' + options.id + '",' +
    '"jumpUrl":"' + encodeURIComponent(options.url) + '"}';
}
/**
 * ios和android在6.1版本上，均对齐，函数签名均一致
 * 因此不需要做平台检测
 * @param  {[type]} action  [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createAllSameSchemaUsingJsBridge = (action, options) => {
  console.log(action, 'action')
  console.log(options, 'options')

  options = filterParamOptions(options);
  var jsonStringParams = createReminderOptionsJsonString(action, options);
  console.log(jsonStringParams,'jsonStringParams添加提醒')

  if (window.JDAppUnite) {
    if (action == 'add') {
      if (isFunction(window.JDAppUnite.addReminder)) {
        console.log('添加提醒')
        window.JDAppUnite.addReminder(jsonStringParams);
      } else {
        throw new JdReminderException('addReminder不是一个函数，注意该函数应该只在APP内才会有')
        return 'addReminder不是一个函数，注意该函数应该只在APP内才会有'
      };
    } else if (action == 'del') {
      if (isFunction(window.JDAppUnite.removeReminder)) {
        window.JDAppUnite.removeReminder(jsonStringParams);
      } else {
        throw new JdReminderException('removeReminder不是一个函数，注意该函数应该只在APP内才会有');
      }
    }
  } else {
    throw new JdReminderException('window.JDAppUnite对象不存在，注意该函数应该只在APP内才会有');
    return 'window.JDAppUnite对象不存在，注意该函数应该只在APP内才会有'
  }
}
/**
 * 生成addReminder,removeReminder参数
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const createReminderOptionsJsonString = (action, options) => {
  console.log(action, options)
  console.log('createReminderOptionsJsonString')
  if (action == 'add') {
    return JSON.stringify({
      businessType: options.type,
      showTag: options.tag || '',
      remindTitle: options.title || '',
      beginTime: options.time,
      uniqueId: options.id,
      jumpStr: options.url || '',
      imgUrl: options.imgUrl || '',
      notifyTime: options.nTime || (options.time - 180000),
      extraStr1: options.extra1 || '',
      extraStr2: options.extra2 || '',
      callBackName: options.addCallback,
      callBackId: options.id,
    });
  }
  if (action == 'del') {
    return JSON.stringify({
      businessType: options.type,
      beginTime: options.time,
      uniqueId: options.id,
      callBackName: options.deleteCallback,
      callBackId: options.id
    });
  }
}

/**
 * 过滤入口参数，如果没有传入相应字段属性，默认设置为空值
 * 另外抹平ios和android间的参数差异
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
const filterParamOptions = (options) => {
  if (!isObject(options)) {
    throw new JdReminderException('入参必须为Object对象类型');
    return;
  }

  //拷贝原始数据
  //原因是ios端，add/del时使用的dataType为数字（提供的枚举值）
  //查询预约状态时使用的是字符串。
  //当添加预约后，在执行查询，最后执行删除（整个过程不退出页面）
  //这时删除时会把dataType修改成字符串值，导致删除命令失败
  //
  //因此需要隔离原始对象
  //
  var copiedOptions = {};
  extendObject(copiedOptions, options)

  //释放options数据
  options = null;

  //ios中，开始时间以秒为单位的数字字符串(旧版中)，新版中使用时间戳
  //android中，以毫秒为单位，long类型，时间戳
  //时间戳为13位
  if (isIphone && !isUsingNewInterface) copiedOptions['time'] = (copiedOptions['time'] / 1000) + '';

  //构造函数里面是否传入了type值，如果有值的话，直接使用构造函数里面的值
  //否则使用传入的type值
  if (isUndefined(this.setting)) {
    if (isUndefined(copiedOptions.type)) throw new JdReminderException('type字段缺失，请在options对象参数中指定');
  } else {
    if (isUndefined(copiedOptions.type)) {
      if (isUndefined(this.setting.type)) throw new JdReminderException('type字段缺失，请在构造函数或options对象参数中指定');
      else {
        if (isUsingNewInterface) {
          copiedOptions['type'] = this.setting.type + '';
        } else {
          copiedOptions['type'] = this.setting.type;
        }
      }
    }
  }
  //ios6.0版本下url使用的是字符串，6.1及以上版本使用的是json串
  //为抹平两种之间的差异，方便第三方调用，这里做兼容处理；第三方使用
  //方式仍为传入url字符串
  //
  transformURLToJSON(copiedOptions);

  //将传入值全部转成字符串类型
  //
  transformKeyToString(copiedOptions);

  //返回options
  return copiedOptions;
}
/**
 * 将对象中的属性值强制转换成字符串类型
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
const transformKeyToString = (obj) => {
  for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {

      //新版中全部转换成字符串
      if (isUsingNewInterface) {
        obj[prop] = obj[prop] + '';
      } else {
        //旧版中android,ios需要针对处理
        //
        //
        //ios该字段需要转换成字符串类型，
        //android不需要
        if (prop == 'id') {
          if (isIphone) obj[prop] = obj[prop] + '';
        }
      }
    }
  }
  return obj;
}
/**
 * ios6.0版本下url使用的是字符串，6.1及以上版本使用的是json串
 * 为抹平两种之间的差异，方便第三方调用，这里做兼容处理；第三方使用
 * 方式仍为传入url字符串
 * @param  {[type]} url [description]
 * @return {[type]}     [description]
 */
const transformURLToJSON = (obj) => {
  //6.1及以上版本，使用json串
  //
  if (isUsingNewInterface) obj['url'] = JSON.stringify({
    des: 'm',
    params: {
      url: obj['url']
    }
  });
}
//扩展对象
const extendObject = (target, source) => {
  if (isUndefined(target) || isUndefined(source)) {
    throw new JdReminderException('target, source参数必须提供');
  }
  if (!isObject(target) || !isObject(source)) {
    throw new JdReminderException('target, source参数必须为Object类型');
  }
  for (var prop in source) {
    if (source.hasOwnProperty(prop)) {
      //所有字段转成字符串类型
      target[prop] = source[prop];
    }
  }
  console.log(target,'target**********')
  return target;
}
/**
 * 解析日历注册回调函数返回参数
 * 旧版中：IOS返回一个参数字符串，形式为'0/1,callbackId'；Android返回两个参数，true/false,callbackId
 * 新版中：IOS，Android均返回两个参数，第一个参数为0/1，第二个参数为callbackId
 *
 * 其中：0/1,true/false表示是否已预约；callbackId为透传值
 * @param  {[type]} ret        [description]
 * @param  {[type]} callBackId [description]
 * @return {[type]}            [description]
 */
const parseCallbackData = (ret, callBackId) => {
  console.log(ret,'parseCallbackDataret')
  console.log(callBackId,'callBackId')
  var args = arguments;
  var ret, callBackId;
  console.log(isUsingNewInterface,'isUsingNewInterface########')
  if (!isUsingNewInterface) {
    //如果第二个参数为undefined
    if (isUndefined(args[1])) {
      var arg = args[0].split(',');
      ret = (arg[0] == 1)
      callBackId = arg[1];
    } else {
      ret = args[0] == 'true';
      callBackId = args[1];
    }
    return {
      appointed: ret,
      id: callBackId
    };
  } else {
    console.log('a+++++++++++')
    //强行转换为字符串类型
    //以区分'','0','1'
    ret += '';

    //结果标识为预约状态
    console.log(ret,'aaaaaaaaaa')
    if (ret == '1' || ret == '0') {
      return {
        appointed: ret == '1',
        id: callBackId
      };
    }

    //批量查询，第一参数返回数组
    //当没有查到时，IOS返回的是空数组，Android返回的是空字符串
    //android
    if (isEmptyString(ret)) return {
      status: [],
      id: callBackId
    };

    //try...catch保护
    try {
      var allStatus = JSON.parse(ret);
    } catch (e) {
      return {
        status: [],
        id: callBackId
      };
    }

    //ios
    if (isArray(allStatus)) {
      return {
        status: allStatus,
        id: callBackId
      }
    }
  }
}

export {
  jdReminder
}
