if (typeof feeRateObject !== "undefined") {
  feeRateObject.feeRateSpecialHandle = function (subRate, value) {
    let result = {};
    if (subRate.name == "综合里程(km)" && value && value < 3) {
      //综合里程3km以内按3km算
      result.valueKey = "3";
      result.value = scMathUtil.roundForObj(value, getDecimal("feeRate")); //设置显示的节点值
    }
    if (subRate.name == "工地转移(km)" && value && value < 50) {
      //工地转移50km以内按50km算
      result.valueKey = "50";
      result.value = scMathUtil.roundForObj(value, getDecimal("feeRate")); //设置显示的节点值
    }
    if (subRate.name == "施工进出场(km)" && value && value < 5) {
      //施工进出场5km以内按5km算
      result.valueKey = "5";
      result.value = scMathUtil.roundForObj(value, getDecimal("feeRate")); //设置显示的节点值
    }
    return result;
  };
}

// 清单基数
const littleFixNames = ["小修", "养护检查预算", "日常养护预算"];
const progression = ["养护管理单位项目管理费", "工程监理费", "设计文件审查费"];
const deficiency = { 工程监理费: 10000, 设计文件审查费: 10000 };
if (typeof baseFigureMap !== "undefined") {
  const { fixedFlag } = commonConstants;
  const budgetMap = {
    // 显示：除清单固定类别是“建筑安装工程费”的以外部分可显示。
    建筑安装工程费: {
      base: "JZAZGCF",
      fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
      filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
      pick: false,
    },
    // 显示：除清单固定类别是“建筑安装工程费”的以外部分可显示
    "建筑安装工程费(不含设备费)": {
      base: "JZAZGCFBHSB",
      fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
      filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
      pick: false,
    },
    // 显示：除清单固定类别是“建筑安装工程费”的以外部分可显示
    定额建筑安装工程费: {
      base: "DEJZAZGCF",
      fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
      filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
      pick: false,
    },
    // 显示：仅清单固定类别是“养护工程其他费用”部分可显示。
    养护管理单位项目管理费: {
      isProgressive: true,
      base: "YHGLDWXMGLF",
      fixedFlag: null,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    信息化费: {
      isProgressive: true,
      base: "YHXMXXHF",
      fixedFlag: null,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    工程监理费: {
      isProgressive: true,
      base: "GCJLF",
      fixedFlag: null,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    "工程监理费(未实行社会监理)": {
      isProgressive: true,
      base: "GCJLFWSXSHJL",
      fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    "设计文件审查费(一阶段)": {
      isProgressive: true,
      base: "SJWJSCFYJD",
      fixedFlag: null,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    "设计文件审查费(二阶段)": {
      isProgressive: true,
      base: "SJWJSCFEJD",
      fixedFlag: null,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    工程设计费: {
      isProgressive: true,
      base: "GCSJF",
      fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
      filter: [fixedFlag.MAINTENANCE_EXPENSES],
      pick: true,
    },
    施工场地建设费: {
      isProgressive: true,
      base: "SGCDJSF",
      fixedFlag: null,
      filter: [fixedFlag.CONSTRUCTION_PLANT_COST],
      pick: true,
    },
    "建筑安装工程费(不含安全生产费)": {
      base: "JZAZGCFBHAQSCF",
      fixedFlag: null,
      filter: [fixedFlag.SAFE_COST],
      pick: true,
    },
    "定额建筑安装工程费(不含专项费用)": {
      base: "DEJZAZGCFBHZXF",
      fixedFlag: null,
      filter: [fixedFlag.SPECIAL_COST],
      pick: true,
    },
    // 显示：除清单固定类别是“一二三四部分合计”的以外部分可显示。
    /*     一二三四部分合计: {
      base: "YESSBFHJ",
      fixedFlag: fixedFlag.ONE_TO_FOUR_TOTAL,
      filter: [fixedFlag.ONE_TO_FOUR_TOTAL],
      pick: false,
    }, */
    // 显示：仅“价差预备费”可显示
    价差预备费: {
      base: "JCYBF",
      fixedFlag: null,
      filter: [fixedFlag.SPREAD_BUDGET_FEE],
      pick: true,
    },
  };
  const boqMap = {
    //仅允许用于固定类别是“第100章至700章清单”以外的清单
    专项暂定合计: {
      base: "ZXZDHJ",
      fixedFlag: null,
      filter: [fixedFlag.ONE_SEVEN_BILLS],
      pick: false,
    },
    /*
     *  清单固定行[第100章至700章清单]下的[第100章清单]需要允许清单可使用基数{100章以外合计}
     *  因此{100章以外合计}不设置关联的清单固定行
     * */
    //仅允许用于固定类别为“100章清单”引用
    "100章以外清单合计": {
      base: "YBZYHQDHJ",
      fixedFlag: null,
      filter: [fixedFlag.ONE_HUNDRED_BILLS],
      pick: true,
    },
  };
  baseFigureMap.budget = budgetMap;
  baseFigureMap.boq = boqMap;
}

// 是否是小修
const isLittleFix = (engName) => {
  return littleFixNames.some((name) => new RegExp(name).test(engName));
};

if (typeof baseFigureTemplate !== "undefined") {
  const { fixedFlag } = commonConstants;
  baseFigureTemplate.budget = {
    // 建筑安装工程费 算法：取清单固定类别是“建筑安装工程费”的建安费。
    JZAZGCF(tender) {
      return cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
    },
    // 建筑安装工程费(不含设备费)算法：取清单固定类别是“建筑安装工程费”的金额 - {设备费}。
    JZAZGCFBHSB(tender) {
      // const engName = projectObj.project.property.engineeringName;
      // if (isLittleFix(engName)) {
      // 小修的没有设备购置固定行
      const baseFee = cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
      const fixedNode = projectObj.project.mainTree.roots.find((node) => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, "common");
      return (baseFee - equipmentFee).toDecimal(decimalObj.bills.totalPrice);
      // } else {
      //   return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.EQUIPMENT_ACQUISITION_FEE], tender, "common");
      // }
    },
    // 建筑安装工程费(不含安全生产费)
    JZAZGCFBHAQSCF(tender) {
      return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.SAFE_COST], tender, "common");
    },
    // 定额建筑安装工程费 算法：取清单固定类别是“建筑安装工程费”的定额建安费(其中定额设备费按40%计算)。
    DEJZAZGCF(tender) {
      // const engName = projectObj.project.property.engineeringName;
      const feeField = "rationCommon";
      // if (isLittleFix(engName)) {
      // 小修的没有设备购置固定行
      const baseFee = cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, feeField);
      const fixedNode = projectObj.project.mainTree.roots.find((node) => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, "equipment");
      return (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.bills.totalPrice);
      // } else {
      //   const deductFlags = [fixedFlag.EQUIPMENT_ACQUISITION_FEE];
      //   //建安费扣除定额设备购置费
      //   const afterDeductFee = cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, deductFlags, tender, feeField, false);
      //   //定额设备购置费
      //   const equipmentAcFee = cbTools.getBaseFee(deductFlags[0], tender, "equipment");
      //   const equipmentAcTaxFee = cbTools.getBaseFee(deductFlags[0], tender, "tax");
      //   return (afterDeductFee + equipmentAcFee * 0.4 + equipmentAcTaxFee).toDecimal(decimalObj.bills.totalPrice);
      // }
    },
    DEJZAZGCFBHZXF(tender) {
      // 定额建筑安装工程费(不含专项费用)
      return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.SPECIAL_COST], tender, "rationCommon", true);
    },
    // 设备费 算法：取清单固定类别是“设备购置”的建安费
    SBF(tender) {
      return cbTools.getBaseFee(fixedFlag.EQUIPMENT_ACQUISITION_FEE, tender, "common");
    },
    // 设备费 算法：取清单固定类别是“设备购置”的定额建安费
    DESBF(tender) {
      return cbTools.getBaseFee(fixedFlag.EQUIPMENT_ACQUISITION_FEE, tender, "rationCommon");
    },
    // 养护工程费 算法：取清单固定类别是“养护工程费”的金额。
    YHGCF(tender) {
      return cbTools.getBaseFee(fixedFlag.MAINTENANCE_FEE, tender, "common");
    },
    // 定额养护工程费 算法：取清单固定类别是“养护工程费”的定额建安费(其中定额设备费按40%计算)。
    DEYHGCF(tender) {
      const feeField = "rationCommon";
      const baseFee = cbTools.getBaseFee(fixedFlag.MAINTENANCE_FEE, tender, feeField);
      const fixedNode = projectObj.project.mainTree.items.find((node) => node.getFlag() === fixedFlag.MAINTENANCE_FEE);
      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, "equipment");
      return (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.bills.totalPrice);
    },
    // 养护管理单位项目管理费 算法：以{定额建筑安装工程费}为基数，采用累进办法计算。。
    YHGLDWXMGLF(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(
        baseFee,
        "养护管理单位项目管理费",
        projectObj.project.property.progressiveInterval,
        decimalObj.bills.totalPrice,
        deficiency
      );
    },
    // 工程监理费 算法：以{定额建筑安装工程费}为基数，采用累进办法计算
    GCJLF(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (baseFee === 0) return 0;
      if (baseFee > 0 && baseFee < 1000000) return 50000;
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(baseFee, "工程监理费", projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
    },
    GCJLFWSXSHJL(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (baseFee === 0) return 0;
      if (baseFee > 0 && baseFee < 1000000) return 50000;
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(
        baseFee,
        "工程监理费(未实行社会监理)",
        projectObj.project.property.progressiveInterval,
        decimalObj.bills.totalPrice,
        deficiency
      );
    },
    // {信息化费} 算法：以{定额建筑安装工程费}为基数，采用累进办法计算。仅清单固定类别是“养护工程其他费”部分可显示。(计算结果去掉不足10000元时按10000元计取)
    YHXMXXHF(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (baseFee === 0) return 0;
      if (baseFee > 0 && baseFee < 2000000) return 100000;
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(baseFee, "信息化费", projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
    },
    // 施工场地建设费 算法：以{定额养护工程费}为基数，采用累进办法计算
    SGCDJSF(tender) {
      // const baseFee = this["DEJZAZGCFBHZXF"](tender);
      const baseFee = this["DEYHGCF"](tender);
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(
        baseFee,
        "施工场地建设费",
        projectObj.project.property.progressiveInterval,
        decimalObj.bills.totalPrice,
        deficiency
      );
    },
    // 一二三四部分合计 算法：取清单固定类别是“一二三四部分合计”的金额
    YESSBFHJ(tender) {
      return cbTools.getBaseFee(fixedFlag.ONE_TO_FOUR_TOTAL, tender, "common");
    },
    /*  价差预备费 算法：以建筑安装工程费为基数，按设计文件编制年始至养护项目工程竣工年终的年数和年工程造价增涨率计算。
            价差预备费 P * [(1+i)^(n-1) -1]
            P——建筑安装工程费总额（元）；
            i——年工程造价增涨率（%）；
            n——设计文件编制年至养护项目开工年+养护项目建设期限（年）。
        */
    JCYBF(tender) {
      //建筑安装工程费作为基数
      const installFee = this["JZAZGCF"](tender);
      //年造价增涨
      const costGrowthRate = calcBase.project.property.costGrowthRate ? calcBase.project.property.costGrowthRate : 0;
      //增涨计费年限
      const growthPeriod = projectObj.project.property.growthPeriod ? calcBase.project.property.growthPeriod : 0;
      //= P * [(1+i)^(n-1) -1]
      return (installFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
    },
    // 设计文件审查费(一阶段) 算法：以{定额建筑安装工程费}为基数，采用累进办法计算。
    // 设计文件审查费（一阶段）和 设计文件审查费（二阶段）两个基数计算后金额不满5000元均应按5000元计。
    SJWJSCFYJD(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (baseFee === 0) return 0;
      if (baseFee > 0 && baseFee < 500000) return 5000;
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(
        baseFee,
        "设计文件审查费(一阶段)",
        projectObj.project.property.progressiveInterval,
        decimalObj.bills.totalPrice,
        deficiency
      );
    },
    SJWJSCFEJD(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (baseFee === 0) return 0;
      if (baseFee > 0 && baseFee < 500000) return 5000;
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(
        baseFee,
        "设计文件审查费(二阶段)",
        projectObj.project.property.progressiveInterval,
        decimalObj.bills.totalPrice,
        deficiency
      );
    },
    GCSJF(tender) {
      const baseFee = this["DEJZAZGCF"](tender);
      if (baseFee === 0) return 0;
      if (baseFee > 0 && baseFee < 500000) return 35000;
      if (!tender) {
        calcBase.baseProgressiveFee = baseFee;
      }
      return calculateUtil.getProgressiveFee(baseFee, "工程设计费", projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
    },
  };

  baseFigureTemplate.boq = {
    //{专项暂定合计}
    // 第100章至700章清单行的暂估合价
    ZXZDHJ: function (tender) {
      return cbTools.getBaseFee(calcBase.fixedFlag.ONE_SEVEN_BILLS, tender, "estimate");
    },
    //{100章以外清单合计}
    // 取清单固定清单[第100章至700章清单]的金额，但扣除清单100章下的金额。
    // 如果是固定清单[第100章至700章清单]下100章以外清单引用此基数，要排除自身(目前只允许100章的清单使用，所以暂时不需要此判断)
    YBZYHQDHJ: function (tender) {
      let oneToSeven = cbTools.findNodeByFlag(fixedFlag.ONE_SEVEN_BILLS);
      if (!oneToSeven) {
        return 0;
      }
      //100-700章固定节点的所有子节点
      let allChildren = [];
      function getChildren(nodes) {
        allChildren = allChildren.concat(nodes);
        for (let node of nodes) {
          if (node.children.length > 0) {
            getChildren(node.children);
          }
        }
      }
      getChildren(oneToSeven.children);
      //扣除的节点：100章的节点[100-200)
      let deductNodes = allChildren.filter(cbTools.withingOneHundred);
      //计算金额
      let fullFeeField = tender ? "common.tenderTotalFee" : "common.totalFee";
      return projectObj.project.calcProgram.getTotalFee([oneToSeven], deductNodes, fullFeeField).toDecimal(decimalObj.bills.totalPrice);
    },
  };
}

if (typeof module !== "undefined") {
  // 甘肃养护，项目属性-小数位数，费率小数位数默认为2。
  const defaultDecimal = {
    bills: { unitPrice: 2, totalPrice: 0 },
    ration: { quantity: 3, unitPrice: 2, totalPrice: 0 },
    glj: { quantity: 3, unitPriceHasMix: 2, unitPrice: 2 },
    feeRate: 4,
    quantity_detail: 4,
    material: 5, //三材系数
    process: 6,
    marketPriceProcess: 2,
    temProcess: 6,
  };

  module.exports = {
    progression,
    deficiency,
    defaultDecimal,
  };
}
// 不显示但可的基数
const invisibleBases = ["设备费", "定额设备费"];

if (typeof projectObj !== "undefined") {
  projectObj.isInsertEquipmentVisable = function (selected) {
    if (projectObj.project.property.valuationType !== "ration") {
      //预算项目中，右键“插入设备”，仅在第一部分中显示。
      return projectObj.project.Bills.isConstructionInstall(selected);
    }
    return true;
  };
}
