<!--
 * @Author: baozhoutao@steedos.com
 * @Date: 2022-06-02 17:45:15
 * @LastEditors: baozhoutao@steedos.com
 * @LastEditTime: 2023-07-10 17:19:08
 * @Description:
-->
<html>

<head>
  <script src="/unpkg.com/@steedos-builder/fiddle@0.0.5/dist/builder-fiddle.umd.js"></script>
  <script src="/unpkg.com/axios@0.26.1/dist/axios.min.js"></script>
</head>

<body>
  <builder-fiddle host="<%=builderHost%>"></builder-fiddle>
  <script>

    const settings = {
      assetUrls: "<%=assetUrls%>",
      rootUrl: "<%=rootUrl%>",
      userId: "<%=userId%>",
      tenantId: "<%=tenantId%>",
      authToken: "<%=authToken%>",
      id: "<%=id%>",
      pageId: "<%=id%>",
      formId: "<%=formId%>",
      messageOnly: true,
      hiddenDeploy: true
    };

    let comp = document.querySelector("builder-fiddle");

    const getArgumentsList = (func)=>{
      let funcString;
      if (typeof func === 'function') {
        funcString = func.toString();
      } else {
        funcString = func;
      }
      const regExp = /function\s*\w*\(([\s\S]*?)\)/;
      if (regExp.test(funcString)) {
        const argList = RegExp.$1.split(',');
        return argList.map(arg => arg.replace(/\s/g, ''));
      } else {
        return [];
      }
    }

    const loadPage = async () => {
      //settings结果集同样加入formId
      const { assetUrls, rootUrl, userId, tenantId, authToken, id, formId } = settings;

      // 如果传入 steedos rooturl
      if (rootUrl && !authToken) return;

      const initialContent = {
        type: "page",
        bodyClassName: 'p-0',
        regions: [
          "body"
        ]
      };

      if (id) {
        const result = await axios.post(
          `${rootUrl}/graphql`,
          {
            //forms作为对象
            query: `
                  {
                    record:forms__findOne(id: "${formId}"){
                      _id,
                      amis_schema,
                      current
                    }
                  }
                `
          },
          {
            withCredentials: true,
            headers: { Authorization: `Bearer ${tenantId},${authToken}` },
          }
        );
        if (result?.data?.data?.record) {
          let schema = JSON.parse(result.data.data.record.amis_schema);


          if (!schema) {
            //进if说明schema字段为空 说明为旧表单 对schema重新赋值
            schema =
            {
              type: "form",
              id: "instanceForm",
              name: "instanceForm",
              body: [],
              "actions": [],
              "wrapWithPanel": false
            }
            if(result.data.data.record.current.fields){
              for (let i = 0; i < result.data.data.record.current.fields.length; i++) {
                const temp = await getFieldEditTpl(result.data.data.record.current.fields[i]);
                if (temp) {
                  schema.body.push(temp);
                }

              }
            }
          }

          let objectName = result.data.object;
          let pageType = result.data.type;
          if (typeof schema === "string") {
            schema = JSON.parse(schema);
          }

          if (!schema.data) {
            schema.data = {};
          }

          if (!schema.data.context) {
            schema.data.context = {};
          }

          schema.data.app_id = '';
          schema.data.tab_id = '';
          schema.data.object_name = '';
          schema.data.dataComponentId = '';
          schema.data.record_id = '';
          schema.data.record = {};
          schema.data.permissions = {};

          schema.data.context.rootUrl = rootUrl;
          schema.data.context.tenantId = tenantId;
          schema.data.context.userId = userId;
          schema.data.context.authToken = authToken;
          return schema || initialContent
        }
      } else {
        return initialContent
      }
    };

    const getSelectOptions = (field) => {
      const options = [];
      // each(field.options.split("\n"), (item) => {
      //   var foo = item.split(":");
      //   if (foo.length == 2) {
      //     options.push({ label: foo[0], value: foo[1] });
      //   } else {
      //     options.push({ label: item, value: item });
      //   }
      // });

      const splitItem = field.options.split("\n");
      splitItem.forEach(item => {
        var foo = item.split(":");
        if (foo.length == 2) {
          options.push({ label: foo[0], value: foo[1] });
        } else {
          options.push({ label: item, value: item });
        }
      });

      return options;
    };

    const startsWith = (url, str) => {

      let flag = false
      if(url.substr(0,4) === str){
        flag = true
      }else{
        flag = false
      }
      return flag

    }

    //将原数据字段转换为amis字段
    const getFieldEditTpl = async (field) => {
      const tpl = {
        label: field.name,
        name: field.code,
        required: field.is_required,
		multiple: field.is_multiselect,
        className: (field.is_wide ? 'is_wide' : '') +
		(field.is_list_display ? ' is_list_display' : '') +
		(field.is_searchable ? ' is_searchable' : '')
      };
      switch (field.type) {
        case "input":
          if (field.is_textarea) {
            tpl.type = "textarea";
          } else {
            tpl.type = "input-text";
          }
          break;
        case "number":
          tpl.type = "input-number";
          tpl.precision=2
          break;
        case "date":
          tpl.type = "input-date";
          tpl.inputFormat = "YYYY-MM-DD";
          tpl.format = 'YYYY-MM-DDT00:00:00.000[Z]';
          break;
        case "dateTime":
          tpl.type = "input-datetime";
          tpl.inputFormat = "YYYY-MM-DD HH:mm";
          tpl.format = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
          break;
        case "checkbox":
		  tpl.type = "checkbox";
          break;

        case "email":
          tpl.type = "input-email";
          tpl.validations = {
            isEmail: true,
          };
          break;
        case "url":
          tpl.type = "input-url";
          tpl.validations = {
            isUrl: true,
          };
          break;
        case "password":
          tpl.type = "input-password";
          tpl.showCounter = true;
          break;
        case "select":
          tpl.type = "select";
          tpl.options = getSelectOptions(field);
          break;

        case "user":
          const useTpl = {
            "type": "steedos-field",
            "id": `u:${field.code}`,
            "config": {
              name: field.code,
              label: field.name,
              reference_to: "space_users",
              reference_to_field: 'user',
              multiple: field.is_multiselect,
              type: "lookup"
            },
          }
          // const useTpl = await lookupToAmis(
          // {
          //   name: field.code,
          //   label: field.name,
          //   reference_to: "space_users",
          //   reference_to_field: 'user',
          //   multiple: field.is_multiselect,
          // },
          //   false,
          //   {}
          // );
          Object.assign(tpl, useTpl);
          break;

        case "group":
          const orgTpl = {
            "type": "steedos-field",
            "id": `u:${field.code}`,
            "config": {
              name: field.code,
              label: field.name,
              reference_to: "organizations",
              multiple: field.is_multiselect,
              type: "lookup"
            }
          }

          // const orgTpl = await lookupToAmis(
          // {
          //   name: field.code,
          //   label: field.name,
          //   reference_to: "organizations",
          //   multiple: field.is_multiselect,
          // },
          //   false,
          //   {}
          // );
          Object.assign(tpl, orgTpl);
          break;
        case "radio":
          tpl.type = "radios";
          tpl.options = getSelectOptions(field);
          break;
        case "multiSelect":
          tpl.type = "checkboxes";
          tpl.options = getSelectOptions(field);
          break;
        case "odata":
		      const argsName = getArgumentsList(field.filters);
          var labelField = field.formula.substr(1, field.formula.length - 2);
          labelField = labelField.substr(labelField.indexOf(".") + 1);
		  // 加入odata标签以示区别 把field-老表单设计器的元素加入
          tpl.type = "select";
          tpl.description = field.description
          tpl.detail_url = field.detail_url
          tpl.filters = field.filters
          tpl.formula = field.formula
          tpl.is_list_display = field.is_list_display
          tpl.is_multiselect = field.is_multiselect
          tpl.is_required = field.is_required
          tpl.is_searchable = field.is_searchable
          tpl.is_wide = field.is_wide
          tpl.search_field = field.search_field
          tpl._id = field._id
          // tpl.labelField = labelField;
          // tpl.valueField = "_value";
          tpl.source = {
            //判断该field.url是否为http开头
            url: startsWith(field.url, "http")
              ? field.url
              : `\${context.rootUrl}${field.url}`,
            method: "get",
            dataType: "json",
            headers: {
              Authorization: "Bearer ${context.tenantId},${context.authToken}",
            },
            adaptor: `
              payload.data = {
                options: _.map(payload.value, (item)=>{
                  const value = item;
                  item["@label"] = item["${labelField}"]
                  delete item['@odata.editLink'];
                  delete item['@odata.etag'];
                  delete item['@odata.id'];
                  return {
                    label: item["@label"],
                    value: value
                  }
                })
              }
              return payload;
            `,
            requestAdaptor: `
              const filters = ${_.replace(field.filters, /_.pluck/g, '_.map')};
              const url = ${field.url}
              if(filters){
                console.log('filters', filters);
                const joinKey = field.url.indexOf('?') > 0 ? '&' : '?';
                if(filters.startsWith('function(') || filters.startsWith('function (')){
                  const argsName = ${JSON.stringify(argsName)};
                  const fun = eval('_fun='+filters);
                  const funArgs = [];
                  for(const item of argsName){
                    funArgs.push(context[item])
                  }
                  api.url = url + joinKey + "$filter=" + fun.apply({}, funArgs)
                }else{
                  api.url = url + joinKey + "$filter=" + filters
                }
              }else{
                api.url = url  
              }
              api.query = {};
              return api;
            `,
            trackExpression: _.join(_.map(argsName, (item)=>{return `\${${item}|json}`}), '-')
          };
          break;
        case "html":
          if (tpl.disabled) {
            tpl.type = 'html';
          } else {
            tpl.type = "input-rich-text";
          }
          break;
        case "table":
          tpl.type = "input-table";
          tpl.addable = field.permission === "editable";
          tpl.editable = tpl.addable;
          tpl.copyable = tpl.addable;
          tpl.columns = [];
          for (const sField of field.fields) {
            if (sField.type != "hidden") {
              sField.permission = field.permission
              const column = await getFieldEditTpl(sField, true);
              tpl.columns.push(column);
            }
          }
          break;
        case "section":
          tpl.type = "fieldset";
		  tpl.title = field.name;
		  tpl.collapsable = true;
		  tpl.body = []
		  if(field.fields){
			for(let i = 0;i<field.fields.length;i++){
				let fieldsItem = await getFieldEditTpl(field.fields[i], true)
				tpl.body.push(fieldsItem)
			}
		  }
          break;
        default:
          break;
      }
        return tpl

    }



    const savePage = async (data) => {
      const { rootUrl, userId, tenantId, authToken, id, formId } = settings;
      if (!id) {
        return;
      }

      // 保存schema时,清理context下的认证信息
      const schema = JSON.parse(
        JSON.stringify(data.data.AmisSchema, null, 4)
      );
      if (schema.data && typeof schema.data.context === 'object') {
        delete schema.data.context.userId;
        delete schema.data.context.tenantId;
        delete schema.data.context.authToken;
        delete schema.data.context.user;
      }
      return await axios.post(
        `${rootUrl}/graphql`,
        {
          query: `
                mutation{
                  forms__update(id: "${formId}", doc: {amis_schema: ${JSON.stringify(JSON.stringify(schema, null, 4))}}){_id}
                }
              `,
        },
        {
          withCredentials: true,
          headers: { Authorization: `Bearer ${tenantId},${authToken}` },
        }
      )
        .catch(function (error) {
          // handle error
          console.log(error);
        });
    };

    const deployPageVersion = async () => {

    };
    window.addEventListener('message', function (event) {
      const { data } = event;
      if (data) {
        if (data.type === 'builder.loadContent') {
          loadPage().then((content) => {
            comp.messageFrame('builder.contentChanged', { AmisSchema: content })
          })
        }
        if (data.type === 'builder.saveContent') {
          savePage(data.data).then(() => {
            comp.messageFrame('builder.contentSaved')
          })
        }
        if (data.type === "builder.deployContent") {
          deployPageVersion().then(() => {
            comp.messageFrame('builder.contentDeployed')
          })
        }
      }
    })

    comp.settings = settings;
  </script>
</body>

</html>
