import * as config from "../config/env";
// import store from "@/store/index";
import urls from "../server/urls";
import html2canvas from "html2canvas";
import axios from "axios";
const tool: any = {
  timeSpace: 0, //本地和服务器的时间间隔
  version: "",
  fetchSKtime: 0, //获取sessionkey超时的重试次数
  const: {}, // 运行时的一些常量
  getUrlParam: function (name: string) {
    const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    if (location.href.indexOf("?") < 0) return "";
    let r = location.href.split("?")[1].match(reg);
    if (r != null) {
      let d = decodeURIComponent(r[2]);
      return tool.getIntValue(d);
    }
    return "";
  },
  getCookieValue: function (name: string) {
    let nameEQ = name + "=";
    let ca = document.cookie.split(";");
    for (let i = 0; i < ca.length; i++) {
      let c = ca[i];
      while (c.charAt(0) == " ") c = c.substring(1, c.length);
      if (c.indexOf(nameEQ) == 0) {
        return c.substring(nameEQ.length, c.length);
      }
    }
    return "";
  },
  getIntValue(value: string | null | undefined) {
    if (
      value === "null" ||
      value === "undefined" ||
      value === null ||
      value === undefined
    ) {
      return "";
    } else if (value === "0") {
      return 0;
    }
    return value;
  },
  createCookie(name: string, value: string | number | boolean, days: number) {
    let expires = "";
    if (days) {
      var date: any = new Date();
      date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
      expires = "; expires=" + date.toGMTString();
    }
    let cookieDomain = "";
    if (name == "user_id" || name == "xyy") {
      cookieDomain = "; domain=51yund.com";
    }
    document.cookie =
      name +
      "=" +
      encodeURIComponent(value) +
      expires +
      cookieDomain +
      "; path=/";
  },
  getYdUserKey: function (key: string) {
    let val = "";
    val = _getLocalStorage(key) || sessionStorage.getItem(key);
    val = tool.getIntValue(val);
    if (["user_id", "xyy"].indexOf(key) > -1) {
      let _key = key == "xyy" ? "sid" : key;
      let ck_val = tool.getIntValue(tool.getCookieValue(_key));
      if (ck_val && ck_val != val) {
        val = ck_val;
        localStorage.removeItem(key);
      }
    }
    if (!val) {
      val = tool.getUrlParam(key);
    }
    return val;
  },
  // 本地持久化存储
  setStorage(name: string, value: string, expires: any) {
    if (window.ydStorage) {
      window.ydStorage.setItem(name, value, expires);
    } else {
      localStorage.setItem(name, value);
    }
  },
  //获取公共数据来源
  getCommonValue: function (str: string) {
    if (!tool[str]) {
      let u: any = window.navigator.userAgent.toLocaleLowerCase();
      tool[str] = "other";
      if (str === "appSource") {
        //app来源（Android/ios/other）
        if (u.indexOf("android") > -1 || u.indexOf("adr") > -1) {
          tool[str] = "android";
        } else if (u.indexOf("iphone") != -1 || u.indexOf("ipad") != -1) {
          tool[str] = "ios";
        }
      } else if (str === "appType") {
        //app类型（wx/qq/yuedong/other）
        if (u.indexOf("yuedong") != -1) {
          tool[str] = "yuedong";
        } else if (u.indexOf("micromessenger") != -1) {
          tool[str] = "wx";
        } else if (u.indexOf("qq") != -1) {
          tool[str] = "qq";
        }
      } else if (str === "sysVersion") {
        //操作系统版本
        if (u.indexOf("android") != -1) {
          tool[str] = u.match(/android\s([0-9.]*)/)[1];
        } else if (u.indexOf("iphone") != -1 || u.indexOf("ipad") != -1) {
          tool[str] = u.match(/cpu iphone os (.*?) like mac os/)[1];
        }
      }
    }
    return tool[str];
  },
  /**
   * 检查ua中是否存在某些值
   * @param {String} source 唯一标识字段
   * @param {Long String} params 长参数
   * */
  checkUserAgent: function (source: string | number, ...params: any[]) {
    if (tool.const[source] != undefined) return tool.const[source];
    tool.const.USER_AGENT =
      tool.const.USER_AGENT || window.navigator.userAgent.toLocaleLowerCase();
    tool.const[source] = params.some((item) => {
      return tool.const.USER_AGENT.indexOf(String(item)) != -1;
    });
    return tool.const[source];
  },
  isYuedong: function () {
    return tool.checkUserAgent("isYuedong", "yuedong");
  },
  isAndroidWeb: function () {
    return tool.checkUserAgent("isAndroidWeb", "android");
  },
  isIosWeb: function () {
    return tool.checkUserAgent("isIosWeb", "iphone", "ipad");
  },
  isWeixin: function () {
    return tool.checkUserAgent("isWeixin", "micromessenger");
  },
  // 是否在悦健身
  isYdFitness: function () {
    return tool.checkUserAgent("isYdFitness", "yd_fitness");
  },
  // 微信小程序
  isWxMiniApp: function () {
    if (window.__wxjs_environment === "miniprogram") {
      return true;
    }
    return tool.checkUserAgent("isWxMiniApp", "miniProgram");
  },
  // getSessionKey: function (
  //   userId: string | number,
  //   xyy: string,
  //   cb: (arg0: boolean) => void
  // ) {
  //   var param = { user_id: userId, xyy: xyy };
  //   return window.$http
  //     .post(urls.getsskey, param, true)
  //     .then(function (res: {
  //       code: number;
  //       session_key: any;
  //       session_ttl: any;
  //     }) {
  //       if (res.code === 0) {
  //         let sessionkey = res.session_key;
  //         if (sessionkey) {
  //           tool.fetchSKtime = 0; //获取成功之后把fetchSKtime还原
  //           //存值的时候先存store，再存localStorage，存store为了取值更快，存storage为了看方便
  //           store.dispatch("saveCommonValue", {
  //             key: "session_key",
  //             value: sessionkey,
  //           });
  //           tool.setStorage("session_key", sessionkey, res.session_ttl);
  //           store.dispatch("saveCommonValue", {
  //             key: "user_id",
  //             value: userId,
  //           });
  //           localStorage.setItem("user_id", userId);
  //           store.dispatch("saveCommonValue", { key: "xyy", value: xyy });
  //           localStorage.setItem("xyy", xyy);
  //         }
  //         let hasLogin = userId == 0 ? false : true;
  //         if (cb) cb(hasLogin);
  //         return sessionkey;
  //       } else if (res.code !== 7007) {
  //         //userId和xyy不匹配或其它异常情况，最常见的场景是首次进来时，用户之前本地存储的xyy过期，7007的情况在http层统一处理
  //         tool.toLogin();
  //       }
  //     });
  // },
  //简化版js节流，默认2s内只能点击一次
  throttle: function (callback: () => void, duration = 2000) {
    let lastTime = tool.lastTime || 0;
    let now = new Date().getTime();
    if (now - lastTime > duration) {
      callback();
      tool.lastTime = now;
    }
  },
  //记录上报（访问来源上报、错误上报）
  reportCmd: function (data: any) {
    window.$http.postOnly(config.logPath + "/sport/report", data);
  },
  // 上报错误信息
  postErrLog(
    data: {
      platform?: string;
      app_source?: any;
      app_type?: any;
      local_path: string;
      local_url: string;
      package_name: string;
      app_version?: string;
      system_version?: any;
      err_msg?: string;
      req_params?: any;
      req_uri?: any;
    },
    cmdName: string
  ) {
    let hosts = location.host;
    if (
      (hosts.indexOf("localhost") > -1 || hosts.indexOf("test") > -1) &&
      !config.logFlag.dev
    ) {
      return;
    }
    let param = {
      user_id: tool.getYdUserKey("user_id") || 0,
      cmd: cmdName,
      device_id: "yuedongweb",
      data: JSON.stringify(data),
    };
    tool.reportCmd(param);
  },
  $throwJS(data: any) {
    //抛出js异常
    let obj: any = {
      //公共部分
      platform: "web",
      app_source: tool.getCommonValue("appSource"),
      app_type: tool.getCommonValue("appType"),
      local_path: location.pathname,
      local_url: location.href,
      package_name: config.logFlag.packageName,
      app_version: tool.version,
      system_version: tool.getCommonValue("sysVersion"),
    };
    Object.assign(obj, data);
    let filterJsErr = [];
    if (config.filterErr && config.filterErr.length > 0) {
      filterJsErr.push(...config.filterErr);
    }
    if (filterJsErr.indexOf(obj.err_msg) > -1) return;
    let cmd_name = "vue_jserr";
    if (obj.err_msg && obj.err_msg.indexOf("http") > -1) {
      cmd_name = "vue_reserr"; //reserr表示资源加载异常（resource error）
    }
    tool.postErrLog(obj, cmd_name);
  },
  // 抛出请求异常
  $throw(err: string, info: any, uri: any, response: any) {
    let obj: any = {
      local_url: location.href,
      local_path: location.pathname,
      err_msg: err + "",
      package_name: config.logFlag.packageName,
      req_params: info,
      req_uri: uri,
    };
    if (response) {
      //返回值结构体异常
      obj.response = response;
    }
    let filterErr = config.filterErr;
    if (filterErr && filterErr.indexOf(obj.err_msg) > -1) return;
    tool.postErrLog(obj, "vue_reqerr");
  },
  //事件上报（比如记录某个按钮点击了多少次，某个页面访问了多少次）
  eventBiz: function (data: any) {
    let param = { detail: data };
    return window.$http.post(config.logPath + "/ydlog/event", param, true);
  },
  //去登录
  toLogin: function (backUrl: any) {
    localStorage.removeItem("session_key");
    localStorage.removeItem("xyy");
    tool.createCookie("user_id", "", -1);
    tool.createCookie("xyy", "", -1);
    tool.createCookie("sid", "", -1);

    let envAgent = "";
    let userAgent: any = window.navigator.userAgent;
    userAgent = userAgent.toLocaleLowerCase();
    if (userAgent.indexOf("yuedong") != -1) {
      envAgent = "app";
    } else if (userAgent.indexOf("micromessenger") != -1) {
      envAgent = "wx";
    } else {
      envAgent = "qq";
    }
    if (envAgent === "app") {
      //判断是否悦动app
      tool.eventBiz("188:3:1").then(() => {
        //跳转客户端登录上报
        let jumpUrl = config.jumpPath + "/local_call?local_action=login";
        location.href = jumpUrl;
      });
    } else {
      //跳转授权登录
      let cbUrl = backUrl ? backUrl : location.href;
      cbUrl = encodeURIComponent(cbUrl);
      // cbUrl = _clearUlrData(cbUrl);
      if (userAgent.match(/WeiBo/i) == "weibo") {
        location.href = `${config.ssoPath}/v${
          config.appVersion || 1
        }/user/login?appid=102&cburl=${cbUrl}`;
        return;
      }
      if (config.appId) {
        //如果配置了appid就走新的sso登录，否则还是走老的
        location.href = `${config.ssoPath}/v${
          config.appVersion || 1
        }/user/login?appid=${config.appId}&cburl=${cbUrl}`;
      } else {
        location.href =
          config.ssoPath +
          "/get_tickets?cburl=" +
          cbUrl +
          "&lg_way=" +
          envAgent;
      }
    }
  },
  iframeLocalCall(url: string) {
    /**
     * ios 如果我们连续 2 个 js 调 native，连续2次改document.location的话，在app中，
     * 只能截获后面那次请求，前一次请求由于很快被替换掉，所以被忽略掉了，前一次请求返回数据丢失。
     * 故换成iframe 来实现调用
     * */
    var iFrame: any;
    iFrame = document.createElement("iframe");
    iFrame.setAttribute("src", url);
    iFrame.setAttribute("style", "display:none;");
    iFrame.setAttribute("height", "0px");
    iFrame.setAttribute("width", "0px");
    iFrame.setAttribute("frameborder", "0");
    document.body.appendChild(iFrame);
    // 发起请求后这个 iFrame 就没用了，所以把它从 dom 上移除掉
    iFrame.parentNode.removeChild(iFrame);
    iFrame = null;
  },
  // 获取浏览器定位
  // getBrowserPosition(callback: (arg0: string) => void) {
  //   if (!AMap) {
  //     callback("定位发生未知错误");
  //   }
  //   const map = new AMap.Map("container", {
  //     resizeEnable: true,
  //   });
  //   map.plugin("AMap.Geolocation", function () {
  //     const geolocation = new AMap.Geolocation({
  //       enableHighAccuracy: true, //是否使用高精度定位，默认:true
  //       timeout: 10000, //超过10秒后停止定位，默认：无穷大
  //       zoomToAccuracy: true,
  //       buttonPosition: "RB",
  //     });
  //     map.addControl(geolocation);
  //     geolocation.getCurrentPosition();
  //     AMap.event.addListener(
  //       geolocation,
  //       "complete",
  //       (data: { position: { getLng: () => any; getLat: () => any } }) => {
  //         let obj = {
  //           lng: data.position.getLng(),
  //           lat: data.position.getLat(),
  //         };
  //         callback(obj);
  //       }
  //     );
  //     AMap.event.addListener(geolocation, "error", (data: { message: any }) => {
  //       let str = "";
  //       switch (data.message) {
  //         case "Geolocation permission denied.":
  //           str = "浏览器阻止了定位操作";
  //           break;
  //         case "Get geolocation failed":
  //           str = "无法获得当前位置";
  //           break;
  //         case "Get geolocation time out":
  //           str = "定位超时，请重试";
  //           break;
  //         default:
  //           str = "定位发生未知错误，请检查您的设备";
  //           break;
  //       }
  //       callback(str);
  //     });
  //   });
  // },
  //yd支付
  ydPay: function (param: any) {
    // 使用方法：
    // let obj = {
    //     m_iUserId:'',        //非必填，若无时不传
    //     m_sWxPayAuthUrl: '', //非必填，若无时不传
    //     m_iPayId:'',
    //     m_sPaySource:'',
    //     m_iPayFee:'',
    //     m_sPayTitle:'',
    //     m_sPayCbUrl:'',
    // }
    // tool.ydPay(obj);
    let obj: any = {
      m_iPayCheeck: 0,
      m_iNoCredit: 0,
      m_CbShowYdCash: 1,
      m_CbBusiness: "",
      m_iUserId: tool.getYdUserKey("user_id"),
      m_sWxPayAuthUrl:
        "http://payapi.51yund.com/wx_pay/wxpublic/php/api/wxpay_auth.php",
    };
    if (!obj.m_iUserId) {
      tool.toLogin();
      return window.global.toast("登录失效，请重新登录再试");
    }
    Object.assign(obj, param);
    var payUrl = "https://circle.51yund.com/pay/index";
    var params =
      "?user_id=" +
      obj.m_iUserId +
      "&order_id=" +
      obj.m_iPayId +
      "&pay_source=" +
      obj.m_sPaySource +
      "&fee=" +
      obj.m_iPayFee +
      "&title=" +
      encodeURIComponent(obj.m_sPayTitle) +
      "&cb_url=" +
      encodeURIComponent(obj.m_sPayCbUrl) +
      "&pay_check=" +
      obj.m_iPayCheeck;
    params = params + "&no_credit=" + obj.m_iNoCredit;
    params = params + "&business=" + obj.m_CbBusiness;
    params = params + "&show_yd_cash=" + obj.m_CbShowYdCash;

    var isShare =
      tool.getUrlParam("is_share") || tool.getCookieValue("is_share");
    var isPlatFormLogin = tool.getUrlParam("is_platform_login");
    if (isShare || isPlatFormLogin) {
      params = params + "&is_share=true";
    }
    //添加协议
    let curProtocol = document.location.protocol;
    if (curProtocol.indexOf("https") != -1) {
      //https
      params = params + "&https=1";
    } else {
      params = params + "&https=0";
    }

    if (tool.isWeixin()) {
      var wxPayUrl = obj.m_sWxPayAuthUrl + params;
      window.location.href = wxPayUrl;
      return;
    }
    // PC扫码支付
    if (
      !navigator.userAgent.match(
        /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i
      )
    ) {
      var pcUrl = "https://circle.51yund.com/pay/pc";
      window.location.href = pcUrl + params;
      return;
    }
    window.location.href = payUrl + params;
  },
  /**
   * 上传base64图片到七牛
   * @param {String} data.base64 base64图片
   * @param {String} data.origin 七牛地址
   * @param {String} data.source 图片source
   * @param {Function} data.success 成功回调
   * @param {Function} data.fail 失败回调
   */
  uploadQiniuBase64: function (data: {
    base64: string;
    source: any;
    fail: () => void;
    success: (arg0: { orig_url: any; thumb_url: any; name: any }) => void;
    origin: any;
  }) {
    // 去base64逗号之后的内容
    if (data.base64.indexOf("base64,") !== -1) {
      data.base64 = data.base64.split("base64,")[1];
    }
    const getToken = function () {
      let param = { source: data.source };
      window.$http
        .post("/sport/qiniu_uptoken", param)
        .then((res: { code: number; up_token: any; photo_id: any }) => {
          if (res.code === 0) {
            let upToken = res.up_token;
            let photoId = res.photo_id;
            let obj = {
              name: photoId + ".jpg",
              token: upToken,
              file: data.base64,
            };
            uploadFile(obj);
          } else {
            data.fail();
          }
        });
    };

    const getPicUrl = function (obj: { name: any }) {
      let param = {
        user_id: tool.getYdUserKey("user_id"),
        filename: obj.name,
        source: data.source,
      };
      window.$http
        .post("/sport/get_qiniu_url", param)
        .then((res: { code: number; orig_url: any; thumb_url: any }) => {
          if (res.code === 0) {
            let imgdata = {
              orig_url: res.orig_url,
              thumb_url: res.thumb_url,
              name: obj.name,
            };
            data.success(imgdata);
          } else {
            data.fail();
          }
        });
    };

    const uploadFile = function (obj: any) {
      axios({
        url: `https://${data.origin}/putb64/-1`,
        data: obj.file,
        method: "POST",
        headers: {
          "Content-Type": "application/octet-stream",
          Authorization: `UpToken ${obj.token}`,
        },
      }).then((res: { data: { code: number } }) => {
        if (res.data.code === 0) {
          getPicUrl(obj);
        } else {
          data.fail();
          window.global.toast("图片上传失败，请重试");
        }
      });
    };
    getToken();
  },
  /**
   * 比较版本号大小
   * @param {String} v1 v1版本号
   * @param {String} v2 v2版本号
   * @param {object} options {lexicographical: true, zeroExtend: true};
   * lexicographical 按字典顺序而不是按顺序比较版本字符串的每个部分,这允许后缀如“ b”或“ dev”，但将导致“ 1.10”被认为小于“ 1.2”
   * zeroExtend 如果一个版本字符串的部分少于另一版本，则更改结果。 在这种情况下，较短的字符串将用“零”部分填充，而不是被认为较小
   * @returns {number} -1: (v1<v2), 0: (v1=v2), 1: (v1>v2)
   */
  versionCompare: function (
    v1: string,
    v2: string,
    options: { lexicographical: any; zeroExtend: any }
  ) {
    let lexicographical = options && options.lexicographical,
      zeroExtend = (options && options.zeroExtend) || true,
      v1parts: any = v1.split("."),
      v2parts: any = v2.split(".");

    function isValidPart(x: string) {
      return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
    }
    if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
      return -1;
    }
    if (zeroExtend) {
      while (v1parts.length < v2parts.length) v1parts.push("0");
      while (v2parts.length < v1parts.length) v2parts.push("0");
    }
    if (!lexicographical) {
      v1parts = v1parts.map(Number);
      v2parts = v2parts.map(Number);
    }
    for (let i = 0; i < v1parts.length; ++i) {
      if (v2parts.length == i) {
        return 1;
      }
      if (v1parts[i] == v2parts[i]) {
        continue;
      } else if (v1parts[i] > v2parts[i]) {
        return 1;
      } else {
        return -1;
      }
    }

    if (v1parts.length != v2parts.length) {
      return -1;
    }
    return 0;
  },
  html2base64Img(node: any) {
    function uploadBase64(base64: string) {
      return new Promise((resolve, reject) => {
        tool.uploadQiniuBase64({
          base64: base64,
          origin: "upload.qiniup.com",
          source: "topic_photo",
          success: (res: { orig_url: any }) => {
            let url = res.orig_url;
            setTimeout(() => resolve({ url, base64 }));
          },
          fail: () => {
            reject();
          },
        });
      });
    }

    function initBase64Img(el: any) {
      let node = el;
      let w = node.clientWidth;
      let h = node.clientHeight;
      let canvas = document.createElement("canvas");
      let canvasRadio = 2;
      canvas.width = w * canvasRadio;
      canvas.height = h * canvasRadio;
      canvas.style.width = w * canvasRadio + "px";
      canvas.style.height = h * canvasRadio + "px";
      let context = canvas.getContext("2d");
      let top = node.offsetTop;
      //然后将画布缩放，将图像放大2倍画到画布上
      context && context.scale(canvasRadio, canvasRadio);
      return html2canvas(node, {
        canvas: canvas,
        allowTaint: false,
        taintTest: true,
        useCORS: true,
        dpi: window.devicePixelRatio,
        width: w,
        height: h,
        top,
        background: "#fff",
        scale: 4,
      } as any).then((canvas) => {
        let context: any = canvas.getContext("2d");
        // 【重要】关闭抗锯齿
        context.mozImageSmoothingEnabled = false;
        context.webkitImageSmoothingEnabled = false;
        context.msImageSmoothingEnabled = false;
        context.imageSmoothingEnabled = false;
        // document.documentElement.style.position = '';
        let dataUrl = canvas.toDataURL("image/png");
        return Promise.resolve(dataUrl);
      });
    }

    return initBase64Img(node).then((base64) => uploadBase64(base64));
  },
};

export const injectTool = () => {
  let timeSpace = localStorage.getItem("timeSpace");
  if (timeSpace) {
    tool.timeSpace = parseInt(timeSpace);
  }
  tool.version = _getVersion();
  tool.supportWebpFlag = _webpSupportHander();
  if (typeof window.tool == "undefined") {
    window.tool = tool;
  }
};

function _getVersion() {
  //客户端首次进来会在url上带V，ios同时还会在cookie上存V（ios老版本存version）
  // 兼容Android 版本号为ver
  let version =
    tool.getUrlParam("v") ||
    tool.getCookieValue("v") ||
    tool.getUrlParam("ver");
  if (!version || version == "null") {
    version = tool.getUrlParam("version") || tool.getCookieValue("version");
    if (!version || version == "null") {
      version = "";
    }
  }
  return version;
}
// 判断是否支持webp格式
function _webpSupportHander() {
  let supportWebp = false;
  try {
    document.createElement("canvas").getContext("2d");
    supportWebp =
      document
        .createElement("canvas")
        .toDataURL("image/webp")
        .indexOf("data:image/webp") == 0;
  } catch (e) {
    let image = new Image();
    image.onload = function () {
      // 图片加载成功且宽度为1，那么就代表支持webp了，因为这张base64图是webp格式。如果不支持会触发image.error方法
      if (image.width == 1) {
        supportWebp = true;
      }
    };
    // 一张支持alpha透明度的webp的图片，使用base64编码
    image.src =
      "data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==";
  }
  return supportWebp;
}
//跳转登录时去掉url上的user_id、xyy和is_login
function _clearUlrData(cbUrl: string) {
  if (cbUrl.indexOf("?") == -1) return encodeURIComponent(cbUrl);
  let [url, query] = cbUrl.split("?");
  let arr = ["user_id", "xyy", "is_login"];
  for (let i = 0; i < arr.length; i++) {
    if (query.indexOf(arr[i]) > -1) {
      let reg = new RegExp("(^|&)" + arr[i] + "=[^&]*", "g");
      query = query.replace(reg, "");
    }
  }
  if (query) {
    if (query.indexOf("&") === 0) {
      //最开始一位是&时去掉
      query = query.slice(1);
    }
    url += "?" + query;
  }
  return encodeURIComponent(url);
}
function _getLocalStorage(name: string) {
  if (window.ydStorage) {
    return window.ydStorage.getItem(name);
  } else {
    let data = localStorage.getItem(name) || "";
    let obj: any = {};
    try {
      obj = JSON.parse(data);
    } catch (err) {
      return data;
    }
    return obj && obj.value ? obj.value : data;
  }
}
