import { tools } from "./tools";
import message from 'antd/lib/message';
import { Shell } from '.';

// 事件中转站
export const eventStation = {
  // 发布事件
  publish: <T = any>(eventName: string, detail: T = null as any, target: HTMLElement | Window = window): boolean => {
    let event = null;
    if (typeof eventName !== 'string' || !eventName) {
      return false;
    }
    if ('CustomEvent' in window) {
      event = new CustomEvent(eventName, { detail: detail, bubbles: true });
    } else {
      event = document.createEvent('CustomEvent');
      event.initCustomEvent(eventName, true, false, { detail: detail });
    }
    return target.dispatchEvent(event);
  },
  // 订阅事件
  subscription: <T>(
    eventName: string,
    handler: (detail: T) => void,
    target: HTMLElement | Window = window
  ): Function => {
    let eventHandler: any;
    target.addEventListener(eventName, eventHandler = (e: CustomEvent) => {
      handler(e.detail);
    });

    return () => {
      // 解绑方法
      target.removeEventListener(eventName, eventHandler);
      eventHandler = null;
    };
  }
};

export class RuleTypes {

  static readonly DT_NUMBER = '10'; //数值

  static readonly DT_MONEY = '11'; // ￥#,### 货币代码 + 数值格式

  static readonly DT_DATETIME = '12'; // YYYY-MM-DD HH24:MI:SS 日期

  static readonly DT_TIME = '13';  // HH24:MI:SS 时间

  static readonly DT_PERCENT = '14'; // 百分比

  static readonly DT_FRACTION = '15'; // 分数

  static readonly DT_TEXT = '16'; //  普通文本

  static readonly DT_BOOL = '17'; // 布尔

  static readonly DT_TEXT_AREA = '18'; // 多行文本

  static readonly DT_IMAGE = '20'; // 图片

  static readonly DT_SIGN_IMAGE = '26'; // 签名图片

  static readonly DT_UNI_IMAGE = '27'; // 新单图

  static readonly DT_UNI_MUL_IMAGE = '28'; // 新多图

  static readonly DT_HTML = '30'; // 超文本

  static readonly DT_MULTI_TEXT = '31'; // 显示时保留空格与换行的文本

  static readonly DT_MULTI_URL = '32'; // 多URL链接

  static readonly DT_HTML2 = '36'; // 超文本

  static readonly DT_EXTERNAL_URL = '37'; // 外部Url

  static readonly DT_BLOB_FILE = '40'; // BLOB附件

  static readonly DT_CLOB_FILE = '41'; // CLOB附件

  static readonly DT_FILE = '43'; // 文件

  static readonly DT_UNI_FILE = '47'; // 新单附件

  static readonly DT_UNI_MUL_FILE = '48'; // 新多附件

  static readonly DT_MEDIA_MIX = '50'; // 图片附件混合类型

  static readonly DT_MEDIA_IMAGE = '51'; // 纯图片

  static readonly DT_WIFI_SYMBOL = '60'; // WiFi符号，显示RFID距离

  static readonly DT_POINT = '77'; // 自定义图坐标线

  static readonly DT_OTHER_SYMBOL = '90'; // 其他，特殊符号

  static readonly STORAGE_UI = 'storage_ui';//存储在storage中的ui数据

  static readonly STORAGE_FIELD = 'storage_field';//存储在storage中的列数据

  static readonly STORAGE_DATA = 'storage_data';//存储在storage中的datamanager数据

  static readonly STORAGE_LOOKUP = 'storage_lookup';//存储在storage中的lookup数据

  static readonly CHAT_ROOM = 'chatroom';//存储在storage中的lookup数据

  static readonly CHAT_ROOM_LIST = 'chatroomList';//存储在storage中的lookup数据

  static readonly STORAGE_CACHE = "storage_cache";//是否需要缓存

  static readonly MINIMIZE = 'minimize';//弹窗最小化

  static readonly BASEINFO = 'baseInfo';//存储登录的账号、密码、是否记住密码

  static readonly USERINFO = 'userInfo';//登录成功后，后端返回的信息

  static readonly EDITEXPRESS = "EDITEXPRESS";//数据行不可编辑

  // 伪列字段(checkBox)
  static readonly pseudoField = '__pseudo_column_field_name__';
  // 伪列字段(number)
  static readonly pseudoFieldNumber = '__pseudo_column_field_name_number__';

  //刷新 scrollMb
  static readonly REFRESHSCROLL = "scrollscroll";
  //keystep驱动列内容宽度计算
  static readonly AUTOCALCWIDTH = "autoCalcWidth";
  //计算列
  static readonly COMPUTEDCOL = "computeCol";
  //关联字段点击
  static readonly LINKCLICK = "linkClick";
  //表单失去焦点
  static readonly RESETPOSITION = "resetPosition"
  //消息数量变化 刷新数据
  static readonly REFRESHDATA = "refreshData"
  // 应用帮助中心的数据存储键值
  static readonly APPLICATIONHELP = "_applicationHelp_";
  //前后端的token
  static readonly TOKEN = "accessToken";
  //是否进入过系统维护页面的key
  static readonly ISERRORPAGE = "__is_in_errorPage__"; // 是否进入过系统维护页面的key
  // 刷新菜单
  static readonly REFRESHMENU = 'refreshMenu'
  // 刷新子表
  static readonly REFRESHSUBITEM = 'refreshSubItem'
  // 本地 lookup 数据
  static readonly localLookupData = "__local_lookup_data__";
  // 刷新scrollMb
  static readonly RESETSCROLLMB = "RESETSCROLLMB";
  //不可排序
  static readonly disabledSort = ['26', '30', '36', '31', '32', '37', '50', '51'];
  //壳红外扫码
  static readonly ShellCode = 'getBarCode';
  //离线表名
  static readonly tableNamePre = "offline_table";
  // 刷新终端互联连接列表
  static readonly REFRESHCONNECT = 'refreshConnect';
  //父级节点路径
  static readonly ROUTEPARENT = "routeParent";
  //查找替换
  static readonly FINDBTN = "findBtn";
  //标签打印
  static readonly LABELBTN = "labelBtn"
  //文件打印
  static readonly FILEPRINTBTN = "filePrintBtn";
  //移动端邮件排序
  static readonly SORTBTN = "sortbtn";
  //移动端工具栏打开
  static readonly ToggleMBTOOLS = "toggleMbTools";
  //时区
  static readonly TimeZoneMode = "timezoneMode"
  //重置内容页排序和过滤器
  static readonly RESETSORTANDFILTER = "RESETSORTANDFILTER"
  //刚进入是否路由跳转至固定tab
  static readonly ISPUSHLOCKTAB = 'isPushLockTab'
  //页面触发全屏菜单事件
  static readonly PAGEFULLSCREEN = 'pageFullScreen'
  //页面触发全屏tabs事件
  static readonly FULLSCREENHEADER = 'fullScreenHeader'
  //全屏鼠标移入tabs事件
  static readonly TOGGLEHEADER = 'toggleHeader'
  //关闭聊天室的工具
  static readonly CLOSECHATTOOL = "closeChatTool";
  //关闭聊天室的工具
  static readonly SENDMSG = "contact";
  //字体
  static readonly FONTFAMILY = '"Microsoft YaHei", Arial, Helvetica, sans-serif, 宋体';
  //iframe嵌套的页面刷新事件
  static readonly FIXPAGEREFRESH = "FixedPageRefresh";
  //iframe 关闭页面
  static readonly REPACETAB = "replaceTab";
  //iframe 改变tab名称
  static readonly CHANGETABNAME = 'changeTabName';
}

export class FLRule {

  // 不允许创建实例
  protected constructor() { }
  /**
    * 打开分享的链接
    */
  static openShareLink = async () => {
    let res = await Shell.getClipboardData();
    if (res.success === true) {
      let content = res.data.content;
      if (content.includes('qr_type') && content.includes('qr_key')) {
        // 页面数据分享
        // store.dispatch(setShareTip(true))

        message.info({
          content: "是否打开一个分享的链接",
          onClose: () => {
            tools.copy(' ')
            // store.dispatch(setShareTip(false))
          },
          onClick: () => {
            tools.copy(' ')
            // FLRule.toShareView(content);
            // store.dispatch(setShareTip(false))
          }
        })
      }
    }
  }
}


/**有info过程调用，必须得传入success与fail函数，如果不是的话，可以promise调用 */

// Promise成功结果
type DoneResult<T> = {
  success: true;
} & ShellDoneResult<T>;

// Promise失败结果
type FailResult = {
  success: false;
} & ShellFailResult;

// Promise 返回结果
export type ShellResult<T> = DoneResult<T> | FailResult;

// 解析JSON数据
let getData = (response: string) => {
  try {
    return JSON.parse(response);
  } catch (e) {
    message.info({ content: 'JSON解析出错' });
    throw new Error('JSON解析出错');
  }
};

//红外扫码
window['getBarCode'] = (code: string) => {
  eventStation.publish<{ code: string; href: string }>(RuleTypes.ShellCode, { code, href: window.location.hash.slice(1) })
}
// 壳打开消息页面

window['exportSuccess' as string] = (type: any) => {
  if (type === 'fail') {
    message.info({ content: '文件未下载' });
  } else {
    message.success({ content: '文件下载成功' });
  }

}

//最小化监听，程序最小化时主动通知前端  0 最小化 1 最大化
window['changeImize'] = async (res: { imizeType: 0 | 1 }) => {
  if (typeof res === 'string') {
    res = JSON.parse(res)
  }
  eventStation.publish(RuleTypes.MINIMIZE);
  try {
    //需要登录后
    if (res.imizeType === 1 && localStorage.getItem(RuleTypes.USERINFO)) {
      FLRule.openShareLink();
    }
  } catch (error) {
    console.error('没有口令')
  }
}

// 壳打印h5回调
window['h5PrintCallBack'] = (res: string) => {
  let result: {
    index: number,
    status: number,
    itemFlag: string,
    itemCaption: string,
    msg: string,
    success: boolean
  } = getData(res)
  const { itemCaption, success, msg } = result;
  if (success) {
    message.success({ content: `${itemCaption}报表打印成功` });
  } else {
    message.error({ content: `${itemCaption}报表打印失败,${msg}` });
  }
}

// 调用壳接口
let triggerShell = (name: string, data: any, doneHandler: string, failHandler: string): boolean => {
  let params = {
    "name": name,
    "data": data ? data : {},
    "success": doneHandler,
    "fail": failHandler,
    "random": Math.random().toString()
  };

  if ((tools.os.ios || tools.isMac) && window.webkit) {
    //ios调用壳函数
    try {
      window.webkit.messageHandlers.AppShell.postMessage(JSON.stringify(params));
      return true;
    } catch (error) {
      return false;
    }
  } else if (window.AppShell) {
    //pc壳和安卓调用壳函数
    try {
      window.AppShell.postMessage(JSON.stringify(params));
      return true;
    } catch (error) {
      return false;
    }
  } else {
    //非壳环境调用接口提示
    if (name != 'getFromPasteboard') {
      message.info({ content: "请用客户端打开" });
    }
    return false;
  }
};

function shellHandler<R, T = {}, Info = R>(options: IShellSetting<T, R, Info>): boolean;
function shellHandler<R, T = {}>(options: TOmit<IShellSetting<T, R>, "success" | "fail" | "info">): Promise<ShellResult<R>>;
function shellHandler<R, T = {}, Info = R>(
  options: IShellSetting<T, R, Info> | TOmit<IShellSetting<T, R>, "success" | "fail" | "info">
) {
  let {
    name,
    data
  } = options;

  let successEvent = `${name}_${tools.randonName()}`, // 成功事件名称
    failEvent = `${name}_${tools.randonName()}`; // 失败事件名称

  // 清除全局Shell事件
  let clearEvent = () => {
    delete window[successEvent];
    delete window[failEvent];
  };
  
  if ("success" in options) {
    let {
      success,
      fail,
      info
    } = options;

    window[successEvent] = (res: string) => {
      let result: ShellDoneResult = getData(res);
      if (result.info) {
        info && info(result);
        return;
      }
      clearEvent();
      success && success(result);
    };
    window[failEvent] = (res: string) => {
      let result: ShellFailResult = getData(res);
      clearEvent();
      fail && fail(result);
    };
    return triggerShell(name, data, successEvent, failEvent);
  } else {
    return new Promise<ShellResult<R>>((resolve, reject) => {
      window[successEvent] = (res: string) => {
        let result: ShellDoneResult<R> = getData(res);
        if (!result.info) {
          clearEvent();
          resolve({ success: true, ...result });
        }
      };
      window[failEvent] = (res: string) => {
        let result: ShellFailResult = getData(res);
        clearEvent();
        resolve({ success: false, ...result });
      };
      if (!triggerShell(name, data, successEvent, failEvent)) {
        reject();
      }
    });
  }
}

export {
  shellHandler
}

